stm32 USART 配置
网上USART配置的博文很多,以前参考的时候也受益匪浅。最近在弄了一个蓝牙通讯控制的实验后就想回顾了一下自己的配置历程,来总结一个通俗易懂人性化的步骤讲解希望日后回顾和对初试者有帮助。(也可直接参考正点原子的例程)
中断通讯方式:
步骤一
:根据电路原理图连接电路,交叉接线:TX—-RX RX—TX ,同时接好Vcc和Gen
注意选择的是USART1 还是23…*。(配置类似)
步骤二
:这一步骤当时困扰了刚开始接触stm32的我,特别是引用其它固件库经常报错,但是代码也没有问题,各种未声明。原因是没有包涵该固件库的头文件(特别是直接用例程的工程加以修改的时候,无关头文件往往会被注释)
因此要在以下文件中去掉引用的库函数的头文件注释
步骤三
:接下来是关键的 1.使能时钟 2.使能IO口 3.使能中断了。这里是必须步骤 而且注意更改
USART口名字,这里以USART2为例,其余USART口更改名字即可
。
解释放在代码注释里,初学者可细看了解相关原理。
串口配置代码
:
void USART2_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; // 声明结构体 在接下来的函数中根据该结构体的参数 初始化需要的GPIOx(ABCDE)的寄存器
USART_InitTypeDef USART_InitStructure; // USART 同理
NVIC_InitTypeDef NVIC_InitStrue; // 中断 同理
/* 使能 USART2 时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); //USART2是挂在APB1低速时钟上的 这里要注意USART1是挂接在高速时钟APB2上的,修改名字即可
USART_DeInit(USART2); // 复位串口2
/* USART2 使用IO端口配置 根据电路图找到TX和RX的IO口*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //使能
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 即可输入也可输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据参数初始化GPIOA寄存器
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA寄存器
/* USART2 工作模式配置 */
USART_InitStructure.USART_BaudRate = 9600; //波特率设置:9600
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位数设置:8位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位设置:1位
USART_InitStructure.USART_Parity = USART_Parity_No ; //是否奇偶校验:无
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制模式设置:没有使能
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//接收与发送都使能
USART_Init(USART2, &USART_InitStructure); //根据结构体数据初始化USART2
/*串口中断使能*/
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//使能接收中断,在接受移位寄存器中有数据时产生 不能在一开始使能发送中断否则会循环在发送中断中
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
USART_Cmd(USART2, ENABLE);// USART2使能
/* 初始化中断 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//中断选择分组方式0 中断向量的分组和优先级可参考 后面博文或者上网搜查
NVIC_InitStrue.NVIC_IRQChannel=USART2_IRQn;
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=0; //抢占优先级
NVIC_InitStrue.NVIC_IRQChannelSubPriority=0; //响应优先级
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStrue);
}
串口Handler代码
:
u8 Counter=0;//接收字节计数
uint8_t rece_buffer[8]; //接收缓冲数组 存放接收数据
u8 clear;//这里是参考一篇博文的方法 清除寄存器残留的
void USART2_IRQHandler(void)
{
/*我只需要接收前八个 这里大家可写自己的接收格式 比如接收到空格为止 if(USART2->DR==‘\0’)*/
if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET)
{
if(Counter<8)
{
rece_buffer[Counter++]=USART2->DR;
}
}
if(USART_GetFlagStatus(USART2,USART_FLAG_IDLE)!=RESET)
{
/*中断结束清空寄存器 */
clear=USART2->SR;
clear=USART2->DR;
Counter=0;
}
}
步骤四
** fputc重写使用printf,让发送更方便**
重写并使用printf的方法有两种,这里只介绍一种,其余可参考正点原子例程或上网搜索。
加上代码
int fputc(int ch, FILE *f) //重写fputc函数 代码可放在usart.c或者主函数里
{
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); //等待上次发送结束
USART_SendData(USART2, (unsigned char)ch); //发送数据到串口
return ch;
}
之后直接使用函数即可
printf("Hello, world!\r\n");
最后的最后提醒一点,使用不同串口的注意修改串口名字,串口IO口名字,挂接的外部时钟名字 ,参考注释
内容粗糙,望能助人。
下一篇总结一下中断的使用
:
stm32入门篇–中断的初步认识及其优先级和分组
参考:
【1】
STM32的UART读写及printf打印