本帖最后由 江弘源 于 2022-2-6 19:19 編輯
【“保姆級”指南】郭天祥51單片機STC89C52外設--HX1838紅外接收頭使用方法 這是我接觸的第一款沒有在郭天祥新概念書里講解的芯片,我覺得紅外線接收協議的探究難度和DS18B20旗鼓相當,大幅低于郭天祥配套的時鐘芯片(反正Intel和Motorola協議看得我暈暈的,時鐘芯片的功能也比常見的萬年歷+時鐘復雜很多),建議(像我的)初學者如果有意強化自己使用陌生芯片的能力,可以使用這款紅外芯片或者溫度探頭DS18B20先挑戰一把,再用時鐘芯片進階研究。 前言:所有代碼在郭天祥51開發板TX-1C普通開發板測試成功。 建議《郭天祥新概念51單片機C語言教程》先攻克定時器,串口打印部分再閱讀本文。 1.紅外通訊--NEC標準協議及其拓展NEC協議(extended-NEC,下稱extNEC) NEC通信協議是常見紅外遙控器的通訊協議。其他的通信協議還有飛利浦(Philips RC5/RC6),松下等廠家的協議等。下面重點介紹NEC標準協議及其拓展態。 如何表示0,1信號: 0信號:0.56ms低電平,之后跟著0.56ms高電平,共1.125ms 1信號:0.56ms低電平,之后跟著1.68ms高電平,共2.25ms
2018071520514243.png (17.84 KB, 下載次數: 92)
下載附件
2022-2-6 13:39 上傳
(ext)NEC一次發送的內容由三部分(及其反碼組成)組成 引導碼:觸發低電平條件,進入外來中斷程序處理紅外信號。先有9ms低電平再跟著4.5ms高電平。 8位地址碼(又稱“客戶碼”):一般一個遙控一碼,以標識遙控器身份,硬件固定和軟件編程兼有(方便配對),防止遙控器的數據被錯誤的接收器接收導致遙控器不小心遙控到非目標設備的情況(串碼)。 extNEC會連續出現16位地址碼,標準NEC8位地址碼出現之后緊跟著地址碼的反碼。 8位數據碼:和遙控器的按鍵一一對應,一般由硬件固定(學習遙控器可以軟件編程,學習目標遙控器的地址碼和數據碼),以標識鍵位。 數據碼的反碼:用于取反之后與前面的數據碼匹配,用于檢查傳輸數據過程是否有問題。 結束碼:最后有0.56ms低電平,表示傳輸代碼結束。 連續信號引導碼:與引導碼類似,不過高電平時間變短,只有2.25ms。 我網上找到的大多數資料把NEC和extNEC混為一談,兩個協議之間的區別便是extNEC將原有標準協議的基礎上放棄了8位用于數據校驗的地址碼反碼,轉而將地址碼由8位(256種排列組合)拓展到16位(65536種),接收和發送端的組合可以變得更多,降低串碼的可能性。 單次傳輸:引導碼-【地址碼-地址碼反碼】(16位地址碼)-數據碼-數據碼反碼-結束碼 連續傳輸:引導碼-【地址碼-地址碼反碼】(16位地址碼)-數據碼-數據碼反碼-結束碼-連續信號引導碼-結束碼-連續信號引導碼-結束碼-...... 【方括號是標準NEC的內容】(圓括號是拓展NEC的內容)
20180715204817233.png (8.59 KB, 下載次數: 72)
下載附件
2022-2-6 13:39 上傳
20180715205532977.png (15.01 KB, 下載次數: 89)
下載附件
2022-2-6 13:39 上傳
我們使用的紅外接收模塊是HX1838。負責將紅外載波信號直接解碼成pwm信號,方便軟件讀取。 -參考參數
O1CN01ovCM6T2CAMhzVu8FZ_!!2209549908433_看圖王.jpg (566.02 KB, 下載次數: 80)
下載附件
2022-2-6 13:39 上傳
模塊含有一顆接收燈,通斷電不亮,通電并接收到載波紅外信號時閃亮。 接收原理 發射極調解載波頻率38khz的紅外信號—— 接收器將紅外信號轉化為TTL電平的(ext)NEC協議信號—— 由單片機軟件解碼(ext)NEC協議信號 (由軟件判斷軟件編程的地址碼是不是和遙控器預設的地址碼匹配,不是則本次接收的數據丟棄,是則說明接收端和發射端匹配,進行下一步處理) (軟件記錄接下來的數據碼及其緊跟著的反碼,判斷反碼的“反碼”是不是和數據碼相匹配(數據校驗),不是則數據傳輸出現差錯,本次接收的數據丟棄,是則存入其他負責存儲數據碼的變量) (軟件將數據碼與預設的編碼表匹配,判斷出按下的是哪個按鍵,執行按鍵對應的操作) 使用方法 其接口非常簡單,接收器5V供電,只有三個接口: VCC,GND和數據端口 直接把VCC和GND杜邦線懟上延伸出來的供電插針(暫時不知道有沒有反接保護),數據端口接上P3.2(外界中斷0輸入)即可。
e48fe26090fe7e26e4d85ab766ad530.jpg (338.06 KB, 下載次數: 75)
下載附件
2022-2-6 13:39 上傳
039773c3f669d498f6be19d0b53adb5.jpg (1.13 MB, 下載次數: 88)
下載附件
2022-2-6 13:42 上傳
P3是“準雙向端口”,記得開始讀取之前先寫1。
2.研究用器材 £ 郭天祥TX-1C 51開發板(或者有空余的外界中斷輸入端的51最小系統板) £ HX1838紅外線接收頭和配套遙控
O1CN01sowKjx2CAMl0eHFYs_!!2209549908433-0-picasso.jpg (300.66 KB, 下載次數: 88)
下載附件
某一個寶上找個商家買到的,不到5塊錢
2022-2-6 13:39 上傳
網上上買到的,不到5塊錢 £ 5個遙控器(從左到右分別是科沃斯掃地機器人遙控器,老式松下空調遙控器,模塊配套的遙控器,DVD遙控器,天貓魔盒遙控器)
655573aae8367c2b1f00f39f0cf88f6.jpg (388.65 KB, 下載次數: 90)
下載附件
2022-2-6 13:39 上傳
£ 其中,左兩個遙控器有接收到信號(接收燈閃亮)但似乎是協議不同,串口打印不出數據;第三四個遙控使用的是標準NEC協議,地址碼好像都是0(改都不改,不怕串碼么),第五個使用的是拓展NEC協議(而且遙控硬件地址碼可以編程修改) 鄙人才疏學淺,這次只能先探究接收單次信號的情況,也就是按下一次按鍵就操作一次代碼(長按無動作)的情況。 3.功能實現(for延時版本) 實現思路: a.引導碼輸入端口,觸發外部中斷0,進入中斷函數,關閉外來中斷0開關防止后來的低電平使得CPU重復進入中斷程序 b.使用while等待電平變化,同時用計時器或者for延時計算引導碼高/低電平延時時間,檢查是否為硬件抖動(過很小一段時間后端口會恢復到高電平),是抖動的話自動“退出”(重新打開外來中斷0開關并return)防止函數卡死。不是的話說明使用while等待引導碼通過。 c.分四組采集數據,一次八位,存儲在數組里 (d.01信號唯一區別是高電平時間長短,用兩個while等待電平低變高再變低,數據位右移默認為0,當高電平時間超出某值時認為接收到1信號,用 或 運算將最高位變為1) (e.采集過程中也要設置防卡死“退出”口,使用while等待電平變化,同時用計時器或者for延時計算引導碼高/低電平延時時間,超過正常數據接受時間自動“退出”) f.數據碼反碼取反和數據碼比對,決定是數據無效并丟棄(“退出”)還是存儲- g.根據地址碼的格式判定是哪種類型NEC協議 h.正常“退出” i.標志位置1,啟動printf串口打印。 有一個要點是防卡死“退出”口要貫穿采集數據的整個過程,防止程序死掉。 第二個要點是相比判斷高電平時間來判斷是0還是1,通過判斷1節代碼整體所用時間(0為1.125ms,1為2.25ms)來判斷是0是1也是可以的(好像寫出來的程序不是很穩定)。 簡介: 啟動串口打印功能,使用中斷法讀取紅外線接收頭接收的數據碼,接收后立即用十進制打印出來。同時判斷發射器使用的是標準還是拓展NEC協議,打印信號類型和對應類型地址碼。 要點一:串口打印參數:波特率9600,方式1,其他保持默認。 要點二:定時器1采用八位自動重裝模式(產生波特率),紅外信號對接外界中斷0輸入口(P3^2) 標志位: signal_input:紅外線接收頭有輸入 signal_extNEC:為1表示遙控器是拓展NEC,0為標準NEC
單片機源程序如下:
- #include<reg52.h>
- #include<intrins.h>
- #include<stdio.h>
- #define unchar unsigned char
- #define unint unsigned int
- sbit IRIN=P3^2;
- unchar IRCOM[7];
- unchar receive_data,custom_address,extra_address;
- unchar signal_input,signal_extNEC;
- void delay(unchar x);
- void init(unint bps_setting);
- void main()
- {
-
- IRIN=1; //I/O口初始化
- IE=0x81; //允許總中斷中斷,使能 INT0 外部中斷
-
- init(0xFD); //波特率9600
-
- while(1)
- {
- if(signal_input==1)
- {
- signal_input=0;
- receive_data=IRCOM[2];
- custom_address=IRCOM[0];
- extra_address=IRCOM[1];
- ES=0;
- TI=1;
- printf("The IR code you receive is %bu!\n",receive_data);
- while(!TI);
-
- if (signal_extNEC==0)
- {
- printf("The corresponding custom address is %bu!,using standard NEC protocol.\n",custom_address);
- while(!TI);
- }
- else if(signal_extNEC==1)
- {
- printf("The full extent of its custom address is %bu",custom_address);
- while(!TI);
- printf(" %bu!,using extra NEC protocol.\n",extra_address);
- while(!TI);
- }
-
- printf("\n");
- while(!TI);
- TI=0;
- ES=1;
- }
- }
- }
- void IR_IN() interrupt 0 using 0//步驟a
- {
- unchar j,k,N=0;
- EX0 = 0;
- delay(15);
- if (IRIN==1)
- {
- EX0 =1;
- return;
- } //軟件防抖動
-
- while (!IRIN) //等IR變為高電平,跳過9ms的前導低電平信號。
- delay(1);
-
- while (IRIN) //等IR變為低電平,跳過4.5ms的前導高電平信號。
- delay(1);
-
- //步驟b結束,c開始
-
- for (j=0;j<4;j++) //收集四組數據
- {
- for (k=0;k<8;k++) //每組數據有8位
- {
-
- while (!IRIN) //等 IR 變為高電平
- delay(1);
- while (IRIN) //計算IR高電平時長
- {
- delay(1);
- N++; //計數器疊加
- if (N>=30)
- {
- EX0=1;
- return;
- } //步驟e,0.14ms計數過長自動離開。
- } //高電平時間記錄判定,即為步驟d
- IRCOM[j]=IRCOM[j] >> 1; //數據最高位補“0”
- if(N>=8)
- {
- IRCOM[j] = IRCOM[j] | 0x80; //數據最高位補“1”
- }
- N=0; //步驟d結束,計數器清零,準備下一位計數
- }
- }
-
- if(IRCOM[2]!=~IRCOM[3])
- {
- EX0=1;
- return;
- }
- //步驟f,數據校驗
-
- if (IRCOM[0]==~IRCOM[1])
- {
- signal_extNEC=0;
- }
- else
- {
- signal_extNEC=1;
- }//步驟g,格式判定
-
- signal_input=1;
- EX0 = 1; //退出并啟動步驟i
- }
- void init(unint bps_setting)
- {
- TH1=bps_setting;
- TL1=bps_setting;
- TMOD=0x20;
- TR1=1;
-
- SM0=0;
- SM1=1; //串口方式1
- REN=1;
-
- EA=1;
- ET0=1;
- ES=1;
-
- }
- /***************延時函數*****************************/
- void delay(unchar x) //x*0.14MS
- {
- unchar i;
- while(x--)
- {
- for (i = 0; i<13; i++) {}
- }
- }
復制代碼
實驗效果: 使用前三四個遙控的情況
92236fd49333354588b22fb763f6217.png (53.16 KB, 下載次數: 81)
下載附件
2022-2-6 13:46 上傳
使用天貓魔盒遙控器的情況
b443900f1c0aa1dfd84f1bdafb88df3.png (47.78 KB, 下載次數: 86)
下載附件
2022-2-6 13:46 上傳
4.后記 鄙人不常登錄論壇,可能會不定期回復問題,或者以后會考慮在這個項目下延伸一些內容(stm32版本......)。 這是菜鳥的第一篇技術文章,歡迎在下面指出問題,也歡迎引用我的內容,記得在下面吱一聲哈。
appendix: 0.引用資料 (這位老哥用的是定時器0進行延時計數,不過有個小問題就是沒有設置防卡死) 1.研究中發現的問題 我去查閱了淘寶給的資料,和論壇上的代碼對比了一下, 這一部分代碼竟然出奇的相似!
473a5306001686a4a77801625bccc61.png (144.3 KB, 下載次數: 106)
下載附件
2022-2-6 13:39 上傳
834c9d6b43a0242d129889f9eca1d79.png (90.38 KB, 下載次數: 78)
下載附件
2022-2-6 13:39 上傳
不過這段代碼好像沒什么卵用(單純是把接收到的數據不知道做什么算術運算),刪掉也不影響串口打印,如果有大佬知道它的作用,歡迎在下面指出。 2.拋磚引玉 ① 既然接收編碼會了,那么用軟件編程發射如何? 店家在郵寄紅外芯片和遙控器的同時,還送了一顆紅外發射二極管。理論上使用51單片機調制pwm也能實現電子信號到紅外信號的調制。 使用單片機收發紅外線信號實現機器間通訊是另一個值得深挖的好問題,先按下不表。 ②關于連續信號的接收問題 在網上只找到了stm32/樹莓派版本的帶連續信號判定的代碼,如果我的文章能夠引出哪位大佬寫代碼實現51單片機連續信號的接收,我將感激不盡。 |