Recieve Interrupt

该示例演示使用 UART 中断方式与PC终端进行数据通信。 PC终端程序(如PUTTY或UartAssist)发送数据。 MCU 接收数据并触发中断。在UART中断处理函数中,在 UART_INT_RD_AVA 中断中将接收到的数据存储到缓冲区中,在 UART_FLAG_RX_IDLE 中断中置位received_flag以表示接收完成。 一旦received_flag被设置,MCU将缓冲区数据发送回PC终端。

环境需求

该示例支持以下开发套件:

开发套件

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

更多信息请参考 快速入门

硬件连线

连接P3_0和RX,P3_1和TX。

编译和下载

该示例的工程路径如下:

Project file: samples\peripheral\uart\rx_interrupt\proj\rtl87x2g\mdk

Project file: samples\peripheral\uart\rx_interrupt\proj\rtl87x2g\gcc

请按照以下步骤操作构建并运行该示例:

  1. 打开工程文件。

  2. 按照 快速入门编译APP Image 给出的步骤构建目标文件。

  3. 编译成功后,在路径 mdk\bingcc\bin 下会生成 app bin app_MP_xxx.bin 文件。

  4. 按照 快速入门MPTool 给出的步骤将app bin烧录至EVB内。

  5. 按下复位按键,开始运行。

测试验证

准备阶段

  1. 启动 PuTTY 或 UartAssist 等PC终端,连接到使用的COM端口,并进行以下UART设置:

  • 波特率: 115200

  • 8 数据位

  • 1 停止位

  • 无校验

  • 无硬件流控

测试阶段

  1. 当EVB启动后,在DebugAnalyzer工具内观察如下LOG。

    Start uart rx interrupt test!
    
  2. 该示例开始发送 ### Uart interrupt sample ###\r\n,观察PC终端上出现的字符串。

  3. 在PC终端上输入字符串,并观察PC终端上是否出现相同的字符串。同时在DebugAnalyzer工具上会显示接收到的数据和中断信息。

代码介绍

该章节分为以下几个部分:

  1. 源码路径.

  2. 初始化函数将在 初始化 章节介绍

  3. 初始化后的功能实现将在 功能实现 章节介绍

源码路径

  • 工程路径: sdk\samples\peripheral\uart\rx_interrupt\proj

  • 源码路径: sdk\samples\peripheral\uart\rx_interrupt\src

该工程的工程文件代码结构如下:

└── Project: output_toggle
    └── secure_only_app
        └── Device                   includes startup code
            ├── startup_rtl.c
            └── system_rtl.c
        ├── CMSIS                    includes CMSIS header files
        ├── CMSE Library             Non-secure callable lib
        ├── lib                      includes all binary symbol files that user application is built on
            └── rtl87x2g_io.lib
        ├── peripheral               includes all peripheral drivers and module code used by the application
            ├── rtl_nvic.c
            ├── rtl_pinmux.c
            ├── rtl_rcc.c
            └── rtl_uart.c
        └── APP                      includes the ble_peripheral user application implementation
            ├── io_uart.c
            └── main_ns.c

初始化

初始化流程包括了 board_uart_initdriver_uart_init


board_uart_init 中包含了PAD与PINMUX设置:

  1. 配置PAD:设置引脚、PINMUX模式、PowerOn、内部上拉。

  2. 配置PINMUX:分配引脚分别为UART3_TX、UART3_RX功能。


driver_uart_init 包含了对uart外设的初始化:

  1. 使能PCC时钟源。

  2. 设置波特率为115200,校验位为无奇偶校验,停止位为1位,数据长度为8bits。

  3. 设置接收阈值为14。

  4. 使能UART接收中断 UART_INT_RD_AVA 和UART接收空闲中断 UART_INT_RX_IDLE

RCC_PeriphClockCmd(APBPeriph_UART3, APBPeriph_UART3_CLOCK, ENABLE);
...
UART_InitStruct.UART_Div            = BaudRate_Table[BAUD_RATE_115200].div;
UART_InitStruct.UART_Ovsr           = BaudRate_Table[BAUD_RATE_115200].ovsr;
UART_InitStruct.UART_OvsrAdj        = BaudRate_Table[BAUD_RATE_115200].ovsr_adj;
UART_InitStruct.UART_Parity         = UART_PARITY_NO_PARTY;
UART_InitStruct.UART_StopBits       = UART_STOP_BITS_1;
UART_InitStruct.UART_WordLen        = UART_WORD_LENGTH_8BIT;
UART_InitStruct.UART_RxThdLevel     = 14;
UART_InitStruct.UART_IdleTime       = UART_RX_IDLE_2BYTE;
...
UART_INTConfig(UART_DEMO, UART_INT_RD_AVA, ENABLE);
UART_INTConfig(UART_DEMO, UART_INT_RX_IDLE, ENABLE);
...

功能实现

  1. 执行 uart_senddata_continuous ,发送 ### Uart interrupt sample ###\r\n 到PC终端。

  2. PC终端发送字符串后,检测接收到数据时, UART_INT_RD_AVAUART_INT_RX_IDLE 中断被触发。

  3. 在UART中断处理函数中,UART正在接收数据会触发 UART_INT_RD_AVA 中断,工作流程如下:

    1. 关闭 UART_INT_RD_AVA 中断。

    2. 执行 UART_GetIID() ,获得中断标志类型。

      1. 当ID为 UART_INT_ID_RX_LEVEL_REACH (RX FIFO数据长度达到RX FIFO阈值UART_RxThdLeve)时,接收FIFO数据,保存到UART_Recv_Buf中。

      2. 当ID为 UART_INT_ID_RX_DATA_TIMEOUT (RX FIFO中至少有一个UART数据,并且不再有数据进来保持4个字节时间)时,接收FIFO数据,保存到UART_Recv_Buf中。

    3. 开启 UART_INT_RD_AVA 中断。

  4. 在UART中断处理函数中,UART完成接收数据会触发 UART_FLAG_RX_IDLE 中断(读空RX FIFO数据后,在RX空闲超时时间内没有数据进入RX FIFO),工作流程如下:

    1. 失能 UART_INT_RX_IDLE 中断。

    2. 清除接收FIFO。

    3. 重新使能 UART_INT_RX_IDLE 中断。

    4. 置位接收标志receive_flag。

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)
{
    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:
    {
        lenth = UART_GetRxFIFODataLen(UART_DEMO);
        UART_ReceiveData(UART_DEMO, UART_Recv_Buf, lenth);
        ...
        break;
    }
...

case UART_INT_ID_RX_LEVEL_REACH:
    {
        lenth = UART_GetRxFIFODataLen(UART_DEMO);
        UART_ReceiveData(UART_DEMO, UART_Recv_Buf, lenth);
        ...
        break;
    }
...
}

UART_INTConfig(UART_DEMO, UART_INT_RD_AVA, ENABLE);
  1. 一旦置位received_flag,MCU就会将缓冲区数据发回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;
    }
}