1.本文介绍
在嵌入式系统开发中,UART(通用异步收发传输器)通讯协议因其简单、可靠且广泛支持的特点而被广泛应用。在进行UART通讯协议交付时,经常需要实现接收一帧数据后发送一帧数据的交互模式。本文将详细介绍在FR800X系列蓝牙中,如何设计一个满足特定需求的UART串口收发应用层代码,包括自动判断数据帧、可调节的响应时间、高数据吞吐量等。
项目需求与特点:
1)设计一个UART串口收发系统,该系统能够自动判断接收到的数据帧,并在接收到数据后,经过一个可调节的延迟(最快20ms),发送一帧响应数据。
2)系统应支持波特率115200,且能够一次性接收1K数据而不丢失。
3)选择了基于FR800X蓝牙SDK的工程ble_simple_peripheral作为基础,并进行相应的修改和扩展。
2.实施步骤
工程配置:首先打开ble_simple_peripheral工程,并禁止系统进入睡眠模式,以确保UART通信的连续性和稳定性。这可以通过调用system_sleep_disable()函数来实现。
文件添加与修改:在工程中增加driver_uart.c和user_task.c两个文件。driver_uart.c负责UART驱动的实现,包括中断处理和数据收发等功能;user_task.c则用于处理用户任务,如数据帧的判断、响应数据的生成和发送等。
3,接口说明与功能实现
首先增加2个文件:driver_uart.c和user_task.c
在driver_uart.c中,我们定义了几个关键的函数来处理UART通信:
uart0_IRQHandler():UART中断处理函数,用于响应UART中断并调用具体的中断服务例程。
uart0_isr():UART中断服务例程,负责读取接收到的数据并调用handle_UartRxHandle()进行处理。
handle_UartRxHandle():在任务区处理接收到的数据,将数据存储到缓冲区中,最后并调用App_uartProcess():判断是否接收到完整的一帧数据。
在user_task.c中,定义了几个关键的函数来处理UART接收的数据:
App_uartProcess():判定串口是否接收到完整的一帧数据,并进行相应的处理。如果接收到完整的一帧数据,则调用App_uartTimeoutTaskStart()启动定时器超时任务,准备发送响应数据。
App_uartHandlerInit():接收UART的初始化函数,用于配置UART的相关参数和中断。
App_uartTimeoutTaskStart():接收UART定时器超时任务启动函数,用于设置延迟时间并在超时后发送响应数据。
4.软件设计
4.1.与流程图
为了实现上述功能,我们设计了相应的软件流程图,并编写了部分关键代码。软件流程图清晰地展示了从UART中断触发到数据处理、再到发送响应数据的整个过程。
串口中断:
主循环数据处理:
4.2.响应时间
4.3.部分关键代码
示例如下:
static void App_uartProcess(void *param)
{
uart_timer_out++;
if(uart_timer_out>=2)
{
uart_timer_out = 0;
stTxUartHandle.size = stTxUartBuf.size;
memcpy(stTxUartHandle.txBuf,stTxUartBuf.txBuf,stTxUartBuf.size);
stTxUartBuf.size = 0;
//show_reg(stTxUartHandle.txBuf, stTxUartHandle.size, 1);
handle_UartRxHandle(stTxUartHandle.txBuf,stTxUartHandle.size);
// 停止定时器
os_timer_stop(&uart_process_timer);
uart_timer_start = 0;
}
}
void uart0_IRQHandler(void)
{
uint8_t data;
switch (__UART_INT_GET_ID(Uart0))
{
case INT_INDEX_TXE:
{
/* Tx empty interrupt and fifo disable */
Uart0->IER_DLH.IER.PTIME = 0;
Uart0->IER_DLH.IER.ETBEI = 0;
//co_printf("---->INT_INDEX_TXE\r\n");
}
break;
case INT_INDEX_RX:
case INT_INDEX_RX_TOUT:
{
/* Rx ready */
//rx fifo at least have one data
while (Uart0->LSR.LSR_BIT.DR)
{
data = Uart0->DATA_DLL.DATA;
uart_timer_out = 0;
//uart_putc_noint_no_wait(UART0, data);
stTxUartBuf.txBuf[stTxUartBuf.size] = data;
stTxUartBuf.size ++;
if (stTxUartBuf.size >= uartRxBufferMAX)
{
stTxUartBuf.size = 0;
}
}
}break;
case INT_INDEX_LINE:
{
volatile uint32_t line_status = Uart0->LSR.LSR_DWORD;
//co_printf("---->INT_INDEX_LINE [%x]\r\n",line_status);
}break;
default:
break;
}
}
__attribute__((section("ram_code"))) void uart0_isr(void)
{
uart0_IRQHandler();
}
五.总结
通过上述步骤和代码设计,我们成功实现了FR800X系列需求的UART串口收发应用层代码。该系统能够自动判断接收到的数据帧,并在接收到数据后经过可调节的延迟发送响应数据。同时,系统支持高波特率和大容量数据接收,为嵌入式系统中的UART通讯提供了可靠且高效的解决方案。