IR Recieve

该示例演示红外接收功能的使用方法。使用另一颗EVB烧录 IR 发送的程序作为IR数据的发送端向EVB发送IR数据,通过IR中断接收IR数据,实现RX功能。

环境需求

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

开发套件

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

更多信息请参考 快速入门

硬件连线

使用另一颗EVB烧录IR TX程序,连接P2_5和另一颗EVB的发送引脚。

编译和下载

该示例的工程路径如下:

Project file: samples\peripheral\ir\rx\proj\rtl87x2g\mdk

Project file: samples\peripheral\ir\rx\proj\rtl87x2g\gcc

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

  1. 打开工程文件。

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

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

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

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

测试验证

当IR接收计数器的个数达到设置的阈值,代表IR数据接收完毕,进入IR中断,打印接收数据及其长度。接收的数据即为IR发送端定义的数据内容。

IR_INT_RX_CNT_THR
len = xx
[io_ir]io_handle_ir_msg: IR RX data[0] = xxx
[io_ir]io_handle_ir_msg: IR RX data[1] = xxx
...

代码介绍

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

  1. 源码路径

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

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

源码路径

  • 工程路径: sdk\samples\peripheral\ir\rx\proj

  • 源码路径: sdk\samples\peripheral\ir\rx\src

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

└── Project: rx
    └── 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_rcc.c
            ├── rtl_pinmux.c
            ├── rtl_nvic.c
            └── rtl_ir.c
        └── APP                      includes the ble_peripheral user application implementation
            ├── main_ns.c
            └── io_ir.c

初始化

初始化流程包括了 board_ir_initdriver_ir_init


board_ir_init 包含了对PAD和PINMUX的设置。

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

  2. 配置PINMUX:分配引脚P2_5为IRDA_RX功能。


driver_ir_init 包含了对IR外设的初始化。

  1. 使能PCC时钟。

  2. 设置IR接收频率为38kHz。

  3. 设置IR为自动接收模式。

  4. 设置IR接收阈值为30,当IR接收FIFO满时丢弃最新数据,过滤低于50ns的杂波数据。

  5. 设置触发接收计数器阈值中断的电平类型为低电平,IR_RxCntThr设置为0x1400。

  6. 使能IR外设接收功能,清除IR接收FIFO。

  7. 配置IR接收FIFO数据个数大于设置的接收阈值中断 IR_INT_RF_LEVEL 和接收电平超时中断 IR_INT_RX_CNT_THR

  8. 取消屏蔽 IR_INT_RF_LEVELIR_INT_RX_CNT_THR 中断。

RCC_PeriphClockCmd(APBPeriph_IR, APBPeriph_IR_CLOCK, ENABLE);
...
IR_InitStruct.IR_Freq               = 38000;
IR_InitStruct.IR_Mode               = IR_MODE_RX;
IR_InitStruct.IR_RxStartMode        = IR_RX_AUTO_MODE;
IR_InitStruct.IR_RxFIFOThrLevel     = IR_RX_FIFO_THR_LEVEL;
IR_InitStruct.IR_RxFIFOFullCtrl     = IR_RX_FIFO_FULL_DISCARD_NEWEST;
IR_InitStruct.IR_RxFilterTime       = IR_RX_FILTER_TIME_50ns;
IR_InitStruct.IR_RxTriggerMode      = IR_RX_FALL_EDGE;
IR_InitStruct.IR_RxCntThrType       = IR_RX_Count_Low_Level;
IR_InitStruct.IR_RxCntThr           = 0x1400;
IR_Init(&IR_InitStruct);
IR_Cmd(IR_MODE_RX, ENABLE);
IR_ClearRxFIFO();
...
IR_INTConfig(IR_INT_RF_LEVEL | IR_INT_RX_CNT_THR, ENABLE);
IR_MaskINTConfig(IR_INT_RF_LEVEL | IR_INT_RX_CNT_THR, DISABLE);

功能实现

  1. 向IR收发模块发送IR数据。当IR接收FIFO的数据个数达到设置的接收阈值(此例中设为30)时,触发 IR_INT_RF_LEVEL 中断。或当接收计数器的个数达到设置的阈值(此例中设为0x1400)时,触发 IR_INT_RX_CNT_THR 中断,进入中断处理函数 IR_Handler

    1. 屏蔽 IR_INT_TF_LEVELIR_INT_RX_CNT_THR 中断。

    2. 如果触发的中断为 IR_INT_TF_LEVEL ,则需要IR从FIFO中接收数据。将数据存入DataBuf内,并记录已经接收的数据长度。

    3. 如果触发的中断为 IR_INT_RX_CNT_THR ,则代表触发了IR接收数据的停止条件。将剩余数据存入DataBuf内,记录已经接收的数据长度,并打印数据内容。

    4. 清除 IR_INT_RX_CNT_THR 中断挂起位。

    5. 取消屏蔽 IR_INT_RF_LEVELIR_INT_RX_CNT_THR 中断。

if (int_status_rfl == SET)
{

    len = IR_GetRxDataLen();
    IR_ReceiveBuf(IR_Rx_Data.DataBuf + IR_RX_Count, len);
    IR_Rx_Data.DataLen += len;
    IR_RX_Count += len;

                IR_ClearRxFIFO();

    IR_ClearINTPendingBit(IR_INT_RF_LEVEL_CLR);
}

/* Stop to receive IR data */
if (int_status_rxcnt == SET)
{
    DBG_DIRECT("IR_INT_RX_CNT_THR");
    /* Read remaining data */
    len = IR_GetRxDataLen();
    IR_ReceiveBuf(IR_Rx_Data.DataBuf + IR_RX_Count, len);
    IR_Rx_Data.DataLen += len;
    IR_RX_Count += len;

                DBG_DIRECT("len = %d", IR_RX_Count);

    for (uint16_t i = 0; i < IR_RX_Count; i++)
    {
        DBG_DIRECT("[io_ir]io_handle_ir_msg: IR RX data[%d] = 0x%x", i, IR_Rx_Data.DataBuf[i]);
    }
    memset(&IR_Rx_Data, 0, sizeof(IR_Rx_Data));
    IR_RX_Count = 0;

    IR_ClearINTPendingBit(IR_INT_RX_CNT_THR_CLR);
}

/* Unmask IR all interrupt */
IR_MaskINTConfig(IR_INT_RF_LEVEL | IR_INT_RX_CNT_THR, DISABLE);