Receive Interrupt
该示例演示使用 UART 中断方式与 PC 终端进行数据通信。
使用 PC 终端程序(如 PuTTY 或 UartAssist)发送数据。SoC 接收到数据后触发 UART 中断。
在 UART 中断处理函数中,在 UART_INT_RD_AVA
中断中将接到的数据存储到缓冲区中,在 UART_INT_RX_IDLE
中断中会设置 received_flag
以表示接收完成。
一旦 received_flag
被设置,SoC 将缓冲区数据发送回 PC 终端,在 PC 终端程序中可观察到 SoC 回复的数据信息。
环境需求
该示例的环境需求,可参考 环境需求。
此外,需要在 PC 终端安装 PuTTY 或 UartAssist 等串口助手工具。
硬件连线
连接 P3_0(UART TX Pin)和 FT232 的 RX,P3_1(UART RX Pin) 和 FT232 的 TX。
配置选项
可配置如下宏修改引脚定义。
#define UART_TX_PIN P3_0 #define UART_RX_PIN P3_1
编译和下载
该示例的编译和下载流程,可参考 编译和下载。
测试验证
准备阶段
启动 PuTTY 或 UartAssist 等 PC 终端,连接到使用的 COM 端口,并进行以下 UART 设置:
波特率: 115200
8 数据位
1 停止位
无校验
无硬件流控
测试阶段
当 EVB 启动后,在 Debug Analyzer 工具内观察如下 log。
Start uart rx interrupt test!
Soc 开始发送
### Uart interrupt sample ###\r\n
,观察 PC 终端上出现的字符串。在 PC 终端上输入字符串并向 SoC 发送,SoC 收到数据后会向 PC 端回复相同的数据。观察 PC 终端上是否出现相同的字符串,同时在 Debug Analyzer 工具上会显示接收到的数据和中断信息。
代码介绍
该章节主要介绍示例中的初始化和相应功能实现的代码和流程说明。
源码路径
工程文件和源码路径如下:
工程路径:
sdk\samples\peripheral\uart\rx_interrupt\proj
源码路径:
sdk\samples\peripheral\uart\rx_interrupt\src
初始化
外设的初始化流程可参考 General Introduction 中的 初始化流程 部分。
调用
Pad_Config()
与Pinmux_Config()
,配置对应引脚的 PAD 和 PINMUX。void board_uart_init(void) { Pad_Config(UART_TX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH); Pad_Config(UART_RX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH); Pinmux_Config(UART_TX_PIN, UART3_TX); Pinmux_Config(UART_RX_PIN, UART3_RX); }
调用
RCC_PeriphClockCmd()
,开启 UART 时钟。对 UART 外设进行初始化:
定义
UART_InitTypeDef
类型UART_InitStruct
,调用UART_StructInit()
将UART_InitStruct
预填默认值。根据需求修改
UART_InitStruct
参数,UART 的初始化参数配置如下表。调用
UART_Init()
,初始化 UART 外设。
UART Hardware Parameters |
Setting in the |
UART |
---|---|---|
UART Baudrate Parameter - div |
|
|
UART Baudrate Parameter - ovsr |
|
|
UART Baudrate Parameter - ovsr_adj |
|
|
Rx Threshold |
14 |
|
IDLE Time |
配置 UART 接收中断
UART_INT_RD_AVA
和 UART 接收空闲中断UART_INT_RX_IDLE
,配置 NVIC。NVIC 相关配置可参考 中断配置。
功能实现
UART 通过中断接收数据的流程如图所示:

