tips:随手记一些写程序时遇到的小问题,主要内容看纸质笔记。
目的:switch判断各状态,然后通过定时器计时判断时序解析数据,实现红外接收
分配:定时器TIM2;红外接收引脚PB10(开10号中断)GPIO_Mode_IPU
一、红外接收模块IR_Research.c
采用NEC协议,分为引导码、地址码、数据码(0和1),用高低电平时间区分。采用双边沿中断。记录上升沿、下降沿的发生时刻,计算时间解析数据。
1.初始化:常规性的 开GPIO/AFIO的APB总线 + GPIO口配置 + 打开EXTI + EXTI配置 + NVIC配置
2.接收信号:用switch判断处于什么状态,标志位Num_Red,初始置1
#define TIM_Start TIM_Cmd(TIM2, ENABLE) //开启定时器
#define TIM_Stop TIM_Cmd(TIM2, DISABLE) //关闭定时器
#define TIM_Get TIM_GetCounter(TIM2) //获取当前CNT的值
#define TIM_Set TIM_SetCounter(TIM2, 0) //计数器清零
#define NEC_TRIGGER ((GPIOB -> IDR & (1 << 10)) == 0? 0:1)
(1)红外信号来时第一次进中断(下降沿)。此时计数器清零,开启定时器。Num_Red加1指示到下一个状态后,跳出switch
(2)第二次进中断(上升沿)。此时停止定时器,获取当前计数器的值,结合分频和预装判断低电平的时间。符合的话Num_Red加1指示下一个状态后计数器清零,开启定时器;不符合的话Num_Red置1指示初始状态。最后跳出switch
(3)第三次进中断(下降沿)。此时停止定时器,获取当前计数器的值,结合分频和预装判断高电平的时间。符合的话Num_Red加1指示下一个状态,把存储数据的数组memset清零;不符合的话Num_Red置1指示初始状态。最后跳出switch
(4)下面进入中断只要判断高电平时间来确定0还是1就行。通过NEC_TRIGGER标志位判断是上升沿还是下降沿。上升沿的话计数器清零,开启定时器。下降沿的话停止定时器,获取当前计数器的值,符合高电平时间就记录在存储数组里,符合低电平时间什么不做就行默认是0,都不符合的话Num_Red置1指示初始状态。最后跳出switch
switch (Num_Red)
{
case 1: //红外信号来时第一次进中断,开启定时器
TIM_Set;
TIM_Start;
Num_Red++;
break;
case 2: //第二次进中断,判断低电平时间
TIM_Stop;
if((TIM_Get > 8000) && (TIM_Get < 10000)) //9ms
{
Num_Red++;
TIM_Set;
TIM_Start;
}
else{Num_Red = 1;}
break;
case 3: //第三次进中断,判断高电平时间
TIM_Stop;
if((TIM_Get > 3800) && (TIM_Get < 5500)) //4.5ms
{
Num_Red++;
i = 0;
//TIM2 -> CNT =0;
memset(Data_Red_Data, 0, sizeof(Data_Red_Data)); //数组清零
//TIM_Set;
//TIM_Start;
}
else{Num_Red = 1;}
break;
case 4: //判断高电平时间确定0或1
if(NEC_TRIGGER) //上升沿计数器清零
{
TIM_Set;
TIM_Start;
}
else
{
TIM_Stop;
if((TIM_Get > 1200) && (TIM_Get < 2200)) //1.6ms: 1
{
Data_Red_Data[i / 8] |= 1 << (i % 8);
}
else if((TIM_Get > 200) && (TIM_Get < 800)) //0.56ms: 0
{}
else
{
Num_Red = 1;
}
i++;
if(i >= 32){i = 0;}
}
break;
}
3.在EXTI中断函数里,判断中断标志位,然后调用上面那个函数,最后清除标志位
4.定时器中断函数里,判断中断标志位,关闭定时器,各变量给初始值,最后清除标志位
时序很重要!全靠时序读取数据,不然就乱码
思路:结合switch,判断中断上升/下降边沿来计时