本帖最后由 sujingliang 于 2024-11-28 13:05 编辑
使用定时器捕获功能来实现红外接收是一种常见的方法。红外接收通常涉及到一个红外接收二极管(IR receiver diode),它能够将接收到的红外信号转换为电信号。然后,这个电信号可以通过微控制器的定时器捕获功能进行解码和处理。 以下是一个基本的步骤指南,用于实现基于定时器捕获的红外接收: 1. 硬件准备- 红外接收二极管:用于接收红外信号。
-
- 微控制器:具有定时器捕获功能的MCU。
- 电阻和电容:用于电路滤波和限流。
- 红外遥控器:用于发送测试信号。
2. 电路连接- 将红外接收二极管的输出端连接到微控制器的一个GPIO引脚,该引脚应配置为定时器捕获输入。
- 根据需要添加适当的电阻和电容进行滤波。
-
3. 配置定时器捕获- 选择定时器:在微控制器的数据手册中选择一个合适的定时器,该定时器应支持输入捕获功能。
- 配置输入捕获:
- 设置捕获通道的输入模式(如上升沿捕获、下降沿捕获或两者都捕获)。
- 配置定时器的预分频器和计数器模式。
void infrared_receiver_init(void)
{
gpio_init_type gpio_init_struct;
tmr_input_config_type tmr_input_config_struct;
crm_clocks_freq_type crm_clock_freq;
/* init infrared receiver fifo */
infrared_receiver_fifo_init();
/* enable tmr3/gpioa clock */
crm_periph_clock_enable(IR_TMR_CLK, TRUE);
crm_periph_clock_enable(IR_GPIO_CLK, TRUE);
/* timer input pin Configuration */
gpio_init_struct.gpio_pins = IR_GPIO_PIN;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init(IR_GPIO_PORT, &gpio_init_struct);
gpio_pin_mux_config(IR_GPIO_PORT, IR_GPIO_PINS_SOURCE, IR_GPIO_MUX);
/* get the system frequency value */
crm_clocks_freq_get(&crm_clock_freq);
/* tmr counter mode configuration */
tmr_base_init(IR_TMRx, 6000, crm_clock_freq.apb1_freq / 1000000);
tmr_cnt_dir_set(IR_TMRx, TMR_COUNT_UP);
/* configure tmr channel to get clock signal */
tmr_input_config_struct.input_channel_select = IR_TMR_CHANNEL;
tmr_input_config_struct.input_mapped_select = TMR_CC_CHANNEL_MAPPED_DIRECT;
tmr_input_config_struct.input_polarity_select = TMR_INPUT_RISING_EDGE;
tmr_input_channel_init(IR_TMRx, &tmr_input_config_struct, TMR_CHANNEL_INPUT_DIV_1);
/* enable capture interrupt */
tmr_interrupt_enable(IR_TMRx, IR_TMR_CHANNEL_INT, TRUE);
/* disable overflow interrupt */
tmr_interrupt_enable(IR_TMRx, TMR_OVF_INT, FALSE);
/* interrupt nvic init */
nvic_irq_enable(IR_TMR_IRQn, 1, 0);
/* enable tmr */
tmr_counter_enable(IR_TMRx, TRUE);
}
这里设置定时器TMR3,通道2,配置红外接收引脚:PB5
4. 编写软件- 初始化定时器捕获:配置定时器和捕获通道。(如前)
- 处理捕获中断:在捕获中断服务程序中读取捕获寄存器的值,并处理这些值以解码红外信号。
- 解码红外信号:根据红外协议(如NEC、Sony、Philips等)解析捕获的时间间隔,以识别按键代码。
定义
#define IR_GPIO_PORT GPIOB
#define IR_GPIO_CLK CRM_GPIOB_PERIPH_CLOCK
#define IR_GPIO_PIN GPIO_PINS_5
#define IR_GPIO_PINS_SOURCE GPIO_PINS_SOURCE5
#define IR_GPIO_MUX GPIO_MUX_1
#define IR_TMRx TMR3
#define IR_TMR_CLK CRM_TMR3_PERIPH_CLOCK
#define IR_TMR_CHANNEL TMR_SELECT_CHANNEL_2
#define IR_TMR_CHANNEL_INT TMR_C2_INT
#define IR_TMR_CHANNEL_FLAG TMR_C2_FLAG
#define IR_TMR_IRQn TMR3_GLOBAL_IRQn
#define IR_TMR_IRQHandler TMR3_GLOBAL_IRQHandler
#define IR_GPIO_READ() (gpio_input_data_bit_read(IR_GPIO_PORT, IR_GPIO_PIN) != RESET)
中断函数:
void IR_TMR_IRQHandler(void)
{
infrared_receiver_data_deal();
}
infrared_receiver_data_deal,NEC协议解析:
void infrared_receiver_data_deal(void)
{
uint32_t value;
static uint32_t ir_data = 0;
/* input capture event occurs */
if(tmr_flag_get(IR_TMRx, IR_TMR_CHANNEL_FLAG) != RESET)
{
/* clear input capture flag */
tmr_flag_clear(IR_TMRx, IR_TMR_CHANNEL_FLAG);
/* clear overflow flag */
tmr_flag_clear(IR_TMRx, TMR_OVF_FLAG);
/* enable overflow interrupt */
tmr_interrupt_enable(IR_TMRx, TMR_OVF_INT, TRUE);
/* rising edge capture */
if(IR_GPIO_READ())
{
/* clear the counter */
tmr_counter_value_set(IR_TMRx, 0);
/* configure capture mode as falling edge capture */
tmr_output_channel_polarity_set(IR_TMRx, IR_TMR_CHANNEL, TMR_POLARITY_ACTIVE_LOW);
}
/* falling edge capture */
else
{
/* get capture counter */
value = tmr_channel_value_get(IR_TMRx, IR_TMR_CHANNEL);
/* configure capture mode as rising edge capture */
tmr_output_channel_polarity_set(IR_TMRx, IR_TMR_CHANNEL, TMR_POLARITY_ACTIVE_HIGH);
/* received start code */
if((value > 4200) && (value < 4700))
{
ir_data = 0;
}
/* received repeat code */
else if((value > 2000) && (value < 2600))
{
/* analysis data */
infrared_receiver_key_deal(ir_data);
}
/* received bit 0 */
else if((value > 300) && (value < 800))
{
ir_data <<= 1;
}
/* received bit 1 */
else if((value > 1400) && (value < 1800))
{
ir_data <<= 1;
ir_data |= 1;
}
}
}
/* overflow event occurs, 6ms , receive complete */
else if(tmr_flag_get(IR_TMRx, TMR_OVF_FLAG) != RESET)
{
/* clear overflow flag */
tmr_flag_clear(IR_TMRx, TMR_OVF_FLAG);
/* disable overflow interrupt */
tmr_interrupt_enable(IR_TMRx, TMR_OVF_INT, FALSE);
/* configure capture mode as rising edge capture */
tmr_output_channel_polarity_set(IR_TMRx, IR_TMR_CHANNEL, TMR_POLARITY_ACTIVE_HIGH);
/* analysis data */
infrared_receiver_key_deal(ir_data);
}
}
main函数调用:
根据接收到的红外数据翻转LED
if(infrared_receive(&ir_value) == SUCCESS)
{
/* display address and cmd */
printf("address: %d\r\n", (uint8_t)(ir_value >> 8));
printf("cmd: %d\r\n\r\n", (uint8_t)(ir_value & 0xFF));
switch(ir_value & 0xFF)
{
case 224:
at32_led_toggle(LED2);
break;
case 192:
at32_led_toggle(LED3);
break;
case 200:
at32_led_toggle(LED4);
break;
}
}
5. 运行效果
红外接收电路:
红外电路接MCU的PB5、GND
用风扇遥控器做为红外发送器,发送内容固定,前3个键分别对应224、192、200,接收器收到信号后,翻转LED
日志输出:
|