串口接收,环形缓冲区+解析
环形缓冲区存储结构体
- #define RX_RING_SIZE 256typedef struct { uint8_t buf[RX_RING_SIZE]; // 实际存数据 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[rx_ring3.head] = 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[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; } }}
复制代码 清除缓存区
- 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(); // 重新使能中断}
复制代码 来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |