IR Transmmit

该示例演示红外发送功能的使用方法。使用 IR 外设进行数据发送,实现红外发射功能,使用逻辑分析仪观察IR发送波形。

环境需求

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

开发套件

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

更多信息请参考 快速入门

硬件连线

连接IR发送引脚P2_5至逻辑分析仪。

编译和下载

该示例的工程路径如下:

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

Project file: samples\peripheral\ir\tx\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发送波形

代码介绍

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

  1. 源码路径

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

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

源码路径

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

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

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

└── Project: tx
    └── 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_TX功能。


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

  1. 使能PCC时钟。

  2. 设置IR发送频率为38kHz。

  3. 设置IR载波占空比为1/2。

  4. 设置IR为发送模式。

  5. 设置 IR_TxInverseIR_TX_DATA_NORMAL ,即不反转IR发送数据。

  6. 设置IR发送FIFO阈值为2。

  7. 配置IR发送FIFO数据个数小于设置的发送阈值中断 IR_INT_TF_LEVEL

RCC_PeriphClockCmd(APBPeriph_IR, APBPeriph_IR_CLOCK, ENABLE);
...
IR_InitStruct.IR_Freq           = vFreq;
IR_InitStruct.IR_DutyCycle      = 2; /* !< 1/2 duty cycle */
IR_InitStruct.IR_Mode           = IR_MODE_TX;
IR_InitStruct.IR_TxInverse      = IR_TX_DATA_NORMAL;
IR_InitStruct.IR_TxFIFOThrLevel = IR_TX_FIFO_THR_LEVEL;
IR_Init(&IR_InitStruct);

/* Enable IR threshold interrupt. when TX FIFO offset <= threshold value, trigger interrupt*/
IR_INTConfig(IR_INT_TF_LEVEL, ENABLE);
...

功能实现

  1. 定义IR发送数据数组:有载波数据用载波个数与0x80000000进行或运算表示,无载波数据用载波个数与0x00000000进行或运算表示。

  2. 执行 IR_SendBuf() 函数,开始往IR发送FIFO中塞发送数据;使能IR外设发送功能。

  3. 记录已经发送的数据个数。

IR_TxData.CarrierFreq = 38000;
IR_TxData.DataLen = 67 + 1; //2+64+1;
IR_TxData.DataBuf[0] =  0x80000000 | 0x156; //342 about 9ms
IR_TxData.DataBuf[1] =  0x00000000 | 0xAB; //171 about 4.5ms
...
IR_TxData.DataBuf[IR_TxData.DataLen - 1] =  0x80000000 | 0x15;
...
IR_SendBuf(IR_TxData.DataBuf, IR_TX_FIFO_SIZE, DISABLE);
IR_Cmd(IR_MODE_TX, ENABLE);
  1. 当IR发送FIFO数据个数小于设置的发送阈值(此例中设为2)时,触发 IR_INT_TF_LEVEL 中断,进入中断处理函数 IR_Handler

    1. 屏蔽 IR_INT_TF_LEVEL 中断。

    2. 如果剩余发送数据个数大于发送FIFO大小,往IR发送FIFO中塞(IR_TX_FIFO_SIZE - IR_TX_FIFO_THR_LEVEL) 个数据并发送,清除 IR_INT_TF_LEVEL 中断挂起位。

    3. 否则如果剩余发送数据个数大于0,往IR发送FIFO中塞剩余数据,清除 IR_INT_TF_LEVEL 中断挂起位。

    4. 否则如果没有剩余数据,失能 IR_INT_TF_LEVEL 中断,清除 IR_INT_TF_LEVEL 中断挂起位。

    5. 取消屏蔽 IR_INT_TF_LEVEL 中断。

IR_MaskINTConfig(IR_INT_TF_LEVEL, ENABLE);
if ((IR_TxData.DataLen - IR_TX_Count) >= IR_TX_FIFO_SIZE)
{
    IR_SendBuf(IR_TxData.DataBuf + IR_TX_Count, (IR_TX_FIFO_SIZE - IR_TX_FIFO_THR_LEVEL), DISABLE);
    IR_TX_Count += (IR_TX_FIFO_SIZE - IR_TX_FIFO_THR_LEVEL);

    /* Clear threshold interrupt */
    IR_ClearINTPendingBit(IR_INT_TF_LEVEL_CLR);
}
else if ((IR_TxData.DataLen - IR_TX_Count) > 0)
{
    /* The remaining data is less than the TX FIFO length */

    /*  Configure TX threshold level to zero and trigger interrupt when TX FIFO is empty */
    IR_SetTxThreshold(0);
    IR_SendBuf(IR_TxData.DataBuf + IR_TX_Count, IR_TxData.DataLen - IR_TX_Count, DISABLE);
    IR_TX_Count += (IR_TxData.DataLen - IR_TX_Count);

    /* Clear threshold interrupt */
    IR_ClearINTPendingBit(IR_INT_TF_LEVEL_CLR);
}
else
{
    /* Tx completed */
    /* Disable IR tx empty interrupt */
    IR_INTConfig(IR_INT_TF_LEVEL, DISABLE);
    IR_TX_Count = 0;

    /* Clear threshold interrupt */
    IR_ClearINTPendingBit(IR_INT_TF_LEVEL_CLR);
}