[活动专区] 【AT-START-L021测评】8、IRTMR红外发送器

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

红外发射器(IR)
AT32L021器件提供了红外发射器解决方案。该解决方案基于TMR16与TMR17间的内部连接。
TMR17用于提供载波频率,TMR16提供要发送的主信号。

为生成红外遥控信号,必须正确配置TMR16通道1和TMR17通道1以生成正确的波形。所有标准红外
脉冲调制模式都可通过编程两个定时器输出比较通道获得。

24.png

25.png
IR 数字接口可向红外二极管驱动电路输出数字信号。它可以输出任何现有调制类型的信号,
调制类型取决于软件算法。
IR 接口非常容易配置,它使用两个 定时器(TIM16 和 TIM17)提供的两个信号。
TIM17 用于提供载波频率( 36 kHz 或 40 kHz载波频率),TIM16 用于提供要发送的实际信号。

26.png

发送电路
28.png

1.初始化
  1. void infrared_transmitter_init(void)
  2. {
  3.   tmr_output_config_type tmr_oc_init_structure;
  4.   crm_clocks_freq_type crm_clocks_freq_struct = {0};
  5.   gpio_init_type gpio_init_struct;
  6.   
  7.   /* scfg clock enable */
  8.   crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK, TRUE);

  9.   /* TMR16 clock enable */
  10.   crm_periph_clock_enable(CRM_TMR16_PERIPH_CLOCK, TRUE);

  11.   /* TMR17 clock enable */
  12.   crm_periph_clock_enable(CRM_TMR17_PERIPH_CLOCK, TRUE);

  13.   /* gpioa gpiob clock enable */
  14.   crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

  15.   /* gpiob gpiob clock enable */
  16.   crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

  17.   crm_clocks_freq_get(&crm_clocks_freq_struct);
  18.   
  19.   gpio_default_para_init(&gpio_init_struct);

  20.   gpio_init_struct.gpio_pins = GPIO_PINS_6 | GPIO_PINS_7;
  21.   gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  22.   gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  23.   gpio_init(GPIOA, &gpio_init_struct);

  24.   gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE6, GPIO_MUX_5);
  25.   gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE7, GPIO_MUX_5);

  26.   gpio_init_struct.gpio_pins = GPIO_PINS_9;
  27.   gpio_init(GPIOB, &gpio_init_struct);

  28.   gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE9, GPIO_MUX_0);
  29.   
  30.   /* irtmr configuration */
  31.   scfg_infrared_config(SCFG_IR_SOURCE_TMR16, SCFG_IR_POLARITY_REVERSE);

  32.   /* compute the prescaler value */
  33.   prescalervalue = (uint16_t) ((crm_clocks_freq_struct.apb1_freq) / 380000) - 1;

  34.   /* TMR16 time base configuration */
  35.   tmr_base_init(TMR16, 99, prescalervalue);
  36.   tmr_cnt_dir_set(TMR16, TMR_COUNT_UP);
  37.   tmr_clock_source_div_set(TMR16, TMR_CLOCK_DIV1);

  38.   tmr_output_default_para_init(&tmr_oc_init_structure);
  39.   tmr_oc_init_structure.oc_mode = TMR_OUTPUT_CONTROL_FORCE_LOW;
  40.   tmr_oc_init_structure.oc_idle_state = FALSE;
  41.   tmr_oc_init_structure.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
  42.   tmr_oc_init_structure.oc_output_state = TRUE;
  43.   tmr_output_channel_config(TMR16, TMR_SELECT_CHANNEL_1, &tmr_oc_init_structure);
  44.   tmr_channel_value_set(TMR16, TMR_SELECT_CHANNEL_1, 50);
  45.   tmr_output_channel_buffer_enable(TMR16, TMR_SELECT_CHANNEL_1, TRUE);

  46.   tmr_period_buffer_enable(TMR16, TRUE);

  47.   /* TMR17 time base configuration */
  48.   tmr_base_init(TMR17, 8, prescalervalue);
  49.   tmr_cnt_dir_set(TMR17, TMR_COUNT_UP);
  50.   tmr_clock_source_div_set(TMR17, TMR_CLOCK_DIV1);

  51.   tmr_output_default_para_init(&tmr_oc_init_structure);
  52.   tmr_oc_init_structure.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
  53.   tmr_oc_init_structure.oc_idle_state = FALSE;
  54.   tmr_oc_init_structure.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
  55.   tmr_oc_init_structure.oc_output_state = TRUE;
  56.   tmr_output_channel_config(TMR17, TMR_SELECT_CHANNEL_1, &tmr_oc_init_structure);
  57.   tmr_channel_value_set(TMR17, TMR_SELECT_CHANNEL_1, 3);
  58.   tmr_output_channel_buffer_enable(TMR17, TMR_SELECT_CHANNEL_1, TRUE);

  59.   tmr_period_buffer_enable(TMR17, TRUE);

  60.   tmr_output_enable(TMR16, TRUE);
  61.   tmr_output_enable(TMR17, TRUE);

  62.   /* tmr enable counter */
  63.   tmr_counter_enable(TMR16, TRUE);
  64.   tmr_counter_enable(TMR17, TRUE);
  65. }
时钟使能:启用了系统配置(scfg)、定时器16(TMR16)、定时器17(TMR17)、GPIOA和GPIOB的外设时钟
GPIO初始化:初始化GPIOA的6号和7号引脚,以及GPIOB的9号引脚
红外配置:通过scfg_infrared_config函数配置红外发射器的源为TMR16,并且设置红外信号的反向极性(SCFG_IR_POLARITY_REVERSE)。

定时器配置:
计算TMR16的预分频值。配置TMR16和TMR17的时间基数,包括预分频值、计数方向(向上计数)和时钟源分频(不分频)。
TMR16的输出通道1被配置为用于实际信号生成。
TMR17的输出通道1被配置为PWM模式A,用于载波信号生成。



2.红外发送函数
基于NEC协议
  1. void infrared_transmit(uint8_t addr, uint8_t command)
  2. {
  3.   uint8_t bit;
  4.   
  5.   /* send start code */
  6.   tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_HIGH);
  7.   delay_us(9000);
  8.   tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_LOW);
  9.   delay_us(4500);
  10.   
  11.   /* send data */
  12.   for(bit = 8; bit > 0; bit--)
  13.     infrared_transmit_bit((addr>>(bit-1))&0x01);
  14.   
  15.   for(bit = 8; bit > 0; bit--)
  16.     infrared_transmit_bit((~addr>>(bit-1))&0x01);

  17.   for(bit = 8; bit > 0; bit--)
  18.     infrared_transmit_bit((command>>(bit-1))&0x01);
  19.   
  20.   for(bit = 8; bit > 0; bit--)
  21.     infrared_transmit_bit((~command>>(bit-1))&0x01);
  22.   
  23.   /* send end code */
  24.   tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_HIGH);
  25.   delay_us(560);
  26.   tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_LOW);
  27. }
27.png
发送的数据格式可以参照上图。

发送1bit函数:
  1. void infrared_transmit_bit(uint8_t data)
  2. {
  3.         if(data != 0)
  4.         {
  5.     tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_HIGH);
  6.     delay_us(560);
  7.     tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_LOW);
  8.     delay_us(1690);
  9.         }
  10.         else
  11.         {
  12.     tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_HIGH);
  13.     delay_us(560);
  14.     tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_LOW);
  15.     delay_us(560);
  16.         }
  17. }
3.main函数
  1. /* initialize button */
  2.   at32_button_init();
  3.   
  4.   infrared_transmitter_init();
  5.         
  6. /* initialize infrared receiver*/
  7.   infrared_receiver_init();
  8. /* display information */
  9.   printf("Infrared receiver Test\r\n");
  10. while(1)
  11. {
  12. if(infrared_receive(&ir_value) == SUCCESS)
  13.     {
  14.       /* display address and cmd */
  15.       printf("address: %d\r\n", (uint8_t)(ir_value >> 8));

  16.       printf("cmd: %d\r\n\r\n", (uint8_t)(ir_value & 0xFF));
  17.                         
  18. if(at32_button_press()==USER_BUTTON)
  19.     {
  20.       button_cnt++;
  21.       infrared_transmit(0x01, button_cnt);
  22.     }
  23. }
at32_button_init();初始化USR button
在USER BUTTON按下时,执行infrared_transmit(0x01, button_cnt);,发送0x01,button_cnt
if(infrared_receive(&ir_value) == SUCCESS),负责接收,并串口输出结果


4.运行效果

23.jpg
由于手头没有红外发光二极管,因此用普通发光二极管替换,发射非可见光能力有限,发送器和接收器必须靠得很近才能收到数据。
24.jpg

接收器的输出:
29.png



48012674801b5aa5a1.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

84

主题

147

帖子

3

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