[活动专区] 【AT-START-L021测评】7、定时器捕获实现红外接收

[复制链接]
 楼主| sujingliang 发表于 2024-11-28 11:23 | 显示全部楼层 |阅读模式
本帖最后由 sujingliang 于 2024-11-28 13:05 编辑

使用定时器捕获功能来实现红外接收是一种常见的方法。红外接收通常涉及到一个红外接收二极管(IR receiver diode),它能够将接收到的红外信号转换为电信号。然后,这个电信号可以通过微控制器的定时器捕获功能进行解码和处理。
以下是一个基本的步骤指南,用于实现基于定时器捕获的红外接收:
1. 硬件准备
  • 红外接收二极管:用于接收红外信号。
  • 21.png
  • 微控制器:具有定时器捕获功能的MCU。
  • 电阻和电容:用于电路滤波和限流。
  • 红外遥控器:用于发送测试信号。
2. 电路连接
  • 将红外接收二极管的输出端连接到微控制器的一个GPIO引脚,该引脚应配置为定时器捕获输入。
  • 根据需要添加适当的电阻和电容进行滤波。
  • 22.png
3. 配置定时器捕获
  • 选择定时器:在微控制器的数据手册中选择一个合适的定时器,该定时器应支持输入捕获功能。
  • 配置输入捕获
    • 设置捕获通道的输入模式(如上升沿捕获、下降沿捕获或两者都捕获)。
    • 配置定时器的预分频器和计数器模式。
  1. void infrared_receiver_init(void)
  2. {
  3.   gpio_init_type gpio_init_struct;
  4.   tmr_input_config_type  tmr_input_config_struct;
  5.   crm_clocks_freq_type   crm_clock_freq;

  6.   /* init infrared receiver fifo */
  7.   infrared_receiver_fifo_init();

  8.   /* enable tmr3/gpioa clock */
  9.   crm_periph_clock_enable(IR_TMR_CLK, TRUE);
  10.   crm_periph_clock_enable(IR_GPIO_CLK, TRUE);

  11.   /* timer input pin Configuration */
  12.   gpio_init_struct.gpio_pins = IR_GPIO_PIN;
  13.   gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  14.   gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  15.   gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  16.   gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  17.   gpio_init(IR_GPIO_PORT, &gpio_init_struct);

  18.   gpio_pin_mux_config(IR_GPIO_PORT, IR_GPIO_PINS_SOURCE, IR_GPIO_MUX);

  19.   /* get the system frequency value */
  20.   crm_clocks_freq_get(&crm_clock_freq);

  21.   /* tmr counter mode configuration */
  22.   tmr_base_init(IR_TMRx, 6000, crm_clock_freq.apb1_freq / 1000000);
  23.   tmr_cnt_dir_set(IR_TMRx, TMR_COUNT_UP);

  24.   /* configure tmr channel to get clock signal */
  25.   tmr_input_config_struct.input_channel_select = IR_TMR_CHANNEL;
  26.   tmr_input_config_struct.input_mapped_select = TMR_CC_CHANNEL_MAPPED_DIRECT;
  27.   tmr_input_config_struct.input_polarity_select = TMR_INPUT_RISING_EDGE;
  28.   tmr_input_channel_init(IR_TMRx, &tmr_input_config_struct, TMR_CHANNEL_INPUT_DIV_1);

  29.   /* enable capture interrupt */
  30.   tmr_interrupt_enable(IR_TMRx, IR_TMR_CHANNEL_INT, TRUE);

  31.   /* disable overflow interrupt */
  32.   tmr_interrupt_enable(IR_TMRx, TMR_OVF_INT, FALSE);

  33.   /* interrupt nvic init */
  34.   nvic_irq_enable(IR_TMR_IRQn, 1, 0);

  35.   /* enable tmr */
  36.   tmr_counter_enable(IR_TMRx, TRUE);
  37. }
这里设置定时器TMR3,通道2,配置红外接收引脚:PB5
23.png
4. 编写软件
  • 初始化定时器捕获:配置定时器和捕获通道。(如前)
  • 处理捕获中断:在捕获中断服务程序中读取捕获寄存器的值,并处理这些值以解码红外信号。
  • 解码红外信号:根据红外协议(如NEC、Sony、Philips等)解析捕获的时间间隔,以识别按键代码。
定义
  1. #define IR_GPIO_PORT                    GPIOB
  2. #define IR_GPIO_CLK                     CRM_GPIOB_PERIPH_CLOCK
  3. #define IR_GPIO_PIN                     GPIO_PINS_5
  4. #define IR_GPIO_PINS_SOURCE             GPIO_PINS_SOURCE5
  5. #define IR_GPIO_MUX                     GPIO_MUX_1

  6. #define IR_TMRx                         TMR3
  7. #define IR_TMR_CLK                      CRM_TMR3_PERIPH_CLOCK
  8. #define IR_TMR_CHANNEL                  TMR_SELECT_CHANNEL_2
  9. #define IR_TMR_CHANNEL_INT              TMR_C2_INT
  10. #define IR_TMR_CHANNEL_FLAG             TMR_C2_FLAG
  11. #define IR_TMR_IRQn                     TMR3_GLOBAL_IRQn
  12. #define IR_TMR_IRQHandler               TMR3_GLOBAL_IRQHandler

  13. #define IR_GPIO_READ()                  (gpio_input_data_bit_read(IR_GPIO_PORT, IR_GPIO_PIN) != RESET)



