#include "ir.h" timer_ic_parameter_struct timer_icinitpara; // 遥控器接收状态 //[7]:收到了引导码标志 //[6]:得到了一个按键的所有信息 //[5]:保留 //[4]:标记上升沿是否已经被捕获 //[3:0]:溢出计时器 uint8_t RmtSta = 0; uint16_t Dval; // 下降沿时计数器的值 uint32_t RmtRec = 0; // 红外接收到的数据 uint8_t RmtCnt = 0; // 按键按下的次数 /* 红外遥控初始化 */ void ir_init(void) { rcu_periph_clock_enable(RCU_AF); /*configure PA6 (TIMER2 CH0) as alternate function*/ gpio_config(IR_IN_PERIPH, IR_IN_PIN, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, nullptr); nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3); nvic_irq_enable(TIMER2_IRQn, 1, 1); /* TIMER2 configuration: PWM input mode ------------------------ the external signal is connected to TIMER2 CH0 pin(PA6) the rising edge is used as active edge the TIMER2 CH0CV is used to compute the frequency value the TIMER2 CH1CV is used to compute the duty cycle value ------------------------------------------------------------ */ timer_parameter_struct timer_initpara; rcu_periph_clock_enable(RCU_TIMER2); timer_deinit(TIMER2); /* TIMER2 configuration */ timer_initpara.prescaler = 107; timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.counterdirection = TIMER_COUNTER_UP; timer_initpara.period = 65535; timer_initpara.clockdivision = TIMER_CKDIV_DIV1; timer_initpara.repetitioncounter = 0; timer_init(TIMER2, &timer_initpara); /* TIMER2 configuration */ /* TIMER2 CH0 PWM input capture configuration */ timer_icinitpara.icpolarity = TIMER_IC_POLARITY_RISING; timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI; timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1; timer_icinitpara.icfilter = 0x00; timer_input_pwm_capture_config(TIMER2, TIMER_CH_0, &timer_icinitpara); /* auto-reload preload enable */ timer_auto_reload_shadow_enable(TIMER2); /* clear channel 0 interrupt bit */ timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_CH0 | TIMER_INT_FLAG_UP); /* channel 0 interrupt enable */ timer_interrupt_enable(TIMER2, TIMER_INT_CH0 | TIMER_INT_FLAG_UP); /* TIMER2 counter enable */ timer_enable(TIMER2); } void ir_process(void) { uint8_t sta = 0; uint8_t t1, t2; if (RmtSta & (1 << 6)) // 得到一个按键的所有信息了 { t1 = RmtRec >> 24; // 得到地址码 t2 = (RmtRec >> 16) & 0xff; // 得到地址反码 if (t1 == (uint8_t)~t2 && t1 == IR_ID) // 检验遥控识别码(ID)及地址 { t1 = RmtRec >> 8; // 得到控制码 t2 = RmtRec; // 得到控制反码 if (t1 == (uint8_t)~t2) { sta = t1; // 键值正确 ir_key_triggered(sta); RmtSta &= ~(1 << 6); // 清除接收到有效按键标识 RmtCnt = 0; // 清除按键次数计数器 } } if ((sta == 0) || ((RmtSta & 0X80) == 0)) // 按键数据错误/遥控已经没有按下了 { RmtSta &= ~(1 << 6); // 清除接收到有效按键标识 RmtCnt = 0; // 清除按键次数计数器 } } } __weak void ir_key_triggered(uint8_t key) {} void TIMER2_IRQHandler(void) { if (SET == timer_interrupt_flag_get(TIMER2, TIMER_INT_FLAG_CH0)) { /* 捕获到上升没沿,读取GPIO PIN状态当为1时是上升沿 */ if (gpio_input_bit_get(IR_IN_PERIPH, IR_IN_PIN)) { /* 设置为下降沿捕获 */ timer_icinitpara.icpolarity = TIMER_IC_POLARITY_FALLING; timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI; timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1; timer_icinitpara.icfilter = 0; timer_input_capture_config(TIMER2, TIMER_CH_0, &timer_icinitpara); /* 清空定时器值 */ timer_counter_value_config(TIMER2, 0); /* 标记上升沿已经被捕获 */ RmtSta |= 0X10; } else { Dval = timer_counter_read(TIMER2); /* 设置为上升沿捕获 */ timer_icinitpara.icpolarity = TIMER_IC_POLARITY_RISING; timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI; timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1; timer_icinitpara.icfilter = 0; timer_input_capture_config(TIMER2, TIMER_CH_0, &timer_icinitpara); /* 完成一次高电平捕获 */ if (RmtSta & 0X10) { /* 接收到了引导码 */ if (RmtSta & 0X80) { /* 标准值为560us */ if (Dval > 300 && Dval < 800) { /* 左移一位, 接收到 0 */ RmtRec <<= 1; RmtRec |= 0; } /* 标准值为1680us */ else if (Dval > 1400 && Dval < 1800) { /* 左移一位, 接收到 1 */ RmtRec <<= 1; RmtRec |= 1; } else if (Dval > 2200 && Dval < 2600) // 得到按键键值增加的信息 2500为标准值2.5ms { RmtCnt++; // 按键次数增加1次 RmtSta &= 0XF0; // 清空计时器 } } else if (Dval > 4200 && Dval < 4700) // 4500为标准值4.5ms { RmtSta |= 1 << 7; // 标记成功接收到了引导码 RmtCnt = 0; // 清除按键次数计数器 } } RmtSta &= ~(1 << 4); } /* clear channel 0 interrupt bit */ timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_CH0); } if (SET == timer_interrupt_flag_get(TIMER2, TIMER_INT_FLAG_UP)) // 定时器超时,没有获捕获到任何信号 { if (RmtSta & 0x80) // 上次有数据被接收到了 { RmtSta &= ~0X10; // 取消上升沿已经被捕获标记 if ((RmtSta & 0X0F) == 0X00) RmtSta |= 1 << 6; // 标记已经完成一次按键的键值信息采集 if ((RmtSta & 0X0F) < 14) RmtSta++; else { RmtSta &= ~(1 << 7); // 清空引导标识 RmtSta &= 0XF0; // 清空计数器 } } timer_icinitpara.icpolarity = TIMER_IC_POLARITY_RISING; timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI; timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1; timer_icinitpara.icfilter = 0; timer_input_capture_config(TIMER2, TIMER_CH_0, &timer_icinitpara); timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP); } }