|
本帖最后由 wzqwxx 于 2021-10-8 11:48 編輯
今天談的是NEC 協議的。關于此協議請上百度。
放假在家集中學習了51單片機,“苦讀”了一些書箱和視頻教程。談不上談論什么 ,其實就向大家匯報這段時間的學習情況,歡迎交流,提出寶貴意見。
本人是第一次在貴壇發貼,定有很多不到的地方,也請大家批評指正。
今天就NEC 協議,仿照教材編寫了三種紅外解碼方案,并都在開發板調試通過,完整源碼會在附件提供。
第一種方案是參照教程的源碼(在此稱第四方案)改寫的,解碼部分代碼比第四方案精減了,而且不失第四方案性能,只用了幾行代碼,占用內存也少。而第四方案正好相反。這兩種方案都是利用中斷,對前后信號兩個下降沿之間時間長短、判定二進制數據0/1位的。優點:利用了兩個中斷,分別是定時器0和外部中斷0,程序執行很快,占用CPU時間很少。缺點:占用了兩個中斷,能正確解碼NEC協議的遙控器信號,也能解碼別的協議遙控器的信號,當然是亂碼。
第二種方案,與第四種方案解碼方式不同,只利用一個外部中斷0,對信號高低電平分別測量延續時長,來判定二進制數據0/1位的。優點:代碼少,占用內存少,只利用了一個外部中斷。能正確解碼NEC協議的遙控器信號,禁止解碼別的協議遙控器的信號,不會出現亂碼。缺點:占用CPU時間多,整個解碼期間不能產生別的中斷。
第三種方案,綜合了一二兩種方案,揚長避短,優勢互補,自認為是很好的方案。相對第四方案,優點:代碼少,占用內存少,程序執行較快,占用CPU時間較少,只利用了一個外部中斷0,能正確解碼NEC協議的遙控器信號,禁止解碼別的協議遙控器的信號。缺點:解碼頭部要延時9+4.5=13.5ms時間,有點長,CPU不能做其它任務。
下面將前三種方案核心代碼貼出,歡迎大家評論交流,并指出錯誤和不足 。
/*-----------------------------------------------
* 【實驗平臺】: QX-單片機開發板
* 【外部晶振】: 11.0592mhz
* 【主控芯片】: STC89C52
* 【編譯環境】: Keil μVisio4
名稱:遙控器紅外解碼數碼管顯示
使用:按遙控器會在數碼管上對應顯示十六進制鍵值
NEC 協議下的編碼表示
其中:引導碼高電平約9000us 左右,低電平約4500us 左右;
接收端:引導碼低電平約9000us 左右,高電平約4500us 左右;
用戶碼16 位,數據碼16 位,共32位;
發送端: 數據0 是用“高電平約560us +低電平約560us”表示。
數據1 可用“高電平約560us+低電平約1680us”表示
接收端反轉:數據0 是用“低電平約560us +高電平約560us”表示。
數據1 可用“低電平約560us+高電平約1680us”表示
------------------------------------------------*/

單片機源程序如下:
- #include<reg52.h> //包含頭文件,頭文件包含特殊功能寄存器的定義
- sbit IR=P3^2; //紅外接口
- sbit beep = P2^3;//蜂鳴器接口
- #define DataPort P0 //定義數據端口 程序中遇到DataPort 則用P0 替換
- sbit LATCH1=P2^6; //定義鎖存使能端口 段鎖存
- sbit LATCH2=P2^7; // 位鎖存
- unsigned char code dofly_DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
- 0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
- //0-F的碼表
- unsigned char irtime; //紅外用全局變量 計數延時,識別比特位電平高低
- unsigned char IRcord[4];//存儲鍵碼
- void delay(unsigned int i)
- {
- unsigned int m,n;
- for(m=i;m>0;m--)
- for(n=114;n>0;n--);
- }
- void tim0_isr (void) interrupt 1 using 1 //STC89C52 11.0592M
- {
- irtime++; //用于計數2個下降沿之間的時間 每個溢出中斷時長256*1.085us=277.7us
- }
- void EX0_ISR (void) interrupt 0 //外部中斷0服務函數
- {
- static unsigned char i; //接收紅外信號處理
- if( irtime <3 || irtime >54) goto end; //兩個下降沿延時過短(少于833us)或過長不解碼 濾除干擾波
- if(irtime > 45 && irtime < 54)//跳過引導碼 頭碼,9ms+4.5ms
- {
- irtime=0;
- i=0;
- }
- else{
- IRcord[i/8] >>= 1; //i/8每處理8位換下一個元素,總的處理4個字節共32位的數據
- if(irtime > 6) IRcord[i/8] |= 0x80; //位0電平時長計數上限4,位1高電平計數上限8
- irtime = 0; //這里取6為0/1 的識別分界
- i++;
- if(i > 31){ i=0; beep = 0; delay(100); beep = 1; }
- } //beep 鳴叫一聲 解碼成功
- end: irtime=0;
- }
- void TIM0init(void)//定時器0初始化
- {
- TMOD=0x02;//定時器0工作方式2,TH0是重裝值,TL0是初值
- TH0=0x00; //重載值
- TL0=0x00; //初始化值
- ET0=1; //開中斷
- TR0=1;
- }
- void EX0init(void)
- {
- IT0 = 1; //指定外部中斷0下降沿觸發,INT0 (P3.2)
- EX0 = 1; //使能外部中斷
- EA = 1; //開總中斷
- }
- void SMG_show(unsigned char num) //兩位數碼管顯示十六進制鍵碼
- {
- P0=dofly_DuanMa[num/16];
- LATCH1=1;
- LATCH1=0;
- P0=0xdf; //選中第一個數碼管
- LATCH2=1;
- LATCH2=0;
- delay(2);
- P0=dofly_DuanMa[num%16];
- LATCH1=1;
- LATCH1=0;
- P0=0xbf; //選中第二個數碼管
- LATCH2=1;
- LATCH2=0;
- delay(2);
- }
- void main(void)
- {
- EX0init(); //初始化外部中斷
- TIM0init();//初始化定時器
- while(1)//主循環
- {
- SMG_show(IRcord[2]);//兩位數碼管顯示十六進制鍵碼
- }
- }
-
-
復制代碼
例程副本.rar
(12.69 KB, 下載次數: 66)
2021-10-6 20:41 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|
評分
-
查看全部評分
|