UART 中断接收数据流程
执行
uart_senddata_continuous
,发送### Uart interrupt sample ###\r\n
到 PC 终端。在函数uart_senddata_continuous
内,等待 UART TX FIFO 为空时,分批将数据填入 FIFO 中。void uart_senddata_continuous(UART_TypeDef *UARTx, const uint8_t *pSend_Buf, uint16_t vCount) { uint8_t count; while (vCount / UART_TX_FIFO_SIZE > 0) { while (UART_GetFlagStatus(UARTx, UART_FLAG_TX_FIFO_EMPTY) == 0); for (count = UART_TX_FIFO_SIZE; count > 0; count--) { UARTx->UART_RBR_THR = *pSend_Buf++; } vCount -= UART_TX_FIFO_SIZE; } while (UART_GetFlagStatus(UARTx, UART_FLAG_TX_FIFO_EMPTY) == 0); while (vCount--) { UARTx->UART_RBR_THR = *pSend_Buf++; } }
PC 终端发送字符串后,SoC 检测接收到数据时,会触发 UART 中断。根据 PC 终端发送的数据长度不同,会触发不同类型的中断。
若 PC 终端发送的数据长度大于设定的阈值时,SoC 首先会触发
UART_INT_ID_RX_LEVEL_REACH
中断。在中断内调用UART_GetRxFIFODataLen()
和UART_ReceiveData()
,接收数据并保存到UART_Recv_Buf
中。若 PC 终端发送的数据长度小于设定的阈值时,SoC 检测到 RX FIFO 内存在数据,但是一段时间内 RX FIFO 没有再填入新数据时,会触发
UART_INT_ID_RX_DATA_TIMEOUT
中断。在中断内调用UART_GetRxFIFODataLen()
和UART_ReceiveData()
,接收数据并保存到UART_Recv_Buf
中。
备注
触发 UART_INT_ID_RX_DATA_TIMEOUT
中断所需要的时间,为 4 个 Characters 的时间。在 115200 波特率的情况下,一个 Character 的时间为 1/112500 * (1+8+0+1) = 86.8us。Character = start bit + data bits + parity bit + stop bits.
若 RX FIFO 为空且在设置的 IDLE 时间内没有接收到数据时,触发
UART_FLAG_RX_IDLE
中断。在中断函数内设置receive_flag
标志位为true
。void UART_HANDLER() { uint16_t lenth = 0; uint32_t int_status = UART_GetIID(UART_DEMO); UART_INTConfig(UART_DEMO, UART_INT_RD_AVA, DISABLE); if (UART_GetFlagStatus(UART_DEMO, UART_FLAG_RX_IDLE) == SET) { DBG_DIRECT("UART_FLAG_RX_IDLE"); UART_INTConfig(UART_DEMO, UART_INT_RX_IDLE, DISABLE); UART_ClearRxFIFO(UART_DEMO); UART_INTConfig(UART_DEMO, UART_INT_RX_IDLE, ENABLE); receive_flag = true; } switch (int_status & 0x0E) { case UART_INT_ID_RX_DATA_TIMEOUT: { DBG_DIRECT("UART_INT_ID_RX_TMEOUT"); lenth = UART_GetRxFIFODataLen(UART_DEMO); UART_ReceiveData(UART_DEMO, UART_Recv_Buf, lenth); for (uint8_t i = 0; i < lenth; i++) { DBG_DIRECT("data=0x%x", UART_Recv_Buf[i]); UART_Send_Buf[UART_Recv_Buf_Lenth + i] = UART_Recv_Buf[i]; } UART_Recv_Buf_Lenth += lenth; break; } case UART_INT_ID_LINE_STATUS: break; case UART_INT_ID_RX_LEVEL_REACH: { DBG_DIRECT("UART_INT_ID_RX_LEVEL_REACH"); lenth = UART_GetRxFIFODataLen(UART_DEMO); UART_ReceiveData(UART_DEMO, UART_Recv_Buf, lenth); for (uint8_t i = 0; i < lenth; i++) { DBG_DIRECT("data=0x%x", UART_Recv_Buf[i]); UART_Send_Buf[UART_Recv_Buf_Lenth + i] = UART_Recv_Buf[i]; } UART_Recv_Buf_Lenth += lenth; break; } case UART_INT_ID_TX_EMPTY: break; default: break; } UART_INTConfig(UART_DEMO, UART_INT_RD_AVA, ENABLE); }
循环判断
receive_flag
的状态。当发现receive_flag
置为true
时,代表此次 UART 接收完毕。调用uart_senddata_continuous
将接收到的数据UART_Recv_Buf
发送回至 PC 终端。while (1) { if (receive_flag == true) { receive_flag = false; uart_senddata_continuous(UART_DEMO, UART_Send_Buf, UART_Recv_Buf_Lenth); for (uint16_t i = 0; i < UART_Recv_Buf_Lenth; i++) { UART_Recv_Buf[i] = 0; } UART_Recv_Buf_Lenth = 0; } }