红外接收解码代码疑问:最终8位数据构建逻辑求助
红外接收解码代码数据构建逻辑疑问
我基本能理解这段红外接收解码代码,但始终搞不懂最终8位数据的构建逻辑,具体疑问标注在代码注释里:
while(ir == 1); INT0IE = 0; while(ir == 0); TMR0=0; while(ir == 1); i++; dat[i]=TMR0; if(dat[1] > 5000 && dat[1]<12000) ******5000和12000是在检测<562uS还是>2250uS?为何只检测dat[1]?**** { } else { i=0; INT0IE = 1; } if(i>=33) { GIE=0; delay(50); cmd=0; for(j=26;j<34;j++) { if(dat[j]>1000 && dat[j]<2000) ****不清楚1000和2000代表什么,知道是定时器值,但为何用这些值判断移位方向?***** cmd<<=1; else if(dat[j]>3500 && dat[j]<4500) ****同上疑问***** { cmd|=0x01; ***知道这是或运算符,但似乎不会改变值,它的作用是什么?比如1保持1,0保持0,我肯定遗漏了点什么*** cmd<<=1; } } cmd>>=1; ****为何此处要右移?****
疑问解答
1. 关于dat[1]的范围判断
首先要结合定时器TMR0的计数周期来看(以PIC常见配置为例:4MHz晶振+分频1:4,单个计数周期约1μS):
- 500012000对应5ms12ms,这是NEC红外协议引导码的高电平段(NEC引导码为9ms低电平+4.5ms高电平),
dat[1]存储的就是这段高电平的时长,判断这个范围是为了确认接收到的是有效红外帧,排除干扰信号。 - 只检测
dat[1]是因为引导码是整个红外帧的起始标识,只要引导码符合协议标准,后续才是地址码、数据码,所以先通过引导码完成帧有效性验证。
2. 关于dat[j]的10002000、35004500范围
同样基于1μS的计数周期:
- 10002000对应1ms2ms,对应NEC协议的逻辑0(逻辑0为562μS低电平+562μS高电平,总时长约1.12ms,落在该区间);
- 35004500对应3.5ms4.5ms,对应NEC协议的逻辑1(逻辑1为562μS低电平+2.25ms高电平,总时长约2.81ms,因定时器误差或代码阈值设置,落在该区间);
- 这两个范围是用来区分当前数据位是逻辑0还是逻辑1,和移位方向无关,是构建8位数据的基础判断条件。
3. 关于cmd|=0x01的作用
cmd初始值为0,每次处理数据位时:
- 若当前位是逻辑1,
cmd|=0x01是将cmd的最低位强制设为1(因为上一次左移后最低位是空的,默认是0),之后左移把位置留给下一位; - 若当前位是逻辑0,直接左移即可,最低位保持0。
你觉得没改变是误解了初始状态,实际上每次处理新位时cmd的最低位都是0,|=0x01是给这个空位写入1,是构建数据位的关键操作。
4. 关于最后cmd>>=1的原因
循环j从26到33共处理8位数据,每次处理完位后都会执行左移:
- 8次处理后,相当于多执行了一次左移(最后一位处理完的左移没有后续位填充),导致整个数据整体左移了一位;
- 执行
cmd>>=1是为了抵消这次多余的左移,让8位数据回到正确的位序上,得到最终的有效8位数据。
内容的提问来源于stack exchange,提问作者derill03
相关产品推荐
相关产品推荐

