FR800X系列用户启用串口收发
1、串口收发展示
2、概要
富笍坤FR800X系列软件开发,基于官方SDK中实现串口发送和接收数据,经调试SDK发现,代码中log_init()函数已经打开串口打印消息,用户可以直接用co_printf()打印消息,这样即实现TX发送数据的环节。用户若需要串口接收数,实现上位机与机器数据交互环节,用户就需要打开串口接收。
本文主要讲述:用户如何打开串口接收、串口调试细节和常用接收一帧数据的方法。用户最常见得数据交互为一发一收方式,发送一帧数据,然后还回一帧数据。
3、如何启用串口接收
一般需要对串口初始化和设计串口接收中断函数
串口初始化:包括打开UART0时钟、设置Tx和Rx端口、设置波特率、使能接收中断、
代码如下(示例):
__SYSTEM_UART0_CLK_ENABLE();
system_set_port_pull(GPIO_PA0, GPIO_PULL_UP, true);
system_set_port_mux(GPIO_PORT_A, GPIO_BIT_0, PORTA0_FUNC_UART0_RXD);
system_set_port_mux(GPIO_PORT_A, GPIO_BIT_1, PORTA1_FUNC_UART0_TXD);
pmu_set_pin_to_CPU(GPIO_PORT_A, (1<<GPIO_BIT_1));
uart_init(UART0, 1152);
fr_uart_enableIrq(UART0, Uart_irq_erbfi);
NVIC_EnableIRQ(UART0_IRQn);
设计中断函数:串口接收中断函数,搜索一下uart0_isr出现的地方,在drvier_uart.c中写串口中断函数接口。
// 设计串口接收结构体
#define uartRxBufferMAX 256
typedef struct{
uint16_t size;
uint8_t txBuf[uartRxBufferMAX];
}st_uartBuffer_t;
// 定义一个接收数据变量
st_uartBuffer_t stRxUartBuf = {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_putc_noint_no_wait(UART0, data);
stRxUartBuf.txBuf[stRxUartBuf.size] = data; // 写入缓存
stRxUartBuf.size ++;
if (stRxUartBuf.size >= uartRxBufferMAX)
{
stRxUartBuf.size = 0;
}
//uart_putc_noint(UART0,data); // 发送接收的数据
}
App_uartTimeoutTaskStart();
/*
while (Uart0->LSR.LSR_BIT.DR)
{
data = Uart0->DATA_DLL.DATA;
uart_putc_noint(UART0,data);
}
*/
}
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();
}
__attribute__((section("ram_code"))) void uart1_isr(void)
{
uart1_IRQHandler();
}
4、串口调试细节
- 串口接收需保证BLE处于正常工作模式,禁止进入睡眠。
- 在初始化增加system_sleep_disable();确保不进入睡眠。
- 配置IO管脚与连接的管脚要正确。
5、常用收发一帧数据
如果判定一帧数据?
串口接收一帧数据每一个字节都是连续的,一般字节与字节之间的间隔不到1mS,这样我们将间隔超过20mS的认为是一帧数据发送完成。使用软件定时器等待接收下一个字节未超过20mS的存储在接收缓存里面,超过20mS表示接收一帧数据。而 发送一帧数据:uart_send_len() 可以发送一帧长度的数据
/*
* 功能: handle_UartRxHandle
*
* 注解: 串口接收一帧数据处理
*
* 输入: dat:缓存 len:长度
* 输出: 无
*
*/
static void handle_UartRxHandle(uint8_t *dat,uint32_t len)
{
//co_printf("len:%d\r\n",len);
uart_send_len(dat,len); // 发送一帧数据
UART_to_AT_CMD(dat,len); // AT命令开发
}
/*
* 功能: App_uartProcess
*
* 注解: 串口接收一帧数据处理
*
* 输入: 无
* 输出: 无
*
*/
static void App_uartProcess(void *param)
{
handle_UartRxHandle(stRxUartBuf.txBuf,stRxUartBuf.size);
stRxUartBuf.size = 0;
}
/*
* 功能: App_uartHandlerInit
*
* 注解: 串口接收应用初始化
*
* 输入: 无
* 输出: 无
*
*/
static void App_uartHandlerInit(void)
{
os_timer_init(&uart_process_timer, App_uartProcess, NULL);
}
/*
* 功能: App_uartTimeoutTaskStart
*
* 注解: 开始接收并等待串行数据超时
*
* 输入: 无
* 输出: 无
*
*/
void App_uartTimeoutTaskStart(void)
{
os_timer_start(&uart_process_timer, 20, false); //start 10ms anti-shake timer
}
6、小结
串口收一帧数据,①需要保证系统处于正常工作模式,才能正常接收数据,②还需用到软件定时器,等待20mS未收到数据认为是接收完成。
串口收发用户经常使用,如开发AT命令、上位机交互协议和串口调试等。本文代码部分已在实际项目中验证过,直接移植代码就可以使用,作者经常用这种方法来开发串口接收,不知您还有哪种更好读串口接收数据的方法,欢迎评论,谢谢!。