中断函数:
  1. void IR_TMR_IRQHandler(void)
  2. {
  3.   infrared_receiver_data_deal();
  4. }


infrared_receiver_data_deal,NEC协议解析:
  1. void infrared_receiver_data_deal(void)
  2. {
  3.   uint32_t value;
  4.   static uint32_t ir_data = 0;

  5.   /* input capture event occurs */
  6.   if(tmr_flag_get(IR_TMRx, IR_TMR_CHANNEL_FLAG) != RESET)
  7.   {
  8.     /* clear input capture flag */
  9.     tmr_flag_clear(IR_TMRx, IR_TMR_CHANNEL_FLAG);

  10.     /* clear overflow flag */
  11.     tmr_flag_clear(IR_TMRx, TMR_OVF_FLAG);

  12.     /* enable overflow interrupt */
  13.     tmr_interrupt_enable(IR_TMRx, TMR_OVF_INT, TRUE);

  14.     /* rising edge capture */
  15.     if(IR_GPIO_READ())
  16.     {
  17.       /* clear the counter */
  18.       tmr_counter_value_set(IR_TMRx, 0);

  19.       /* configure capture mode as falling edge capture */
  20.       tmr_output_channel_polarity_set(IR_TMRx, IR_TMR_CHANNEL, TMR_POLARITY_ACTIVE_LOW);
  21.     }
  22.     /* falling edge capture */
  23.     else
  24.     {
  25.       /* get capture counter */
  26.       value = tmr_channel_value_get(IR_TMRx, IR_TMR_CHANNEL);

  27.       /* configure capture mode as rising edge capture */
  28.       tmr_output_channel_polarity_set(IR_TMRx, IR_TMR_CHANNEL, TMR_POLARITY_ACTIVE_HIGH);

  29.       /* received start code */
  30.       if((value > 4200) && (value < 4700))
  31.       {
  32.         ir_data = 0;
  33.       }
  34.       /* received repeat code */
  35.       else if((value > 2000) && (value < 2600))
  36.       {
  37.         /* analysis data */
  38.         infrared_receiver_key_deal(ir_data);
  39.       }
  40.       /* received bit 0 */
  41.       else if((value > 300) && (value < 800))
  42.       {
  43.         ir_data <<= 1;
  44.       }
  45.       /* received bit 1 */
  46.       else if((value > 1400) && (value < 1800))
  47.       {
  48.         ir_data <<= 1;
  49.         ir_data |= 1;
  50.       }
  51.     }
  52.   }

  53.   /* overflow event occurs, 6ms , receive complete */
  54.   else if(tmr_flag_get(IR_TMRx, TMR_OVF_FLAG) != RESET)
  55.   {
  56.     /* clear overflow flag */
  57.     tmr_flag_clear(IR_TMRx, TMR_OVF_FLAG);

  58.     /* disable overflow interrupt */
  59.     tmr_interrupt_enable(IR_TMRx, TMR_OVF_INT, FALSE);

  60.     /* configure capture mode as rising edge capture */
  61.     tmr_output_channel_polarity_set(IR_TMRx, IR_TMR_CHANNEL, TMR_POLARITY_ACTIVE_HIGH);

  62.     /* analysis data */
  63.     infrared_receiver_key_deal(ir_data);
  64.   }
  65. }
main函数调用:

根据接收到的红外数据翻转LED
  1. if(infrared_receive(&ir_value) == SUCCESS)
  2.     {
  3.       /* display address and cmd */
  4.       printf("address: %d\r\n", (uint8_t)(ir_value >> 8));

  5.       printf("cmd: %d\r\n\r\n", (uint8_t)(ir_value & 0xFF));
  6.                         
  7.                         switch(ir_value & 0xFF)
  8.                         {
  9.                         case 224:
  10.                                 at32_led_toggle(LED2);
  11.                                 break;
  12.                         case 192:
  13.                                 at32_led_toggle(LED3);
  14.                                 break;
  15.                         case 200:
  16.                                 at32_led_toggle(LED4);
  17.                                 break;
  18.                         }
  19.     }



5. 运行效果
红外接收电路:
21.jpg

红外电路接MCU的PB5、GND
22.jpg


用风扇遥控器做为红外发送器,发送内容固定,前3个键分别对应224、192、200,接收器收到信号后,翻转LED
tutieshi_480x270_8s.gif
日志输出:

23.png


您需要登录后才可以回帖 登录 | 注册

本版积分规则

84

主题

146

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部

84

主题

146

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部