喝岖 发表于 2026-2-9 17:05:00

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

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

环形缓冲区存储结构体

#define RX_RING_SIZE 256typedef struct {    uint8_t buf;// 实际存数据    volatile uint16_t head;   // 写指针(中断在改),(volatile)防止编译器优化导致 中断/主循环不同步    volatile uint16_t tail;   // 读指针(主循环在改)} ring_buf_t;初始化串口

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); }配置结构体

ring_buf_t rx_ring3 = {0, 0, 0};串口接收中断(基础)

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 = ch;         rx_ring3.head = next;       }       USART_ClearITPendingBit(USART3, USART_IT_RXNE);   }}解析函数(放循环,阻塞等待)

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;    // 只要缓冲区里有数据,就一直处理    while (rx_ring3.head != rx_ring3.tail)   {      // 1. 从环形缓冲区读取一个字节          uint8_t ch = rx_ring3.buf;      rx_ring3.tail = (rx_ring3.tail + 1) % RX_RING_SIZE;      switch (state_r4)      {            case 0: // 等待帧头                if (ch == 0x2A)                {                  frame_buf = ch;                  count_r4 = 1;                  state_r4 = 1;                }                break;            case 1: // 校验 CMD                if (ch == 0x11)                {                  frame_buf = ch;                  state_r4 = 2;                }                else                {                  state_r4 = 0;   // CMD 不匹配,丢弃                }                break;            case 2: // 校验 LEN                if (ch == 0x04)                {                  data_len_r4 = ch;                  frame_buf = ch;                  state_r4 = 3;                }                else                {                  state_r4 = 0;   // LEN 不匹配,丢弃                }                break;            case 3: // 接收 DATA(4字节) + CRC                frame_buf = ch;                // 1(2E) + 1(CMD) + 1(LEN) + 4(DATA) + 1(CRC) = 8                if (count_r4 >= 8)                {                  /* ========= 业务判断 ========= */                  uint8_t byte6 = frame_buf; // 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;      }    }}清除缓存区

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();// 重新使能中断}
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

计海龄 发表于 2026-2-16 23:45:05

感谢分享

里豳朝 发表于 2026-3-7 06:07:40

热心回复!

雌鲳签 发表于 2026-3-8 20:54:14

感谢分享,下载保存了,貌似很强大

纪晴丽 发表于 2026-3-9 10:27:07

不错,里面软件多更新就更好了

岑韬哎 发表于 2026-3-11 03:30:42

这个有用。

师佳思 发表于 2026-3-11 09:07:04

喜欢鼓捣这些软件,现在用得少,谢谢分享!
页: [1]
查看完整版本: 串口接收,环形缓冲区+解析