找回密码
 立即注册
首页 业界区 安全 串口接收,环形缓冲区+解析

串口接收,环形缓冲区+解析

喝岖 2026-2-9 17:05:00
串口接收,环形缓冲区+解析

环形缓冲区存储结构体
  1. #define RX_RING_SIZE 256typedef struct {    uint8_t buf[RX_RING_SIZE];  // 实际存数据    volatile uint16_t head;     // 写指针(中断在改),(volatile)防止编译器优化导致 中断/主循环不同步    volatile uint16_t tail;     // 读指针(主循环在改)} ring_buf_t;
复制代码
初始化串口
  1. void USART3_IRQHandler(void);//提前声明串口接收中断void uart3_Init(u32 baud){            GPIO_InitTypeDef GPIO_InitStructure;  USART_InitTypeDef USART_InitStructure;  NVIC_InitTypeDef NVIC_InitStruct;    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);                           RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);                            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;                           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                                  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                  GPIO_Init(GPIOB,&GPIO_InitStructure);                                       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;                           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                                  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                  GPIO_Init(GPIOB,&GPIO_InitStructure);     USART_InitStructure.USART_BaudRate = baud;                                  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(USART3, &USART_InitStructure);             NVIC_InitStruct.NVIC_IRQChannel = USART3_IRQn;  NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;  NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;  NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;  NVIC_Init(&NVIC_InitStruct);//配置NVIC    USART_Cmd(USART3, ENABLE);                                              USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);          USART_ITConfig(USART3, USART_IT_ERR, ENABLE);    BSP_IntVectSet(BSP_INT_ID_USART3,USART3_IRQHandler);  BSP_IntEn(BSP_INT_ID_USART3); }
复制代码
配置结构体
  1. ring_buf_t rx_ring3 = {0, 0, 0};
复制代码
串口接收中断(基础)
  1. void USART3_IRQHandler(void){   if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) {       uint8_t ch = (uint8_t)USART_ReceiveData(USART3);       uint16_t next = (rx_ring3.head + 1) % RX_RING_SIZE;       // 如果缓冲区没满,存入 数据       if (next != rx_ring3.tail) {           rx_ring3.buf[rx_ring3.head] = ch;           rx_ring3.head = next;       }       USART_ClearITPendingBit(USART3, USART_IT_RXNE);   }}
复制代码
解析函数(放循环,阻塞等待)
  1. void Extract_select_Data(void)//判断数据包{    static uint8_t state_r4 = 0;    static uint8_t data_len_r4 = 0;    static uint8_t count_r4 = 0;    static uint8_t frame_buf[32];    // 只要缓冲区里有数据,就一直处理    while (rx_ring3.head != rx_ring3.tail)     {        // 1. 从环形缓冲区读取一个字节          uint8_t ch = rx_ring3.buf[rx_ring3.tail];        rx_ring3.tail = (rx_ring3.tail + 1) % RX_RING_SIZE;        switch (state_r4)        {            case 0: // 等待帧头                if (ch == 0x2A)                {                    frame_buf[0] = ch;                    count_r4 = 1;                    state_r4 = 1;                }                break;            case 1: // 校验 CMD                if (ch == 0x11)                {                    frame_buf[count_r4++] = ch;                    state_r4 = 2;                }                else                {                    state_r4 = 0;   // CMD 不匹配,丢弃                }                break;            case 2: // 校验 LEN                if (ch == 0x04)                {                    data_len_r4 = ch;                    frame_buf[count_r4++] = ch;                    state_r4 = 3;                }                else                {                    state_r4 = 0;   // LEN 不匹配,丢弃                }                break;            case 3: // 接收 DATA(4字节) + CRC                frame_buf[count_r4++] = ch;                // 1(2E) + 1(CMD) + 1(LEN) + 4(DATA) + 1(CRC) = 8                if (count_r4 >= 8)                {                    /* ========= 业务判断 ========= */                    uint8_t byte6 = frame_buf[5]; // DATA2                    if (byte6 & 0x04)   // bit2 = 1                    {                        select_bit2_flag = 1;//解析结果                        BLE_TO_MCU_OK_FLAG=1;                    }                    else                    {                        BLE_TO_MCU_OK_FLAG=0;                        select_bit2_flag = 0;                    }                    /* ============================ */                    state_r4 = 0;   // 准备下一帧                }                break;            default:                state_r4 = 0;                break;        }    }}
复制代码
清除缓存区
  1. void RingBuf3_ClearAndResetParser(void){//    __disable_irq();  // 关中断,保证原子性    // 1. 清空环形缓冲区数据    memset(rx_ring3.buf, 0, RX_RING_SIZE);    // 2. 重置 head/tail    rx_ring3.head = 0;    rx_ring3.tail = 0;    // 3. 重置解析器状态    state_r3 = 0;    count_r3 = 0;    data_len_r3 = 0;    pkg_ready = 0;//    __enable_irq();  // 重新使能中断}
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册