在嵌入式设计中,经常使用串口(UART)接收数据。通常我们接收数据使用串口中断函数,通过判断帧格式来确定接收到一个完整的帧。
这种方法有个缺点:当帧尾丢失,可能造成长时间等待,直到收到下一个数据帧的结尾才能停止。这样会造成接连的两个数据包接收错误。
但是配合定时器中断进行通讯的超时判断,可以解决包尾丢失的问题。不过这种方法适用于通讯不紧凑的情况。也就是每帧数据间隔时间需要长些。具体有多长,以115200的波特率为例,帧与帧的间隔最好大于3ms。
数据结构
使用的数据结构是
typedef struct
{
uint8_t* buf; //指向接收缓存区
uint16_t length; //接收的数据长度
uint16_t state; //一帧数据是否接收完成
uint16_t timer; //在定时器中断中,用于倒计时,判断是否超时
uint16_t max_count_down_value; //超时判断的时间,如3ms
uint16_t buf_max_length; //buf缓冲区的长度
}UartDataStruct
函数
共使用3个函数
数据结构的初始化uart_struct_init()串口接收中断中的函数uart_rx_IRQ_handler()定时器中断中的函数uart_timer_IRQ_handler()
流程图如下
首先初始化数据结构中的变量uart_struct_init()
然后在相应串口的接收中断中添加函数uart_rx_IRQ_handler()
函数流程图如下:
最后在定时器中断中添加函数uart_timer_IRQ_handler()。定时器最好是将周期设置成1ms,或者使用滴答中断。
函数流程图如下:
通过判断uart_timer_IRQ_handler()的返回值是否为0,得到是否接收到1个完整的数据帧。
总结
当然也可以单纯的使用超时判断的方法接收串口数据,等待一帧数据接收完成之后对数据进行处理。通过这种方法能够简化串口中断的处理程序,摆脱了帧格式的束缚。不过这个方法也有缺点,就是实时性较差,需要延时3ms才能得到完整的数据帧。因此,在使用中要根据情况选择不同的方法。