STM32-使用串口空闲中断,实现串口不定长接收

示例代码是直接操作寄存器的
核心思路很简单:
1. 接收到消息后,打开串口总线空闲中断:USART_CR1寄存器中IDLE写1
2. 总线进入空闲中断后,关闭空闲中断:USART_CR1寄存器中IDLE写0
3. 根据状态寄存器,判断中断类型。

示例代码如下:

#include "myusart2.h"
#include "string.h"

u8 usart2_rec_buff[usart2_rec_len];
u8 usart2_rec_flag=0;              //数据达到指定长度置1,接收错误或主函数处理完成置0
u16 usart2_rec_count=0;             //接收数量,接收完成后置0,接收报错置零。

char usart2_rec_too_long[]="too long!";
   
void myusart2_init(u32 clk,u32 baudrate)   //串口3
{
    u32 temp=0;
    RCC->APB1ENR |=1<<18;     //使能串口时钟   APB1
    RCC->APB2ENR |=1<<3;      //使能IO口时钟   APB2 GPIOB  PB10 PB11
    
    sys_gpio_set(GPIOB, SYS_GPIO_PIN10,SYS_GPIO_MODE_AF, SYS_GPIO_OTYPE_PP, SYS_GPIO_SPEED_HIGH, SYS_GPIO_PUPD_PU);  ///USARTx_TX
    sys_gpio_set(GPIOB, SYS_GPIO_PIN11,SYS_GPIO_MODE_IN, SYS_GPIO_OTYPE_PP, SYS_GPIO_SPEED_HIGH, SYS_GPIO_PUPD_PU);  //USARTx_RX
    
    temp = (clk * 1000000 + baudrate / 2) / baudrate;  /* 得到BRR, 采用四舍五入计算 */
    
    MYUSART2->BRR = temp;       // 波特率设置 
    MYUSART2->CR1 = 0;          // 清零CR1寄存器 
    MYUSART2->CR1 |= 0 << 12;   // M = 0, 1个起始位, 8个数据位, n个停止位(由USART_CR2 STOP[1:0]指定, 默认是0, 表示1个停止位) 
    MYUSART2->CR1 |= 1 << 3;    //TE = 1, 串口发送使能    
    MYUSART2->CR1 |= 1 << 2;    // RE = 1, 串口接收使能           
    MYUSART2->CR1 |= 1 << 5;    // RXNEIE = 1, 接收缓冲区非空中断使能 
    
    sys_nvic_init(2, 2, MYUSART2_IRQn, 2); //组2,优先级 2,2   
    MYUSART2->CR1 |= 1<<13;   //使能串口x
    
    MYUSART2->SR  &=~(1<<7);//解决单片机复位时,第一个字节发送丢失问题
}

/*中断函数*/
void MYUSART2_IRQHandler(void)    
{
    u8 rec_data;
    if (MYUSART2->SR & (1 << 5))                    //确认接收非空。数据放入缓存。如果超长,接收长度置0,接收报错。
    {                  
        rec_data=MYUSART2->DR;  
       
        if(usart2_rec_flag==0){
            MYUSART2->CR1 |= 1<<4;                //使能总线空闲中断
            
            if(usart2_rec_count<usart2_rec_len-1){
                usart2_rec_buff[usart2_rec_count]=rec_data;
                usart2_rec_count++;
            }else{
                usart2_rec_count=0;
                usart2_send_data(usart2_rec_too_long);
             }
        }
            
    }
    else if(MYUSART2->SR & (1<<4))                //如果总线空闲
    {
        usart2_rec_buff[usart2_rec_count]='\0';               //rec_buff添加字符串结束标志。这里是为了让接收的数据变成一个字符串。
        usart2_rec_flag=1;
        usart2_rec_count=0;
        
//        usart2_send_data((char *)usart2_rec_buff);        //返回接收的数据
 //       usart2_send_data("\r\n");
        MYUSART2->CR1 &= ~(1<<4);                  //关闭总线空闲中断
        MYUSART2->SR &=~(1<<4);
    }  
}


/*只发送字符串数据*/
void usart2_send_data(char *str)                
{   
    u8 len = strlen(str);
    for(u8 i=0;i<len;i++){
        MYUSART2->DR = str[i];  
        while ((MYUSART2->SR & 0X40) == 0);                           //等待发送结束 
    }      
}

posted on 2024-09-26 17:43  爱挖土的张三  阅读(661)  评论(0)    收藏  举报

导航