简介
以USART2接受数据为例,环形队列可以循环使用缓冲区的空间,并且可以处理到每一帧数据,适合收发数据比较频繁的场景
正文
初始化后利用中断接受一字节数据
void USART2_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart2);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance ==USART2)
{
HAL_UART_Transmit(&huart2,&rx_data,1,0xffff); /*将接收到的数据发送出去*/
HAL_UART_Receive_IT(&huart2,&rx_data,1); /*接受下一字节数据*/
}
}
顺利的话我们就能把接受到的数据原封不动的发送出去,之后进行下一步
下面是串口通信使用环形队列的一种方式
usart.h文件
#define UART2_RX_BUF_SIZE 200
#define RING_BUF_DATA_TYPE unsigned char
uint8_t ring_buf_read(RING_BUF_DATA_TYPE* pdata);
usart.c文件
uint8_t rx_data = 0;
typedef struct {
RING_BUF_DATA_TYPE uart1_rx_data[UART2_RX_BUF_SIZE];
uint16_t data_len;
uint16_t read_index;
}RING_BUF_TYPEDEF;
RING_BUF_TYPEDEF ring_buf={0};
/*初始化环形缓冲区*/
uint8_t ring_buf_init(RING_BUF_TYPEDEF* r_buf)
{
r_buf->data_len =0;
r_buf->read_index = 0;
return 0;
}
/*环形缓冲区为空或者数据已经被读完*/
uint8_t ring_buf_is_empty()
{
if(ring_buf.data_len == ring_buf.read_index)
{
return 1;/*环形缓冲区为空返回1*/
}
return 0;
}
/*环形缓冲区爆满*/
uint8_t ring_buf_is_fill()
{
if(ring_buf.data_len == ring_buf.read_index - 1)
{
return 1;/*环形缓冲区爆满返回1*/
}
return 0;
}
/*往环形缓冲区中写数据*/
uint8_t ring_buf_write(RING_BUF_DATA_TYPE data)
{
if(ring_buf_is_fill() == 0)/*环形缓冲区未满*/
{
if(ring_buf.data_len==UART2_RX_BUF_SIZE)
{
ring_buf.data_len = 0;
}
ring_buf.uart1_rx_data[ring_buf.data_len]=data;
ring_buf.data_len++;
return 1; /*写成功*/
}
return 0; /*写失败*/
}
/*从环形缓冲区中读数据*/
uint8_t ring_buf_read(RING_BUF_DATA_TYPE* pdata)
{
int16_t i = 1000;
while(ring_buf_is_empty() != 0 && i >= 0)//接受可能过快等一段时间
{
i--;
}
if(ring_buf_is_empty()==0) /*环形缓冲区非空*/
{
if(ring_buf.read_index == UART2_RX_BUF_SIZE)
{
ring_buf.read_index = 0;
}
*pdata= ring_buf.uart1_rx_data[ring_buf.read_index];
ring_buf.read_index++;
return 1; /*读成功*/
}
return 0; /*读失败*/
}
main.c文件
void main()
{
/*省略.....*/
while (1)
{
/* USER CODE END WHILE */
if(ring_buf_read(&temp8))
{
printf("%c",temp8);
}
HAL_Delay(100);
/* USER CODE BEGIN 3 */
}
}
最后效果,只要保证缓冲区不出现饱满,的情况可以每隔较长时间处理每一帧数据
下面是一个应用,假设以16进制 AA BB CC 为指定命令。
void main()
{
/*省略......*/
while (1)
{
if(ring_buf_read(&temp8)==0) continue;
if(temp8 == 0xAA)
{
if(ring_buf_read(&temp8)==0) continue;
if(temp8 == 0xBB)
{
if(ring_buf_read(&temp8)==0) continue;
if(temp8==0xCC)
{
printf("接收到指定命令\r\n");
}
}
}
}
}