標(biāo)題: 單片機(jī)紅外發(fā)射程序與原理詳解 [打印本頁]

作者: huoguo    時(shí)間: 2018-12-3 21:25
標(biāo)題: 單片機(jī)紅外發(fā)射程序與原理詳解
用AT89S51單片機(jī)制作紅外電視遙控器

制作的實(shí)物如下圖所示:


  一般紅外電視遙控器的輸出都是用編碼后串行數(shù)據(jù)對(duì)38~40kHz的方波進(jìn)行脈沖幅度調(diào)制而產(chǎn)生的。
  當(dāng)發(fā)射器按鍵按下后,即有遙控碼發(fā)出,所按的鍵不同遙控編碼也不同。這種遙控碼具有以下特征:
  采用脈寬調(diào)制的串行碼,以脈寬為0.565ms、間隔0.56ms、周期為1.125ms的組合表示二進(jìn)制的“0”;以脈寬為0.565ms、間隔1.685ms、周期為2.25ms的組合表示二進(jìn)制的“1”。
  上述“0”和“1”組成的32位二進(jìn)制碼經(jīng)38kHz的載頻進(jìn)行二次調(diào)制,然后再通過紅外發(fā)射二極管產(chǎn)生紅外線向空間發(fā)射。一般電視遙控器的遙控編碼是連續(xù)的32位二進(jìn)制碼組,其中前16位為用戶識(shí)別碼,能區(qū)別不同的紅外遙控設(shè)備,防止不同機(jī)種遙控碼互相干擾。后16位為8位的操作碼和8位的操作反碼,用于核對(duì)數(shù)據(jù)是否接收準(zhǔn)確。
  根據(jù)紅外編碼的格式,發(fā)送數(shù)據(jù)前需要先發(fā)送9ms的起始碼和4.5ms的結(jié)果碼。
  遙控串行數(shù)據(jù)編碼波形如下圖所示:
  接收方一般使用TL0038一體化紅外線接收器進(jìn)行接收解碼,當(dāng)TL0038接收到38kHz紅外信號(hào)時(shí),輸出端輸出低電平,否則為高電平。所以紅外遙控器發(fā)送紅外信號(hào)時(shí),參考上面遙控串行數(shù)據(jù)編碼波形圖,在低電平處發(fā)送38kHz紅外信號(hào),高電平處則不發(fā)送紅外信號(hào)。
  單片機(jī)紅外電視遙控器電路圖如下:

