- void infrared_transmitter_init(void)
- {
- tmr_output_config_type tmr_oc_init_structure;
- crm_clocks_freq_type crm_clocks_freq_struct = {0};
- gpio_init_type gpio_init_struct;
-
- /* scfg clock enable */
- crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK, TRUE);
- /* TMR16 clock enable */
- crm_periph_clock_enable(CRM_TMR16_PERIPH_CLOCK, TRUE);
- /* TMR17 clock enable */
- crm_periph_clock_enable(CRM_TMR17_PERIPH_CLOCK, TRUE);
- /* gpioa gpiob clock enable */
- crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
- /* gpiob gpiob clock enable */
- crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
- crm_clocks_freq_get(&crm_clocks_freq_struct);
-
- gpio_default_para_init(&gpio_init_struct);
- gpio_init_struct.gpio_pins = GPIO_PINS_6 | GPIO_PINS_7;
- gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
- gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
- gpio_init(GPIOA, &gpio_init_struct);
- gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE6, GPIO_MUX_5);
- gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE7, GPIO_MUX_5);
- gpio_init_struct.gpio_pins = GPIO_PINS_9;
- gpio_init(GPIOB, &gpio_init_struct);
- gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE9, GPIO_MUX_0);
-
- /* irtmr configuration */
- scfg_infrared_config(SCFG_IR_SOURCE_TMR16, SCFG_IR_POLARITY_REVERSE);
- /* compute the prescaler value */
- prescalervalue = (uint16_t) ((crm_clocks_freq_struct.apb1_freq) / 380000) - 1;
- /* TMR16 time base configuration */
- tmr_base_init(TMR16, 99, prescalervalue);
- tmr_cnt_dir_set(TMR16, TMR_COUNT_UP);
- tmr_clock_source_div_set(TMR16, TMR_CLOCK_DIV1);
- tmr_output_default_para_init(&tmr_oc_init_structure);
- tmr_oc_init_structure.oc_mode = TMR_OUTPUT_CONTROL_FORCE_LOW;
- tmr_oc_init_structure.oc_idle_state = FALSE;
- tmr_oc_init_structure.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
- tmr_oc_init_structure.oc_output_state = TRUE;
- tmr_output_channel_config(TMR16, TMR_SELECT_CHANNEL_1, &tmr_oc_init_structure);
- tmr_channel_value_set(TMR16, TMR_SELECT_CHANNEL_1, 50);
- tmr_output_channel_buffer_enable(TMR16, TMR_SELECT_CHANNEL_1, TRUE);
- tmr_period_buffer_enable(TMR16, TRUE);
- /* TMR17 time base configuration */
- tmr_base_init(TMR17, 8, prescalervalue);
- tmr_cnt_dir_set(TMR17, TMR_COUNT_UP);
- tmr_clock_source_div_set(TMR17, TMR_CLOCK_DIV1);
- tmr_output_default_para_init(&tmr_oc_init_structure);
- tmr_oc_init_structure.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
- tmr_oc_init_structure.oc_idle_state = FALSE;
- tmr_oc_init_structure.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
- tmr_oc_init_structure.oc_output_state = TRUE;
- tmr_output_channel_config(TMR17, TMR_SELECT_CHANNEL_1, &tmr_oc_init_structure);
- tmr_channel_value_set(TMR17, TMR_SELECT_CHANNEL_1, 3);
- tmr_output_channel_buffer_enable(TMR17, TMR_SELECT_CHANNEL_1, TRUE);
- tmr_period_buffer_enable(TMR17, TRUE);
- tmr_output_enable(TMR16, TRUE);
- tmr_output_enable(TMR17, TRUE);
- /* tmr enable counter */
- tmr_counter_enable(TMR16, TRUE);
- tmr_counter_enable(TMR17, TRUE);
- }
时钟使能:启用了系统配置(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协议
- void infrared_transmit(uint8_t addr, uint8_t command)
- {
- uint8_t bit;
-
- /* send start code */
- tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_HIGH);
- delay_us(9000);
- tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_LOW);
- delay_us(4500);
-
- /* send data */
- for(bit = 8; bit > 0; bit--)
- infrared_transmit_bit((addr>>(bit-1))&0x01);
-
- for(bit = 8; bit > 0; bit--)
- infrared_transmit_bit((~addr>>(bit-1))&0x01);
- for(bit = 8; bit > 0; bit--)
- infrared_transmit_bit((command>>(bit-1))&0x01);
-
- for(bit = 8; bit > 0; bit--)
- infrared_transmit_bit((~command>>(bit-1))&0x01);
-
- /* send end code */
- tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_HIGH);
- delay_us(560);
- tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_LOW);
- }
发送的数据格式可以参照上图。
发送1bit函数:
- void infrared_transmit_bit(uint8_t data)
- {
- if(data != 0)
- {
- tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_HIGH);
- delay_us(560);
- tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_LOW);
- delay_us(1690);
- }
- else
- {
- tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_HIGH);
- delay_us(560);
- tmr_output_channel_mode_select(TMR16, TMR_SELECT_CHANNEL_1, TMR_OUTPUT_CONTROL_FORCE_LOW);
- delay_us(560);
- }
- }
3.main函数
- /* initialize button */
- at32_button_init();
-
- infrared_transmitter_init();
-
- /* initialize infrared receiver*/
- infrared_receiver_init();
- /* display information */
- printf("Infrared receiver Test\r\n");
- while(1)
- {
- 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));
-
- if(at32_button_press()==USER_BUTTON)
- {
- button_cnt++;
- infrared_transmit(0x01, button_cnt);
- }
- }
at32_button_init();初始化USR button
在USER BUTTON按下时,执行infrared_transmit(0x01, button_cnt);,发送0x01,button_cnt
if(infrared_receive(&ir_value) == SUCCESS),负责接收,并串口输出结果
4.运行效果
由于手头没有红外发光二极管,因此用普通发光二极管替换,发射非可见光能力有限,发送器和接收器必须靠得很近才能收到数据。
接收器的输出: