典型红外接收波形引导码+用户码-用户码反码+指令码-指令码反码,在指令发送完成后,按键还未松开,会每隔100ms发送一个低脉冲和一个高脉冲。
单片机实现红外检测的基本原理,简单的说就是记录高低电平时间,确实是引导码、0码、1码,接收32bit数据码即可。
实现:
1.定时器中断,固定时间检测接收脚位电平,得到数据。
2.外部中断的方式,加定时器记时方式。
//定时器0中断
//0.25ms进入一次
void Tim0Int() interrupt 1
{
TR0 = 0;
timStep ++;
timCountMin ++; //计数器计数
timCountMax ++;
timBzCount ++;
tkDewaterCn ++;
baseTimCn = 0;
//检测到无下降沿多少秒,将下面那一段屏蔽掉
if(redRev)
{
countHigh ++; //state countStep = 2;
if(countHigh > 440) //120ms清零
{
recCompltFlg = 0;
sysUserCode = 0;
sysCtrolCode = 0;
}
if(countHigh > 30)
{
pilotCodeFlg = 0;
DataCount = 0;
}
revLowFlg = 0;
}
else
{
if(revLowFlg == 0)
{
if(pilotCodeFlg == 0) //检测引导码
{
if(countLow >= 20)
{
if(countHigh >= 16)
{
if(countLow <= 37)
{
if(countHigh <= 19)
{
pilotCodeFlg = 1; //确认为引导码
}
}
}
}
}
else //检测数据码
{
DataCount++;
if((countHigh <= 2)&&(countHigh >= 1)&&(countLow <= 3)&&(countLow >= 2))
{
//确认为零码
Databit = 0;
}
else if((countHigh >= 5)&&(countLow >= 2)&&(countLow <= 3)&&(countHigh <= 7))
{
//确认为1码
Databit = 1;
}
else
{
//错误码
DataCount = 0;
pilotCodeFlg = 0;
}
if(DataCount != 0)
{
if(DataCount < 17)
{
if(Databit) //默认先接LSB
{
userCode >>= 1;
userCode |= 0x8000;
}
else
{
userCode >>= 1;
}
}
else
{
if(Databit) //默认先接LSB
{
ctrolCode >>= 1;
ctrolCode |= 0x8000;
}
else
{
ctrolCode >>= 1;
}
if(DataCount == 32)
{
//确认接收数据结束
DataCount = 0;
pilotCodeFlg = 0;
//结束的处理,看看怎么弄
recCompltFlg = 1; //查询后清零
sysUserCode = userCode;
sysCtrolCode = ctrolCode;
}
}
}
}
//重置计数参数
countLow = 0;
countHigh = 0;
countLow ++;
revLowFlg = 1;
}
else
{
countLow ++; //state countStep = 1;
}
}
TL0 = 0x60; //定时器0低5位初值
TH0 = 0xf0; //定时器0高8位初值
//硬件自动清除中断标志
TF0 = 0;
TR0 = 1;
//P17 ^= 1;
//红外解码 INT04下降沿唤醒
if(recCompltFlg)
{
if(sysUserCode == USERCODE)
{
switch(sysCtrolCode)
{
case WATERCODE : touchKeyVal = 0x02;
recCompltFlg = 0;
sysUserCode = 0;
sysCtrolCode = 0;
break;
case LIGHTCODE : touchKeyVal = 0x06;
recCompltFlg = 0;
sysUserCode = 0;
sysCtrolCode = 0;
break;
case SWCODE : touchKeyVal = 0x01;
recCompltFlg = 0;
sysUserCode = 0;
sysCtrolCode = 0;
break;
case WINDCODE : touchKeyVal = 0x04;
recCompltFlg = 0;
sysUserCode = 0;
sysCtrolCode = 0;
break;
case TIMMINGCODE : touchKeyVal = 0x05;
recCompltFlg = 0;
sysUserCode = 0;
sysCtrolCode = 0;
break;
case DEWATERCODE : touchKeyVal = 0X03;
if(timFlgOn)
{
recCompltFlg = 0;
sysUserCode = 0;
sysCtrolCode = 0;
}
break;
default :
recCompltFlg = 0;
sysUserCode = 0;
sysCtrolCode = 0;
break;
}
}
//recCompltFlg = 0;
//sysUserCode = 0;
//sysCtrolCode = 0;
}
提醒可以利用每100MS每次的高低脉冲实现按键长按的检测。
项目合作、吹牛、扯淡、交朋友,请联系18665321219
原文:https://www.cnblogs.com/logicexpression/p/13512165.html