红外遥控的编解码以及识别驱动
红外遥控的波形如下图所示:
我用到了stm8单片机中的定时器1,以及红外接收头所对应的中断,中断使用下降沿,主要通过脉冲低电平的时间
不同来区分不同的数据。定时器1来计算连续两次中断的间隔(其对应了相应脉冲的宽度)
根据上述条件,写出的红外遥控识别程序如下:
#include "public.h"
#define PeriodT 25 //T的时间/16us
static u16 OldT1Count=0; //保存计数器1的旧值
static u16 T1Count=0; //保存计数器1的当前值
static u8 BitCount=0; //写入位数值
static u8 NewData; //有没有新的一帧数据到来标志
u8 RecvData[12]; //用于保存接收数据的数组
static u16 u8PulseWidth=0; //计算出的脉冲宽度值
/*******************************************************************************
// Function: vDrv_ExitIntPC4Init()
// Description: 红外按键外部中断PC4
// Author: Huangzhigang 2014-0306
*******************************************************************************/
void vDrv_ExitIntPC4Init()
{
//PC4 中断 输入 浮动
GPIO_Init(GPIOC, GPIO_PIN_4, GPIO_MODE_IN_FL_IT); //红外接收头对应IO口
//EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOC, EXTI_SENSITIVITY_RISE_FALL); //上升沿触发中断
EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOC, EXTI_SENSITIVITY_FALL_ONLY); //下降沿触发中断
}
/*******************************************************************************
// Function: Time1_Init()
// Description: 定时器1初始化配置
// Author: Huangzhigang 2014-0306
*******************************************************************************/
void Time1_Init()
{
TIM1_DeInit();
//向上计数 分频数为256 自动重装载值为0xffff
//256/16= 16us 计数器加一次 加到0xffff 清零重新加
TIM1_TimeBaseInit(255, TIM1_COUNTERMODE_UP, 0xffff, 0);
//允许更新中断
//TIM1_ITConfig(TIM1_IT_UPDATE, ENABLE);
TIM1_Cmd(ENABLE);
}
/*******************************************************************************
// Function: rDrv_PulseWidth
// Description: 计算脉宽
// Param:
// Return: 有宽度返回1 无效宽度返回0
// Others:
// Author: Huangzhigang 2014-0306
*******************************************************************************/
u8 rDrv_PulseWidth() //u8 *PulseWidth
{
T1Count = TIM1_GetCounter();
if(OldT1Count == 0)
{
OldT1Count = T1Count;
u8PulseWidth = 0;
return 0;
}
else
{
if(T1Count - OldT1Count > 0)
{
u8PulseWidth = T1Count-OldT1Count;
OldT1Count = T1Count;
return 1;
}
else
{
u8PulseWidth = 0xffff-OldT1Count+T1Count;
OldT1Count = T1Count;
return 1;
}
}
}
/*******************************************************************************
// Function: vDrv_WriteRecvData
// Description: 将接受的数据写入数组
// Param: u8Bit 写入的值为1还是0
红外遥控器发送数据是先发送高位数据 再发低位数据
// Author: Huangzhigang 2014-0306
*******************************************************************************/
void vDrv_WriteRecvData(u8 u8Bit)
{
u8 Bit = 1;
if(u8Bit)
{
RecvData[BitCount/8] |= Bit<<(7-(BitCount%8)); //对应位写1
}
else
{
RecvData[BitCount/8] &= ~(Bit<<(7-(BitCount%8))); //对应位写0
}
if(++BitCount > 95)
{
NewData=0;
BitCount=0;
}
}
/*******************************************************************************
// Function: Interrupt_Remote
// Description: 红外遥控PC4 中断处理
// 思路: 有遥控器的波形 算出进入条件,1,0 各个情况的脉冲宽度
// 进入条件:为8T的低电平和8T的高电平 以下降沿为触发方式 计时16T 即可
// 1:1T的低电平 3T的高电平 计时4T
// 0;1T的低电平 1T的高电平 计时2T
// 计算方式 定时器1 定时16us T=400us 所以1T的时间等于计数器加400/16=25次
// 16T = 26*16=400 4T =100 2T= 50
// Author: Huangzhigang 2014-0306
*******************************************************************************/
void Interrupt_Remote()
{
if(rDrv_PulseWidth())
{
if((u8PulseWidth >= (400-5))&&(u8PulseWidth <=(400+5)) )//PeriodT*16+Herror //5表示误差范围
{
NewData=1; //表示有新数据到来 开启数组的写入功能
}
else if((u8PulseWidth >= (100-5))&&(u8PulseWidth <=(100+5))&&(NewData==1))
{
vDrv_WriteRecvData(1);
}
else if((u8PulseWidth >=(50-5))&&(u8PulseWidth <= (50+5))&&(NewData==1))
{
vDrv_WriteRecvData(0);
}
else
{
NewData=0;
BitCount=0;
}
}
} 将上述代码Interrupt_Remote() 除了rDrv_PulseWidth()之外的其它函数全部都去掉,因为目前还不知道红外遥控器实际的编码以及脉冲宽度情况。使用一个数组来记录和保存rDrv_PulseWidth()函数在每次中断后所计算出来的脉冲宽度。(建议不知道的情况下数组足够大,一般几十字节)。这样在一次红外遥控按键后,我们所设的数组中就能过得到一组完整脉冲宽度数据,冲这组数据中我们就可以判断出该遥控器的编码情况,并可以在自己的单片机程序中使用它了(代码以后补充)。
原文地址:http://blog.csdn.net/a656343072/article/details/39499679