找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 4318|回復(fù): 3
打印 上一主題 下一主題
收起左側(cè)

51單片機(jī)紅外遙控解碼器設(shè)計(jì)(匯編語言)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:395447 發(fā)表于 2018-9-8 19:18 | 只看該作者 回帖獎(jiǎng)勵(lì) |正序?yàn)g覽 |閱讀模式
紅外遙控解碼器
  廣東湛江海洋大學(xué) 楊振尚
        你家里是否有一個(gè)電視機(jī)遙控器或者空調(diào)機(jī)遙控器呢?你是否也想讓它遙控其他的電器甚至讓它遙控您的電腦呢?那好,跟我一起做這個(gè)紅外遙控解碼器。
     該小制作所需要的元件很少:?jiǎn)纹瑱C(jī)TA89C2051一只,RS232接口電平與TTL電平轉(zhuǎn)換心片MAX232CPE一只,紅外接收管一只,晶振11.0592MHz,電解電容10uF4只,10uF一只,電阻1K1個(gè),300歐姆左右1個(gè),瓷片電容30P2個(gè)。發(fā)光二極管8個(gè)。價(jià)錢不足20元。
電路原理介紹:
       主控制單元是單片機(jī)AT89C2051,中斷口INT0跟紅外接受管U1相連,接收紅外信號(hào)的脈沖,8個(gè)發(fā)光二極管作為顯示解碼輸出(也可以用來擴(kuò)展接其他控制電路),U3是跟電腦串行口RS232相連時(shí)的電平轉(zhuǎn)換心片,9、10腳分別與單片機(jī)的1、2腳相連,(1腳為串行接收,2腳為串行發(fā)送),MAX232CPE的7、8腳分別接電腦串行口的2(接收)腳、3(發(fā)送腳)。晶振采用11.0592MHz,這樣才能使得通訊的波特率達(dá)到9600b/s,電腦一般默認(rèn)值是9600b/s、8位數(shù)據(jù)位、1位停止位、無校驗(yàn)位。電路就這么簡(jiǎn)單了,現(xiàn)在分析具體的編程過程吧。
如圖所示,panasonic遙控器的波形是這樣的(經(jīng)過反復(fù)測(cè)試的結(jié)果)。
        開始位是以3.6ms低電平然后是3.6ms高電平,然后數(shù)據(jù)表示形式是0.9ms低電平0.9ms高電平周期為1.8ms表示0, 0.9ms低電平 2.4ms高電平周期為3.3ms表示1,編寫程序時(shí),以大于3.4ms小于3.8ms高電平為起始位,以大于2.2ms小于2.7ms高電平表示1,大于0.84ms小于1.11ms高電平表示0。因此,我們主要用單片機(jī)測(cè)量高電平的長(zhǎng)短來確定是1還是0即可。定時(shí)器0的工作方式設(shè)置為方式1:mov tmod,#09h,這樣設(shè)置定時(shí)器0即是把GATE置1,16位計(jì)數(shù)器,最大計(jì)數(shù)值為2的16次方個(gè)機(jī)器周期,此方式由外中斷INT0控制,即INT0為高時(shí)才允許計(jì)數(shù)器計(jì)數(shù)。比如:
