如何实现不用外部中断来红外解码?
要把红外接收头的引脚接在单片机(除了外部中断引脚)的任意IO口,该怎么实现解码啊? 不断的检测信号输入引脚,其他的什么都不能做,如果做其他事就有可能错过了红外信号接受时间;因为红外信号到来时是不定时的,随时都有可能出现,所以使用中断的目的就是为了在做其他事时产生中断来处理红外接受程序。 那样的话,不就是单独的红外的程序而已了吗?我的程序还要运行其他动作呢。 哎!现在不知道该怎么办? 那你的中断都干什么了?贴个图来帮你看看。 用输入捕获中断(ICP). 做板的时候没有注意这个问题。现在有没有办法改。所以就想用其他IO口来实现红外解码 回复【4楼】ykr1-----------------------------------------------------------------------
怎么捕获法,也是一直在那里等待? 楼主用的什么型号单片机,有的单片机没有PCA捕获。 STC89C52 建议楼主飞根线,来的比较实际。 89C52没有PCA捕获 ,一般有PWM输出的单片机才有PCA捕获。 用定时中断,可以任一个IO口解码 回复【9楼】liuzhichengour
-----------------------------------------------------------------------
我也觉得,实在没有办法的话 只好是这样咯。其实我的模板上是接外部中断的。但当时修改电路板的时候不知道发什么神经,把管脚给改了,现在写程序才注意到。 回复【11楼】daicp
-----------------------------------------------------------------------
怎么实现,能说详细点吗? 回复【11楼】daicp
-----------------------------------------------------------------------
定时中断,那还是要等待电平的转换的,那样的话程序不就是一直在那里卡住?而且解码的准确程度还得值得思考 回复【14楼】cbmjd
-----------------------------------------------------------------------
不能满足楼主要求,意义不是很大。 回复【15楼】liuzhichengour
-----------------------------------------------------------------------
呵呵......我知道。 其实我是改了板,然后程序是按照中断的方式写的,但现在就是想知道能不能用别的IO口实现像中断那样的解码 回复【17楼】cbmjd
-----------------------------------------------------------------------
可以用定时器外部启动引脚来实现,就是用定时器模拟中断,把定时器赋值到最大值-1,然后使用外部引脚启动定时器,当有信号时定时器会溢出进入中断,实现中断功能,不过使用时注意中断前有点延时,做好补偿就可以。 回复【18楼】liuzhichengour
-----------------------------------------------------------------------
那应该怎么实现的?定时器赋值到最大值-1? 定时中断绝对准确灵敏,且多任务方式(也就是解码不会独点CPU),我们的程序已商用 回复【20楼】daicp
-----------------------------------------------------------------------
能不能给点提示啊?运用多任务? 就是做一个定时中断了,然后在定时中断检测电平高低,记数,识别码元这样了 红外信号的开头一般都有几个mS的前导信号,所以每隔1mS去检测一次这个引脚电平或许可行,没试过。
检测一次只占1mS里面的几个时钟周期,所以占CPU很少。 这是 搜来的 不知道行不行
//**********定时器一初始化**********
void timer1_init(void)
{
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x0E;
OCR1AL=0x10;
OCR1BH=0x00;
OCR1BL=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
}
SIGNAL(SIG_INTERRUPT0) //int0 interrupt
{
TCNT1=0;
if(CodeCnt==1)
{ // 收到第一个起始码, 准备状态转解码状态
TCCR1B=0x01; // 开定时器
CodeCnt=2;
IrTemp=0;
MCUCR=0x03; //第2个起始码的上升沿作为第一个同步信号
}
else
{
if(CodeCnt>13)
{ // 完成解码
IrCode=IrTemp;
while(TCNT1<889); // 延时889us
MCUCR=0x02; // 恢复下降沿中断
CodeCnt=0; // 转空闲状态
}
else
{
if(CodeCnt>1)
{ // 解码中,共12次CodeCnt=2-13
CodeCnt++; // 转解码状态+1
IrTemp<<=1;
while(TCNT1<1320); // 延时1.33ms, 检测信号电平
if(IrDat)
{ // 1,下一次下降沿有效
IrTemp|=1;
MCUCR=0x02;
}
else
{ // 0,下一次上升沿有效
MCUCR=0x03;
}
}
}
}
}
SIGNAL(SIG_OUTPUT_COMPARE1A)
{
if(CodeCnt==0)
{ // 空闲状态转准备状态
TCCR1B=0; // 关定时器
CodeCnt=1;
}
else
{ // 错误,转空闲状态
MCUCR=0x02; // 恢复下降沿中断
CodeCnt=0;
TCNT1=0;
}
}
volatile uint data0; //前16个脉冲存放地址
volatile uint data1; //后16个脉冲存放地址
volatile uint Flag=0; //接收完成一帧标志位
volatile float oldFall=0,newFall=0;//时间的先后纪录
volatile uintbitcnt=0; //脉冲个数纪录
uchar code;
//定时T1初始化
//系统时钟为7.3728M内频,64分频,最大定时时长483.184MS
void timer1_init(void)
{
TCCR1B = 0x00;//停止定时器
TIMSK |= 0x20;//中断允许
ICR1H= 0xFd;
ICR1L= 0xFd;//输入捕捉匹配值
TCCR1A = 0x00;
TCCR1B = 0x83;//启动定时器
}
//数据头的时间:Th=9+4.5=13.5ms
//数据“0”的时间:T0=0.565+0.56=1.125ms
//数据“1”的时间:T1=1.685+0.56=2.245ms
//定时器T1输入捕捉中断服务程序
SIGNAL(SIG_INPUT_CAPTURE1)
{
float time=0;
unsigned int temp=0;
newFall=ICR1; //读取当前时间
time=newFall-oldFall; //计算脉冲加间隔的时间
oldFall=newFall; //存放上一次的时间
if(time<0)time=newFall-oldFall+0xffff;//定时周期交叉的情况
temp=(unsigned int)time; //取整
//T0的8分频,即(1.125*7372.800)/64 = 129.6us ;正负20宽范围判断
if((temp>119) && (temp<149)) // "0"信号
{
temp=0;
}
//T1的8分频为258.624us
else if((temp>238) && (temp<278)) //“1”信号
{
temp=1;
}
//Th的8分频为1555.2us
else if((temp>1535) && (temp<1575)) //header头信号
{
bitcnt=0;
data0=0;
data1=0;
return; //返回,等待下次开始接收
}
else //干扰信号
{
bitcnt=0;
data0=0;
data1=0;
return;
}
bitcnt++;
if(bitcnt<16) //开始接收前16位
{
data0=data0|temp;
data0=data0<<1;
}
else if(bitcnt==16)
{
data0=data0|temp;
}
else if(bitcnt<32) //开始接收后16位
{
data1=data1|temp;
data1=data1<<1;
}
else if(bitcnt==32) //接收完最后一位
{
data1=data1|temp;
Flag=1; //接收完一帧,标志位置1
}
} 回复【23楼】hsztc
红外信号的开头一般都有几个ms的前导信号,所以每隔1ms去检测一次这个引脚电平或许可行,没试过。
检测一次只占1ms里面的几个时钟周期,所以占cpu很少。
-----------------------------------------------------------------------
大约是这个意思了 回复【24楼】cbmjd
-----------------------------------------------------------------------
这个单任务的,因为里面有死等的语句
程序一定不能在某个地方等待,否则这个单片机只解码不能做其他事了 回复【23楼】hsztc
-----------------------------------------------------------------------
回复【25楼】daicp
-----------------------------------------------------------------------
应该可以吧 但那样也要不断的检测吧,程序会不会一直卡在 定时检测上? 哎!困了 回去休息先,明天再想。谢谢你们啊! 先说说 接在哪个脚上把 回复【29楼】jrcsh 邪恶的小会会
-----------------------------------------------------------------------
不好意思啊!昨晚还要走半个小时才能回到宿舍 所以.......
那个是接到P1^7脚上的 用中断做是正确的 你的编码格式怎样的 常用红外遥控器对时序的要求并不是特别严格 用io口做查询就需要单片机速度快些 回复【32楼】pang7
-----------------------------------------------------------------------
我用的单片机是89C52 你说的查询是不是也是一直在那里等待电平的转换? 回复【31楼】pang7
-----------------------------------------------------------------------
编码时主要判断电平有没有达到9+4.5ms 如果是,则在那里等待,但问题就出现在这里了,这样单片机就一直在等待,别的功能完全没有用 除用中断还没有更好的办法。
刚做完,试过定时中断,理论讲没问题。实测不可用。
还是外触发中断。上沿触发。效果很好。
我想外中断加定时中断效率会很高。
我只用外中断,效率不是特高,但效果不错。20us测一次,0的时候是24-25次。1的时候是77-78。前导高电平108-110。
总体用时应该是20-30ms完成一次解码。整个周整期是108ms. 上面的代码看了一下没明白。捕获是如何工作没搞明白。哪位大侠能讲讲吗?
应该用定时器效率会更高。 不需要完全等待 比方说100us查询一次 对于ms级别来说 差100us无所谓的 我也考虑过用任意脚 做红外脚,思路就是用定时器定时的检测IO口的电平,记录高低电平的时差
在解码。不过一直没有试验。
类似从异步串口的数据接收。 是用中断加定时器比较好 我之前也是这样写的 但是现在就想弄一下其他口的方法 比如查询法什么的 但一直没有调出来 用心看下我下面所说的你就知道怎么用普通IO做红外了
定时器做个100us的中断,有中断就去查下IO的状态,记录高低电平(一般记录信号的电平)用寄存器来记。找出同步头 本帖最后由 hpdell 于 2012-4-13 11:11 编辑
看看这个地址的博客,应该可以的
http://hi.baidu.com/%BD%AD%BA%FE%D3%CE%BF%CDbxak/blog/item/68deebd74ddc77d851da4b98.html 不建议这样做
否则单片机再做别的就没时间了
如果还有动态扫描显示的话
那就更玄乎啦 用定时器采生一个125US的中断。煞后计算遥控码的时间,最后才解码,这样不会影响了 定时250us或者100us,去扫描IO口计数即可 markcool 用定时器对IO采样 不用外部的话,我觉得是不是单片机可累的啊。 duxingkei 发表于 2011-4-1 18:20 static/image/common/back.gif
我也考虑过用任意脚 做红外脚,思路就是用定时器定时的检测IO口的电平,记录高低电平的时差
在解码。不过一 ...
这个可以的,我一直都这样用,不过红外还是无线 configure one of the timers as a counter (to count input pulse) and set the counter to -1.
so the counter overflows on the very next input pulse -> you got an external interrupt.
it is probably one of the oldest tricks for embedded applications.
页:
[1]