本帖最后由 sujingliang 于 2024-11-28 13:47 编辑
红外发射器(IR)
AT32L021器件提供了红外发射器解决方案。该解决方案基于TMR16与TMR17间的内部连接。
TMR17用于提供载波频率,TMR16提供要发送的主信号。
为生成红外遥控信号,必须正确配置TMR16通道1和TMR17通道1以生成正确的波形。所有标准红外
脉冲调制模式都可通过编程两个定时器输出比较通道获得。
IR 数字接口可向红外二极管驱动电路输出数字信号。它可以输出任何现有调制类型的信号,
调制类型取决于软件算法。
IR 接口非常容易配置,它使用两个 定时器(TIM16 和 TIM17)提供的两个信号。
TIM17 用于提供载波频率( 36 kHz 或 40 kHz载波频率),TIM16 用于提供要发送的实际信号。
发送电路
1.初始化
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.运行效果
由于手头没有红外发光二极管,因此用普通发光二极管替换,发射非可见光能力有限,发送器和接收器必须靠得很近才能收到数据。
接收器的输出:
|
|