FR800X系列蓝牙-UART串口收发应用层代码设计实践

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通讯提供了可靠且高效的解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小武编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值