單片機(jī)程序源碼:
  1. #include <AT89X51.h>
  2. static bit OP;        //紅外發(fā)射管的亮滅
  3. static unsigned int count;       //延時(shí)計(jì)數(shù)器
  4. static unsigned int endcount; //終止延時(shí)計(jì)數(shù)
  5. static unsigned char flag;      //紅外發(fā)送標(biāo)志
  6. char iraddr1;  //十六位地址的第一個(gè)字節(jié)
  7. char iraddr2;  //十六位地址的第二個(gè)字節(jié)
  8. void SendIRdata(char p_irdata);
  9. void delay();
  10. void main(void)
  11. {
  12.   count = 0;
  13.   flag = 0;
  14.   OP = 0;
  15.   P3_4 = 0;
  16.   EA = 1; //允許CPU中斷
  17.   TMOD = 0x11; //設(shè)定時(shí)器0和1為16位模式1
  18.   ET0 = 1; //定時(shí)器0中斷允許

  19.   TH0 = 0xFF;
  20.   TL0 = 0xE6; //設(shè)定時(shí)值0為38K 也就是每隔26us中斷一次  
  21.   TR0 = 1;//開始計(jì)數(shù)
  22.   iraddr1=3;
  23.   iraddr2=252;

  24.   do{
  25.       delay();
  26.       SendIRdata(12);
  27.   }while(1);
  28. }
  29. //定時(shí)器0中斷處理
  30. void timeint(void) interrupt 1
  31. {
  32.   TH0=0xFF;
  33.   TL0=0xE6; //設(shè)定時(shí)值為38K 也就是每隔26us中斷一次
  34.   count++;
  35.   if (flag==1)
  36.   {
  37.     OP=~OP;
  38.   }
  39.   else
  40.   {
  41.     OP = 0;
  42.   }
  43.   P3_4 = OP;
  44. }

  45. void SendIRdata(char p_irdata)
  46. {
  47.   int i;
  48.   char irdata=p_irdata;
  49.   //發(fā)送9ms的起始碼
  50.   endcount=223;
  51.   flag=1;
  52.   count=0;
  53.   do{}while(count<endcount);
  54.   //發(fā)送4.5ms的結(jié)果碼
  55.   endcount=117
  56.   flag=0;
  57.   count=0;
  58.   do{}while(count<endcount);
  59.   //發(fā)送十六位地址的前八位
  60.   irdata=iraddr1;
  61.   for(i=0;i<8;i++)
  62.   {
  63.      //先發(fā)送0.56ms的38KHZ紅外波(即編碼中0.56ms的低電平)
  64.      endcount=10;
  65.      flag=1;
  66.      count=0;
  67.      do{}while(count<endcount);
  68. //停止發(fā)送紅外信號(hào)(即編碼中的高電平)
  69.      if(irdata-(irdata/2)*2)  //判斷二進(jìn)制數(shù)個(gè)位為1還是0
  70.      {
  71.        endcount=41;  //1為寬的高電平
  72.      }
  73.     else
  74.      {
  75.      endcount=15;   //0為窄的高電平
  76.      }
  77.     flag=0;
  78.     count=0;
  79.     do{}while(count<endcount);
  80.     irdata=irdata>>1;
  81.   }
  82.   //發(fā)送十六位地址的后八位
  83.   irdata=iraddr2;
  84.   for(i=0;i<8;i++)
  85.   {
  86.      endcount=10;
  87.      flag=1;
  88.      count=0;
  89.      do{}while(count<endcount);
  90.      if(irdata-(irdata/2)*2)
  91.      {
  92.         endcount=41;
  93.      }
  94.      else
  95.      {
  96.        endcount=15;
  97.      }
  98.      flag=0;
  99.      count=0;
  100.      do{}while(count<endcount);
  101.      irdata=irdata>>1;
  102.   }
  103.   //發(fā)送八位數(shù)據(jù)
  104.   irdata=p_irdata;
  105.   for(i=0;i<8;i++)
  106.   {
  107.      endcount=10;
  108.      flag=1;
  109.      count=0;
  110.      do{}while(count<endcount);
  111.      if(irdata-(irdata/2)*2)
  112.      {
  113.          endcount=41;
  114.      }
  115.      else
  116.      {
  117.        endcount=15;
  118.      }
  119.      flag=0;
  120.      count=0;
  121.      do{}while(count<endcount);
  122.      irdata=irdata>>1;
  123.   }
  124.   //發(fā)送八位數(shù)據(jù)的反碼
  125.   irdata=~p_irdata;
  126.   for(i=0;i<8;i++)
  127.   {
  128.      endcount=10;
  129.      flag=1;
  130.      count=0;
  131.      do{}while(count<endcount);
  132.      if(irdata-(irdata/2)*2)
  133.      {
  134.          endcount=41;
  135.      }
  136.      else
  137.      {
  138.        endcount=15;
  139.      }
  140.      flag=0;
  141.      count=0;
  142.      do{}while(count<endcount);
  143.      irdata=irdata>>1;
  144.   }
  145.   endcount=10;
  146.   flag=1;
  147.   count=0;
  148.   do{}while(count<endcount);
  149.   flag=0;
  150. }
  151. void delay()
  152. {
  153.   int i,j;
  154.   for(i=0;i<400;i++)
  155.   {
  156.     for(j=0;j<100;j++)
  157.     {
  158.     }
  159.   }
  160. }