jnb p3.2,$
jb p3.2,$
clr tr0
這3條指令就可以測(cè)量一個(gè)高電平,接下來讀取計(jì)數(shù)值TH0,TL0就可以分辨是起始位還是10。在確定碼表之前,您可以使用P0口的8個(gè)發(fā)光二極管來顯示編碼,16位編碼分兩次顯示:
mov p0,keydata
acall delay_1s ;//1ms延時(shí)子程序
mov p0,keydata+1
ljmp main
根據(jù)P0相繼的兩次顯示的編碼,記錄每個(gè)按鍵的編碼,形成編碼表,即遙控器編碼的解碼完畢。碼表確定之后,以后接收到遙控器的編碼之后,就與碼表比較,找到匹配的碼項(xiàng),并把該碼項(xiàng)對(duì)應(yīng)的順序號(hào)輸出到P0口,同時(shí)也把順序號(hào)向串行口輸出到電腦,電腦接收該數(shù)據(jù)后由串口軟件決定如何處理。
          程序不長(zhǎng),下面是完整的程序和注釋:(先看流程圖)
  1. keydata equ 30h ;//該地址和31H地址用來存放遙控器按鍵編碼。
  2. org 00h
  3. main:
  4.     movkeydata,#0  ;// 清零
  5.     mov tmod,#09h       ;//設(shè)置定時(shí)0方式1,GATE=1
  6.         mov r7,#0      ;//計(jì)數(shù)器,用來計(jì)數(shù)是否滿8位
  7.     mov  r6,#0           ;//計(jì)數(shù)器,用來計(jì)數(shù)是否滿2字節(jié)(解16位編碼)
  8.     jb p3.2,[        DISCUZ_CODE_2        ]nbsp;           ;//是否為低電平
  9. again:                        ;//如果為低,繼續(xù)往下面執(zhí)行
  10.     movtl0,#0           ;//清零TL0
  11.     mov th0,#0         ;//清零TH0
  12.     setb tr0       ;//開啟定時(shí)器0
  13.     jnbp3.2,[        DISCUZ_CODE_2        ]nbsp;          ;//等待高電平到來
  14.     jb p3.2,[        DISCUZ_CODE_2        ]nbsp;    ;//高電平到來,此時(shí)開始計(jì)數(shù)
  15.     clr tr0 ;//高電平結(jié)束,停止計(jì)數(shù)
  16.     mov a,th0     ;//讀取th0 值,TL0忽略不計(jì)     
  17.     clr c             ;//
  18.     subba,#12    ;//
  19.     jc again ;//th0<12則轉(zhuǎn),即小于3.4ms,你可以算一下這個(gè)時(shí)間
  20.     mov a,#14     ;//
  21.     clr c             ;//
  22.     subba,th0    ;//和14比較,如果TH0>14則大于3.8ms
  23.         jcagain      ;//大于3.8ms,從新再檢測(cè)
  24. nextbit:       ;//起始位找到了,然后下一位
  25.     movtl0,#0    ;//
  26.     movth0,#0    ;//
  27.     setb tr0 ;//啟動(dòng)定時(shí)器
  28.     jnbp3.2,[        DISCUZ_CODE_2        ]nbsp;   ;//等待高電平
  29.     jb p3.2,[        DISCUZ_CODE_2        ]nbsp;   ;//高電平到來,此時(shí)開始計(jì)數(shù)
  30.     clr tr0  ;//高電平結(jié)束,停止計(jì)數(shù)
  31.     mov a,th0     ;//讀取計(jì)數(shù)值,TL0忽略不計(jì)
  32.     clr c             ;//
  33.     subb a,#8     ;//th0和8比較
  34.     jcnext  ;;;;//若 <2.2ms則轉(zhuǎn),再判斷是否大于0.84ms
  35.     mov a,#10     ;//再跟10比較
  36.     clr c             ;//
  37.     subba,th0    ;//
  38.     jc again;;;;;;;//若 >2.7ms,則放棄,從新檢測(cè)
  39.     mova,keydata      ;//符合大于2.2ms 小于2.7ms,即為“1”
  40.     setbc        ;//C = 1
  41.     rrc a             ;//把1移位進(jìn)A
  42.     movkeydata,a      ;//保存
  43.     inc r7           ;//計(jì)數(shù)器加1
  44.     cjner7,#8,nextbit    ;//是否滿8位
  45.     inc r6                  ;//計(jì)數(shù)加1
  46.     cjner6,#2,last8 ;//是否滿兩字節(jié)
  47.     sjmpseach           ;//不滿兩字節(jié),再新采集
  48. last8:                        ;//滿1字節(jié),再接下來第二字節(jié)
  49.     movkeydata+1,a  ;//把第一字節(jié)編碼數(shù)據(jù)保存到31h里
  50.     mov r7,#0            ;//計(jì)數(shù)器R7清零
  51.     sjmpnextbit        ;//繼續(xù)采集數(shù)據(jù)
  52. next:                  ;//小于2.2ms時(shí)轉(zhuǎn)到這里
  53.     mov a,th0            ;//讀取計(jì)數(shù)值TH0
  54.     swap a                  ;//高4位與低4位對(duì)換
  55.     mov r1,a       ;//保存到R1
  56.     anltl0,#0f0h             ;//取TL0高4位,低4位忽略不計(jì)
  57.     mov a,tl0            ;//
  58.     clr c                    ;//
  59.     rrc a             ;//
  60.     rrc a             ;//
  61.     rrc a             ;//
  62.     rrc a             ;//
  63.     add a,r1 ;//
  64.     mov r1,a ;//
  65.     subba,#30    ;//以上幾行是把TH0的低4位和TL0的高4位合并為1字節(jié)作為計(jì)數(shù)值
  66.     jc nextbit; //判斷是否 <0.84ms,是則放棄,繼續(xù)采集
  67.     mov a,r1 ;//否
  68.     clr c             ;//
  69.     cjnea,#64,continue   ;//跟64比較
  70. continue:            ;//
  71.     jncnextbit ;  //a>64表示采樣值>1.11ms  放棄
  72.     mova,keydata  ;//否則 ,符合位“0”
  73.     clrc          ;//C  = 0
  74.     rrc a                    ;//把零右移進(jìn)A
  75.     movkeydata,a             ;//保存
  76.     inc r7                  ;//計(jì)數(shù)器加1
  77.     cjner7,#8,nextbit    ;//是否滿8位
  78.     inc r6                  ;//計(jì)數(shù)器加1
  79.     cjner6,#2,last_8      ;//是第一字節(jié)已經(jīng)滿
  80.     sjmpseach           ;//
  81. last_8:                ;//如果為第二字節(jié)
  82.     movkeydata+1,a  ;//則保存第一字節(jié)到31h
  83.     mov r7,#0            ;//清零R7
  84.     sjmpnextbit       ;//
  85. seach:                       ;//匹配按鍵編碼
  86.     movr0,#-2  ;//按鍵編碼字節(jié)個(gè)數(shù)計(jì)數(shù)器
  87.     movr1,#-1  ;//按鍵順序計(jì)數(shù)器
  88. seach1:                ;//
  89.         incr0           ;//
  90. seach2:               ;//
  91.        incr0                  ;//
  92.     inc r1                  ;//
  93.     cjner1,#29,compare   ;//是否R1=29
  94.     sjmpexit0           ;//
  95. compare:              ;//開始匹配
  96.     mov a,r0       ;//
  97.     movdptr,#keycode      ;//地址指針指向碼表首址
  98.     movca,@a+dptr    ;//取碼
  99.     cjnea,keydata,seach1      ;//比較
  100.     inc r0                  ;//R0+1,再比較下一字節(jié)(每個(gè)按鍵編碼為2字節(jié))
  101.     mov a,r0       ;//
  102.     ;mov dptr,#keycode   ;//
  103.     movca,@a+dptr    ;//比較
  104.     cjnea,keydata+1,seach2   ;//是否匹配,不匹配則繼續(xù)跟下一字節(jié)比較
  105.     movp1,r1         ;//如果匹配,把按鍵順序號(hào)輸出到p1
  106. send:                        ;//
  107.     movtmod,#20h     ;   //設(shè)置timer 1,mode 2
  108.     movtl1,#0fdh             ;//設(shè)置定時(shí)器初值
  109.     movth1,#0fdh             ;//
  110.     movscon,#01010000b;//以上設(shè)置,即設(shè)置串口波特率系數(shù)為:9600,8,1,0
  111.     setb tr1       ;//啟動(dòng)定時(shí)器1
  112. loop_s:         ;//
  113.     movsbuf,r1    ;//把R1(按鍵順序號(hào))輸出到串口
  114.     jnb ti,[        DISCUZ_CODE_2        ]nbsp;      ;//等待是否發(fā)送完畢
  115.     clr ti                  ;//發(fā)送完畢,清零TI
  116. exit0:                       ;//
  117. ljmp main                   ;//循環(huán)
  118. keycode:              ;//每?jī)勺止?jié)代表一個(gè)按鍵的編碼
  119. db 11111000b,00000000b,    11111100b,00000000b,    11111001b,11000000b
  120. db 11111100b,11000000b,    11111010b,00000000b,    11111010b,00100000b
  121. db 11111010b,01000000b,    11111010b,01100000b,    11111010b,10000000b
  122. db 11111010b,10100000b,    11111010b,11000000b,    11111010b,11100000b
  123. db 11111011b,00000000b,    11111011b,00100000b,    11111011b,01000000b
  124. db 11111011b,01100000b,    11111111b,01100000b,    11111111b,10100000b
  125. db 10001100b,10001110b,    10001101b,11101110b,    10001100b,10101110b
  126. db 10001101b,11001110b,    11111000b,11100000b,    11111100b,10000000b
  127. db 11111100b,01000000b,    11111001b,10100000b,    11111100b,10100000b
  128. db 11111100b,01100000b
  129. end
