IR Receive
该示例演示了如何在 IR 中断模式下接收数据。
使用 P2_6 引脚作为 PWM 输出引脚,输出 PWM 波形用于模拟发送端数据。将 PWM 输出引脚连接到 IR 输入引脚。
在 IR 中断内进行数据的接收,当数据量超过 IR 的 FIFO 容量时,需要多次连续接收数据。
环境需求
该示例的环境需求,可参考 环境需求。
硬件连线
连接 PWM 输出引脚 P2_6 与 IR 接收引脚 P2_5。
配置选项
可配置如下宏修改引脚定义。
#define IR_RX_PIN P2_5 #define PWM_OUT_PIN P2_6
可配置如下宏修改 PWM 配置信息。
#define PWM_PERIOD 26.3 //uint:us #define PWM_DUTY_CYCLE 50 //uint:percent #define PWM_HIGH_COUNT ((((PWM_PERIOD)*(PWM_DUTY_CYCLE*40))/100)-1) #define PWM_LOW_COUNT ((((PWM_PERIOD)*((100-PWM_DUTY_CYCLE)*40))/100)-1)
编译和下载
该示例的编译和下载流程,可参考 编译和下载。
测试验证
初始化完毕后,PWM 开始输出波形,频率设置为 38KHz,与 IR 接收频率相同。在主程序中,每间隔 500us 反复使能和失能 TIM PWM 输出,模拟 500us 的有载波数据和无载波数据。PWM 波形如图所示。

PWM 输出波形
当 PWM 输出波形的时候,IR 接收器将 500us 的 PWM 波形解析为一个 mark 数据。当 PWM 不输出波形的时候,IR 接收器将 500us 的低电平解析为一个 space 数据。
当 IR 接收计数器的数据个数达到设置的阈值,会触发 IR
IR_INT_RF_LEVEL
中断,在 IR 中断内接收当前数据。在主程序中,PWM 输出变化数次后,会停止输出 PWM 波形,此时 IR 检测到低电平输入。当低电平输入时间达到设定的 counter 值时,触发
IR_INT_RX_CNT_THR
中断,将剩余数据全部接收完毕。IR_INT_RX_CNT_THR len = xx [io_ir]io_handle_ir_msg: IR RX data[0] = 0x80000012 [io_ir]io_handle_ir_msg: IR RX data[1] = 0x00000012 ... [io_ir]io_handle_ir_msg: IR RX data[xx] = 0x00000200
备注
其中载波数据 0x800000012 表示高电平输出为 12 个载波周期,0x12 代表低电平输出 12 个载波周期。
代码介绍
该章节主要介绍示例中的初始化和相应功能实现的代码和流程说明。
源码路径
工程文件和源码路径如下:
工程路径:
sdk\samples\peripheral\ir\rx\proj
源码路径:
sdk\samples\peripheral\ir\rx\src
初始化
外设的初始化流程可参考 General Introduction 中的 初始化流程 部分。
调用
Pad_Config()
与Pinmux_Config()
,配置对应引脚的 PAD 和 PINMUX。void board_ir_init(void) { Pad_Config(IR_RX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, PAD_OUT_LOW); Pinmux_Config(IR_RX_PIN, IRDA_RX); } void board_pwm_init(void) { Pad_Config(PWM_OUT_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pinmux_Config(PWM_OUT_PIN, PWM_OUT_PIN_PINMUX); }
调用
RCC_PeriphClockCmd()
,开启 IR 时钟。对 IR 外设进行初始化:
定义
IR_InitTypeDef
类型IR_InitStruct
,调用IR_StructInit()
将IR_InitStruct
预填默认值。根据需求修改
IR_InitStruct
参数,IR 的初始化参数配置如下表。调用
IR_Init()
,初始化 IR 外设。
IR Hardware Parameters |
Setting in the |
IR |
---|---|---|
Sample Clock |
38000 |
|
IR Mode |
||
IR Rx Mode |
||
FIFO Threshold Level |
10 |
|
IR Rx Trigger Mode |
||
IR Rx Counter Threshold Type |
||
IR Rx Counter Threshold |
0x200 |
调用
IR_Cmd()
,使能 IR 外设。调用
IR_INTConfig()
与IR_MaskINTConfig()
,配置 IR 接收 FIFO 数据个数大于设置的接收阈值中断IR_INT_RF_LEVEL
和接收电平超时中断IR_INT_RX_CNT_THR
。配置 NVIC,详情参考参考 中断配置。调用
RCC_PeriphClockCmd()
,开启 TIM 时钟。对 TIM 外设进行初始化:
定义
TIM_TimeBaseInitTypeDef
类型TIM_InitStruct
,调用TIM_StructInit()
将TIM_InitStruct
预填默认值。根据需求修改
TIM_InitStruct
参数,TIM 的初始化参数配置如下表。调用
TIM_TimeBaseInit()
,初始化 TIM 外设。
TIM Hardware Parameters |
Setting in the |
TIM |
---|---|---|
TIM Mode |
||
PWM Enable |
||
PWM High Count |
|
|
PWM Low Count |
|
功能实现
IR 通过中断接收数据的流程如图所示:

IR 中断接收数据流程图
在
ir_demo
中,循环使能与失能 PWM 输出,模拟 IR 载波数据。循环 50 次之后,PWM 会停止输出波形。
void ir_demo(void)
{
...
for (uint32_t i = 0; i < 50; i++)
{
TIM_Cmd(PWM_TIMER_NUM, ENABLE);
platform_delay_us(500);
TIM_Cmd(PWM_TIMER_NUM, DISABLE);
platform_delay_us(500);
}
}
当 IR 接收 FIFO 的数据个数达到设置的接收阈值时,触发
IR_INT_RF_LEVEL
中断。在中断内调用IR_GetRxDataLen()
与IR_ReceiveBuf()
,接收当前 IR 数据。当 PWM 停止输出波形后,当 IR 检测到超过设置的
IR_InitTypeDef::IR_RxCntThr
载波周期的低电平长度时,触发IR_INT_RX_CNT_THR
中断。在中断内调用IR_GetRxDataLen()
与IR_ReceiveBuf()
,接收剩余的 IR 数据。void IR_Handler(void) { uint16_t len = 0; ITStatus int_status_rfl = IR_GetINTStatus(IR_INT_RF_LEVEL); ITStatus int_status_rxcnt = IR_GetINTStatus(IR_INT_RX_CNT_THR); /* Mask IR all interrupt */ IR_MaskINTConfig(IR_INT_RF_LEVEL | IR_INT_RX_CNT_THR, ENABLE); /* Receive by interrupt */ 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; ... 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); }