復(fù)制代碼

以上的Word格式文檔51黑下載地址:
單片機(jī)紅外發(fā)射(原理與設(shè)計(jì)程序).doc (126.5 KB, 下載次數(shù): 200)


作者: 1149719013    時(shí)間: 2019-12-26 15:33
有沒有用單片機(jī)發(fā)送矩陣開關(guān)紅外信號(hào)的程序
作者: shmilyr1213    時(shí)間: 2020-1-18 15:42
大神,請(qǐng)問為什么 endcount=223是9ms  endcount=10時(shí)是0.56ms。定時(shí)器不是26us一次嗎?算迷糊了呀。自學(xué)的很多都不懂,務(wù)鄙視呀。
作者: cccc888    時(shí)間: 2020-1-18 20:35

實(shí)測(cè)接收頭處的波形,

作者: lyl44    時(shí)間: 2020-1-27 18:45
直接驅(qū)動(dòng)?沒用三極管
作者: tieq1952    時(shí)間: 2020-1-28 07:58
謝謝分享。!
作者: 1239225803    時(shí)間: 2020-5-14 09:18
你好 在keil上編譯出錯(cuò) 錯(cuò)誤信息

作者: 1239225803    時(shí)間: 2020-5-14 09:19
你好 在keil上編譯出錯(cuò) 錯(cuò)誤信息:Build target 'Target 1'
assembling STARTUP.A51...
compiling aag.c...
AAG.C(59): error C141: syntax error near 'flag'
Target not created
作者: 20563112    時(shí)間: 2021-5-11 22:03
1239225803 發(fā)表于 2020-5-14 09:19
你好 在keil上編譯出錯(cuò) 錯(cuò)誤信息:Build target 'Target 1'
assembling STARTUP.A51...
compiling aag.c. ...

你不會(huì)一點(diǎn)C的語法糾錯(cuò)都不會(huì)吧
作者: xxd0708    時(shí)間: 2021-5-12 12:55
cccc888 發(fā)表于 2020-1-18 20:35
實(shí)測(cè)接收頭處的波形,

這是用什么工具測(cè)試的啊
作者: 20563112    時(shí)間: 2021-5-14 17:03
我驗(yàn)證過了,這個(gè)代碼不行
作者: danq    時(shí)間: 2021-5-19 11:44
樓主用的是40us溢出,上面是223,117等等...都有重新核算一次,就可以正常運(yùn)行了
作者: 越南超級(jí)人類    時(shí)間: 2021-6-27 10:32
1239225803 發(fā)表于 2020-5-14 09:19
你好 在keil上編譯出錯(cuò) 錯(cuò)誤信息:Build target 'Target 1'
assembling STARTUP.A51...
compiling aag.c. ...

flag附近少了一個(gè)分號(hào)而已,自己好好看看,不動(dòng)點(diǎn)腦子不行的
作者: sadv    時(shí)間: 2021-6-29 18:48
紅外信號(hào)編碼的方式有很多種,樓主說明的只是其中最常見的一種,一般稱為NEC,還有其他很多種不同的編碼,編碼方式不同,解碼的方式自然也就不同,所以應(yīng)用的時(shí)候還是要看具體時(shí)哪一種編碼方式
作者: kavin21513    時(shí)間: 2021-8-2 16:07
實(shí)驗(yàn)發(fā)現(xiàn), 采用12M的晶振,中斷最少要20us,也就是周期最少要40us了,所以樓主的程序算法上是40us溢出.
如果采用24M晶振,就可以13us中斷,產(chǎn)生周期為26us的38K載波.
所以要采用24M晶振.不然速度不夠.
作者: 飛騰網(wǎng)絡(luò)    時(shí)間: 2022-2-22 22:03
大師為什么用的兩個(gè)晶振 那個(gè)左邊那個(gè)小IC是干啥的呢




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1