復(fù)制代碼
---------------------------------------------------------------------------------
各種遙控器編碼不同,如果你采用的是其他遙控器,修改幾個(gè)參數(shù)即可(當(dāng)然按鍵的編碼表肯定不同了),即計(jì)數(shù)器的值不同,不過有的遙控器有機(jī)器碼(機(jī)器碼每個(gè)按鍵都是一樣的),此時(shí)可以跳過機(jī)器碼的采集。最后有一點(diǎn)想提一下的是,剛開始不知道遙控器的編碼是比較麻煩的,筆者在雙龍電子網(wǎng)站下載了個(gè)聲卡示波器,用他可以一目了然觀看遙控器的波形,測(cè)量其脈沖寬度,有了它確實(shí)方便很多,該軟件可以到雙龍公司網(wǎng)站免費(fèi)下載使用。如果你想用遙控器遙控電腦,你可以自己編寫一個(gè)接受串行口應(yīng)用軟件,或者你可以直接下載使用Girder這個(gè)軟件,該軟件是專門為串口遙控器做的,很好用,下載地址為:girder點(diǎn)nl,你可以利用這個(gè)軟件定義遙控器來遙控你電腦移動(dòng)鼠標(biāo)、鍵盤操作、上網(wǎng)瀏覽、打開播放器、關(guān)機(jī)等。

51端口的結(jié)構(gòu)及工作原理.pdf

891.4 KB, 下載次數(shù): 29, 下載積分: 黑幣 -5

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂1 踩
回復(fù)

使用道具 舉報(bào)

地板
ID:225481 發(fā)表于 2018-9-9 12:46 | 只看該作者
如果將編碼輸出直接連接到接收器輸出端,就是取消IR發(fā)射接收器件,無線改成有線控制,要怎樣修改程序呢?
回復(fù)

使用道具 舉報(bào)

板凳
ID:225481 發(fā)表于 2018-9-9 12:33 | 只看該作者
單片機(jī)信號(hào)輸出端直接連接到設(shè)備紅外接收端,程序要修改哪里?就是去掉IR發(fā)射接收,由遙控變成線控。
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:6985 發(fā)表于 2018-9-9 11:17 | 只看該作者
原來是老鄉(xiāng),海洋大學(xué)沒這個(gè)系呀老鄉(xiāng)
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表