串口通信也称异步串行通信,是计算机、仪器仪表必备的一种简单通信接口,可以实现两个仪器或PC机之间近距离(15米)低速(100k)通信,采用三线方式(收,发,地线)的全双工方式进行。 串口通信要考虑几个重要参数:波特率、数据位、停止位和奇偶校验。

波特率:表示每秒钟传送的bit 的个数!常见波特率:2400/9600/115200

数据位:发送的数据位数,常用7位/9位/8位

停止位:用于表示单个包的最后一位。典型的值为1位/1.5 位/2 位

奇偶校验:串口通信中一种简单的数据检错方式,常用:奇校验/偶校验/无

现在我们看一下我手上的这块板子:stm32f091rc,一块具有8个串口的家伙,是很多其他的板子不具有的。

STM32CUbeMX配置串口功能_STM32CUbeMX配置串口功能


串口的结构框图如下:

STM32CUbeMX配置串口功能_STM32CUbeMX配置串口功能_02


下面就开始对USART进行学习。

寄存器:

STM32CUbeMX配置串口功能_数据_03


USART的寄存器包括3个控制寄存器(CR1,CR2,CR3),1个波特率寄存器(BRR),1个保护时间和预分频寄存器(GTPR),1个接收超时寄存器(RTOR),1个请求寄存器(RQR),1个中断和状态寄存器(ISR),1个中断标志清除寄存器(ICR),1个数据接收寄存器(RDR)和1和数据发送寄存器(TDR)。

对于USART发送和接收数据,数据手册上有如下配置步骤:

发送配置步骤:

1. 设置USART_CR1 的 M 位来定义字长。

2. 利用USART_BRR 寄存器选择希望的波特率。

3. 在USART_CR2 中设置停止位的位数。

4. 通过将USART_CR1 寄存器的 UE 位置 1 来使能 USART。

5. 如果采用多缓冲器通信,配置USART_CR3 中的 DMA 使能(DMAT)。 按多缓冲器通信中的描述配置DMA 寄存器。

6. 设置USART_CR1 中的 TE 位,发送一个空闲帧作为第一次数据发送。

7. 把要发送的数据写进 USART_TDR 寄存器 ( 此动作将清除 TXE 位 )。 在只有一个缓冲器的情况下,对每个待发送的数据重复步骤7。重复步骤 7 之前应等待TXE 变成1。

8. 在 USART_TDR 寄存器中写入最后一个数据字后,要等待 TC=1, 它表示最后一个数据帧的传输结束。 当需要关闭 USART 或需要进入停机模式之前,需要确认传输结束,避免破坏最后一次传输。

接收配置步骤:

1. 设置 USART_CR1 的 M 位来定义字长。

2. 利用波特率寄存器 USART_BRR 选择希望的波特率。

3. 在 USART_CR2 中设置停止位的位数。

4. 通过将 USART_CR1 寄存器的 UE 位置 1 来激活 USART。

5. 如果采用多缓冲器通信,配置 USART_CR3 中的 DMA 使能位 (DMAR)。 按多缓冲器通信

中的描述配置 DMA 寄存器。

6. 将 USART_CR1 的 RE 位置 1。 这将激活接收器,使它开始寻找起始位。

当一个字符被接收到时

● RXNE 位被置 1。 它表明移位寄存器的内容被转移到 RDR。 换句话说,数据已经被接收

并且可以被读出( 包括与之有关的错误标志)。

● 这时如果RXNEIE 位是1,将会引起中断请求。

● 在接收期间如果检测到帧错误,噪音或溢出错误,错误标志将被置起。 PE 标志也会和RXNE 一起被置1。

● 在多缓冲器通信时,RXNE 在每个字节接收后被置起,并由 DMA 对数据寄存器的读操作而清零。

● 在单缓冲器模式里,由软件读USART_RDR 寄存器完成对 RXNE 位清除。 RXNE 标志也可以通过对 USART_RQR 寄存器中的 RXFRQ 位写 1 来清除。 RXNE 位必须在下一字符接收结束前被清零,以避免溢出错误。


根据数据手册下面开始对其进行用库函数配置:

USART_InitStructure.USART_BaudRate = 115200;//设置波特率             USART_InitStructure.USART_WordLength =USART_WordLength_8b;//设置发送数据位
USART_InitStructure.USART_StopBits = USART_StopBits_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); 
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);  //开启中断           

USART_Cmd(USART2, ENABLE);//使能USART2
USART_ClearFlag(USART2, USART_FLAG_TC);

NVIC配置函数:

NVIC_InitTypeDef  NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;   
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;                 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

定义一个结构体变量,然后中断通道设置为串口1,优先级设置为0,在32个外设中断中是最高优先级。

中断内函数:

void USART2_IRQHandler(void)
{
         if( USART_GetITStatus( USART2, USART_IT_RXNE ) != RESET )        // 等待接收为空
        {   
                USART2->ICR |= 0x00000040;

                Uart_buf[0] = (unsigned char)(USART_ReceiveData(USART2));
              //  Uart_Put_Char(Uart_buf[0]);           
                                if( Uart_buf[0]==0xAA)
     {            
          Uart_buf[0]=0;
              GPIO_SetBits(GPIOA ,GPIO_Pin_5); //打开LED  
        printf("LED灯当前状态打开!\r\n");           
         } 
    if( Uart_buf[0]==0xBB)
     {
            Uart_buf[0]=0;      
              GPIO_ResetBits(GPIOA ,GPIO_Pin_5);    //关闭LED
              printf("LED灯当前状态关闭!\r\n");             
        }

同时,在程序调试过程中,我也遇到了一些麻烦,主要是printf函数的实现,最开始程序一直死在启动函数上,一直找不到原因,在学长的帮助下,在工程中添加了Retarget.c文件,使工程顺利运行。具体原因笔者还没搞清楚,后续会补上。

程序运行成功。在串口中断服务函数中,当串口接收到字符0xAA后,就打开LED灯,当接收到字符0xBB后,就关闭LED灯。实现了PC机上串口调试助手控制LED的开关。理解这个思路,当然可以控制MCU搭载或者驱动的任何负载,包括电机正转、反转,电磁阀开关,继电器开关,将串口助手集成到上位机软件中,就是一个完整的控制系统了。

此篇文章写的条例不太清晰,还望各位读者评论,大家一起学习!