一:本贴内容:
使用定时器做串口超时判断与串口接收数据,实现接收不定长的数据。
二:瑞萨RA0E2的串口中断标志位如下所示:
typedef enum e_sf_event { UART_EVENT_RX_COMPLETE = (1UL << 0), ///< Receive complete event UART_EVENT_TX_COMPLETE = (1UL << 1), ///< Transmit complete event UART_EVENT_RX_CHAR = (1UL << 2), ///< Character received UART_EVENT_ERR_PARITY = (1UL << 3), ///< Parity error event UART_EVENT_ERR_FRAMING = (1UL << 4), ///< Mode fault error event UART_EVENT_ERR_OVERFLOW = (1UL << 5), ///< FIFO Overflow error event UART_EVENT_BREAK_DETECT = (1UL << 6), ///< Break detect error event UART_EVENT_TX_DATA_EMPTY = (1UL << 7), ///< Last byte is transmitting, ready for more data } uart_event_t;
如上图所示:有关串口接收的状态位,是串口接收完成一帧标志位如下:只有接收固定长度的数据字符才可以触发:
UART_EVENT_RX_COMPLETE
串口接收的的状态位,如下:
UART_EVENT_RX_CHAR
上面的状态,在串口接收的一个字符时候就会触发,串口可以实时的接收数据。
为了接收不定长的数据,我这里使用定时器的超时判断一帧数据是否完成,从而实现数据的接收。
三:代码实现
3.1 定义一些宏定义变量:
uint8_t usart0_flag =0 ; uint8_t usart0_pack = 0; uint8_t usart0_Recpoint = 0 ; uint8_t usart0_Reclength = 0 ; uint8_t usart0_Recbuffer[30] ; uint8_t usart0_OverTime = 0 ; // uint8_t usart0_dealbuffer[30] ;
3.2 串口发送数据函数如下:
实现串口发送一个字节数据:
void g_uart0_sendOneByte(uint8_t ch) { R_UARTA_Write(&g_uart0_ctrl, (uint8_t *)&ch, 1); while(g_data_transmit_flag == false); g_data_transmit_flag = false; }
3.3 串口实现发送固定长度数据:
void g_uart0_databack(int length) { uint8_t i = 0 ; for(i=0 ; i< length;i++) { g_uart0_sendOneByte(usart0_dealbuffer[i]) ; } }
将串口接收到的数据,返回至串口。
3.4 串口回调函数如下所示:
void g_uart0_callback(uart_callback_args_t *p_args) { switch (p_args->event) { case UART_EVENT_RX_CHAR: usart0_flag = 1; usart0_OverTime = 5; usart0_Recbuffer[usart0_Recpoint++]=(p_args->data); usart0_Reclength = usart0_Recpoint; break; case UART_EVENT_TX_COMPLETE: g_data_transmit_flag = true; break; default: break; } }
3.5 串口超时判断部分如下所示:
case 2: if(usart0_flag == 1) { usart0_OverTime-- ; if(usart0_OverTime < 1) { usart0_OverTime = 0 ; usart0_flag =0 ; usart0_pack =1 ; memcpy(&usart0_dealbuffer[0],&usart0_Recbuffer[0],usart0_Reclength) ; } } break;
3.6 将收到的数据原路返回:
case 10: if(usart0_pack==1) { usart0_pack = 0 ; usart0_Recpoint = 0 ; g_uart0_databack(usart0_Reclength); } break;
RA0E2芯片:每当串口接收硬件物理地收到一个字节(并通常将其存入接收数据寄存器后),就会产生一次接收中断。在中断服务函数需要立刻读取这个字节并存入接收的缓冲区(buffer里面,这里注意一下接收的长度,当超过接收数组的最大buffer时候,需要做错误处理)。
想要判断要完整接收一帧数据,需要在软件代码中做一下处理,我这里做的是超时判断,大体思路是:在串口接收中断中,给某个变量赋初值,比如说:5;然后再定时器的处理函数中,将该值减小。同时将接收到的数据存入接收缓冲区内,当串口接收计时的数据减小到0时候,意味着串口内不再接收到新的数据,软件判定一帧数据接收完成。最后将数据做回传处理,同时将接收的指针做清零处理。
四:测试图片如下所示: