欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7474|回復: 2
打印 上一主題 下一主題
收起左側

51單片機學習:紅外接收(對原子哥的ALIENTEK遙控器進行解碼)

[復制鏈接]
跳轉到指定樓層
樓主
正點原子的ALIENTEK遙控器
用戶碼00ff
16進制鍵值碼表
45    46    47
44    40    43
07    15    09
16    19    0d
0c    18    5e
08    1c     5a
42    ☻     4a




紅外接收管  通用型即可



---------------------------------------------------------------------------
下面是類似的波形圖,這個是網上找的,圖片較大,縮小后看上去有些模糊,不過沒關系,數據手冊上一般都有



遙控器在發射紅外信號之前,我們的mcu已經開啟了定時器
在定時器中斷函數中的全局變量irTimeCounts++ 一直在自加
irTimeCounts多長時間加一次? 或者說多長時間進入一次定時器中斷函數呢?
在方式2時,t=256*12/11059200 約為277.78us
============================================================
1.對于1.125ms的時間,timer0會中斷1.125/t=4.05次 也就是要5次,算上各種誤差,(頂多5次,至少4次)
2.對于2.25ms 的時間,timer0會中斷 2.25/t=8.1次, 也就是要9次,算上各種誤差,(頂多9次,至少8次)
  對于這里的次數,比N次小一點,就是N次,比N次大一點,就是N+1次,因為不會有半次,
  誤差給它正負0.4次足夠了,給了誤差后再算次數,直接舍入就行
那么我們就檢測irTimeCounts的值,
如果小于6或7,那么接收到的數據為0
如果大于6或7,那么接收到的數據為1
從計算結果來看,我覺得0.56,1.125,2.25這些值的出現是比較合理的,
能有效避免由于器件誤差和環境造成的數據誤判,而且計算也方便
  1. #include "my51.h"
  2. #include "ir.h"
  3. #include "smg.h"

  4. void main()
  5. {
  6.         timer0Init();          //定時器0初始化
  7.         int0Init();                  //外部中斷0初始化
  8.         
  9.         while(1)
  10.         {
  11.                 if(irTimeCountsArrProcess()) //如果成功接收并解析完成一幀數據
  12.                 {                                                         //就讓蜂鳴器響一下
  13.                         beep=0;                                         //蜂鳴器開啟
  14.                         led4=~led4;                                 //4號燈反轉一下
  15.                 }
  16.                                                                                  
  17.                 displaySMG(irCodeByteDataProcessForSmg());//顯示
  18.                 beep=1;                                                                              //蜂鳴器關閉
  19.                 //由于displaySMG()函數執行時間較短,故蜂鳴器響聲時間也較短,聽到滴了一下
  20.         }

  21. }
復制代碼
  1. #ifndef _51IR_H_
  2. #define _51IR_H_
  3. #include "my51.h"

  4. extern u8 data smgWela[7];                                   //數碼管顯示的數據

  5. extern void int0Init();                                              //外部中斷0初始化
  6. extern void timer0Init();                                   //定時器0初始化
  7. extern bool irTimeCountsArrProcess();    //成功解析一幀中斷數據返回TRUE
  8. extern u8* irCodeByteDataProcessForSmg();//將遙控器碼值處理成數碼管可顯示數據

  9. #endif
復制代碼
  1. #include "ir.h"

  2. u8 irTimeCounts=0;                            //定時器0在方式2下8位自動重裝時的中斷計數值
  3. u8 irTimeCountsArr[32]={0};          //存放紅外接收數據時的中斷次數記錄值,
  4. u8 bitNum=0;                                    //標志當前接收的是第幾個比特位
  5. u8 irReceFlag=0;                            //紅外接收一幀數據未完成標志,為1時完成
  6. u8 irCodeByteData[4]={0};           //保存接收到的4個字節的有效數據
  7. u8 irTimeCountsArrProcessOk=0;//對接收到的33位數據處理未完成標志,1完成

  8. void int0Init();                                     //外部中斷0初始化
  9. void timer0Init();                                     //定時器0初始化
  10. bool irTimeCountsArrProcess();    //解析中斷次數,即解碼
  11. u8* irCodeByteDataProcessForSmg();//將遙控器碼值處理成數碼管可顯示數據

  12. u8* irCodeByteDataProcessForSmg() //將解碼的4字節數據處理成數碼管可顯示的數據
  13. {        
  14.         if(irTimeCountsArrProcessOk)  //檢測一幀數據是否解析完成
  15.         {
  16.                 //這里的用戶碼只顯示低八位,因為高八位反正都是00(手上2個遙控器都是00)
  17.                 //然后還顯示遙控鍵值及其反碼,我們的數碼管只有6位,只顯示3字節數據
  18.                 if(irCodeByteData[2]+irCodeByteData[3]!=0xff)//校驗數據的完整性
  19.                 {                                                                         //最后一個字節是鍵碼的反碼
  20.                         led6=0;          //調試代碼
  21.                 }
  22.                 else
  23.                 {
  24.                         smgWela[0]=irCodeByteData[1] >> 4 ;           //取高4位
  25.                         smgWela[1]=irCodeByteData[1] & 0x0f;   //取低4位
  26.                         smgWela[2]=irCodeByteData[2] >> 4 ;
  27.                         smgWela[3]=irCodeByteData[2] & 0x0f;
  28.                         smgWela[4]=irCodeByteData[3] >> 4 ;
  29.                         smgWela[5]=irCodeByteData[3] & 0x0f;
  30.                     smgWela[6]=0xff;        //小數點全不顯        
  31.                 }
  32.                 irTimeCountsArrProcessOk=0;//標志清零,下一次有未解析的數據時才會再解析
  33.         }
  34.         return          smgWela;
  35. }

  36. bool irTimeCountsArrProcess()        //對接收到的32位的中斷次數數據進行解析
  37. {
  38.         u8 i,j,k,value=0;
  39.         if(irReceFlag)                           //檢測是否已經接收到新的4字節的紅外通信數據
  40.         {
  41.                 for(j=0;j<4;j++)                    //有4個字節
  42.                 {
  43.                         for(i=0;i<8;i++)         //對每個字節的8位數據處理
  44.                         {
  45.                                 value>>=1;
  46.                                 if(irTimeCountsArr[k++]>6)         //這里我們用6或7都是可以的
  47.                                 {
  48.                                          value|=0x80;                         //大于6的話該位數據是1
  49.                                 }
  50.                         }
  51.                         irCodeByteData[j]=value;//保存該字節,也就是遙控器的鍵碼        
  52.                 }
  53.                 irReceFlag=0;        //接收標志清零,這樣就會等到下次收到數據后才會再解析
  54.                 irTimeCountsArrProcessOk=1; //中斷數據解析完畢標志置1
  55.                 return TRUE;                              //解析完成
  56.         }
  57.         return FALSE;        //未進行解析,該返回值主要是為了方便外部文件調用時判斷的        
  58. }


  59. void int0() interrupt 0//外部中斷0
  60. {         
  61.    if(irTimeCounts>30) //9ms的話中斷32.4次,30這個取值差不多就可以了,不用太精確
  62.    {        //這里9ms引導碼需要timer0中斷irTimeCounts=9*11059.2/(256*12)=32.4次
  63.             bitNum =0;
  64.                 irTimeCounts=0;//為接收第0位數據做準備
  65.                 return;                   //丟棄引導碼,反正不是有效數據0或1的都丟棄,直接返回                  
  66.    }                                 

  67.    irTimeCountsArr[bitNum]=irTimeCounts; //將中斷次數數據存儲起來
  68.    irTimeCounts=0;     //存好了就立即清零,這樣不會影響下一位數據的接收
  69.    bitNum++;               //繼續下一位
  70.    if(32==bitNum)      //32位數據已經接收完成(0~31已經存儲)
  71.    {
  72.                    bitNum=0;             //清零,這里不清也可以,反正引導時也會清
  73.                 irReceFlag=1; //接收完成標志
  74.    }                                 
  75.         
  76. }

  77. void timer0() interrupt 1  //定時器0中斷函數
  78. {
  79.          irTimeCounts++;           //注:該值最大為255
  80. }

  81. void timer0Init()        //定時器0初始化
  82. {        //配置工作方式寄存器,且不影響定時器1的狀態
  83.         TMOD &= 0xf0;   //保留定時器1的配置,并清除定時器0的配置
  84.         TMOD |= 0X02;   //使用定時器0的工作方式2
  85.         TH0=0X00;
  86.         TL0=0X00;                 //工作方式2是8位自動重裝
  87.         ET0=1;                          //打開定時器
  88.         EA=1;                          //打開總中斷
  89.         TR0=1;                          //啟動定時器0
  90. }

  91. void int0Init()            //外部中斷0初始化
  92. {
  93.         IT0=1;                         //配置外部中斷0的觸發方式為 跳變延觸發
  94.         EX0=1;                         //打開外部中斷0
  95.         EA=1;                          //打開總中斷        
  96. }
復制代碼
  1. #ifndef _51SMG_H_
  2. #define _51SMG_H_

  3. #include "my51.h"

  4. sbit dula =P2^6;                          //段選鎖存器控制  控制筆段
  5. sbit wela =P2^7;                          //位選鎖存器控制  控制位置
  6. extern u8 data smgWela[7];  //第一位到第六位,最后一個是小數點位置控制

  7. #define dark        0x11//0x11是第17號元素,0x00是低電平,數碼管不亮,即table[17]
  8. #define dotDark 0xff                //小數點全暗

  9. void displaySMG(u8* pWela); //數碼管顯示函數,參數是數組指針

  10. #endif
復制代碼
  1. #include "smg.h"
  2. #include "my51.h"

  3. static u8 code table[]= {                 //0~F外加小數點和空輸出的數碼管編碼
  4.         0x3f , 0x06 , 0x5b , 0x4f , // 0 1 2 3
  5.         0x66 , 0x6d , 0x7d , 0x07 , // 4 5 6 7
  6.         0x7f , 0x6f , 0x77 , 0x7c , // 8 9 A B
  7.         0x39 , 0x5e , 0x79 , 0x71 , // C D E F
  8.         0x80 , 0x00 , 0x40          // . 暗 負號    暗即不顯示是第17索引號
  9. };                                                                //負號為第18索引號元素

  10. /*  由于此表只能一次顯示一個小數點,故已注釋掉,僅供查詢
  11.         例如想要第一個和第六個數碼管小數點同時點亮,
  12.         則執行 pWela->dot = 0xfe & 0xdf  即可
  13.         u8 code dotTable[]={   //小數點位置,某一位置0時,小數點亮
  14.         0xff ,                 //那么全暗就是0xff
  15.         0xfe , 0xfd , 0xfb ,   //1 2 3
  16.         0xf7 , 0xef , 0xdf     //4 5 6                    
  17. };*/

  18. u8 data smgWela[7]={0,0,0,0,0,0,0}; //第一位到第六位,最后一個是小數點位置控制

  19. //P0口的數碼管位選控制鎖存器只用了低6位,我們保留高2位的數據,留作它用
  20. void displaySMG(u8* pWela)
  21. {
  22.         u8 i=0;        
  23.     //控制6位數碼管顯示函數,不顯示的位用參數dark
  24.     u8 preState=P0|0x3f;  //保存高2位狀態,其中最高位是ADC0804的片選信號
  25.         wela=0;dula=0;_nop_();//先鎖定數據,防止吳亮及位選鎖存器高2位數據被改變
  26.                
  27.         P0=0;                                 //由于數碼管是共陰極的,陽極送低電平,燈不亮
  28.     dula=1;_nop_();
  29.     dula=0;                                 //段選數據清空并鎖定

  30.     P0=preState;                    //共陰極數碼管是陰極置高不亮,低6位置1,高2位保留        
  31.     wela=1;_nop_();                  //注:wela和dula上電默認為1                 
  32.     wela=0;                                    //位選鎖定,初始保留高2位的數據,低6位置高不亮

  33.         for(i=0;i<6;i++)          //顯示6位數碼管
  34.         {
  35.                 P0=table[pWela[i]]|(((1<<i) &="" pwela[6])?0x00:0x80);
  36.             dula=1;_nop_();             //送段數據,疊加小數點的顯示,0x00點亮小數點
  37.             dula=0;
  38.             
  39.                    P0=preState&~(1<<i); 不影響高2位數據,低6位是數碼管位選,低電平有效
  40.             wela=1;        _nop_();         //送位選號
  41.             wela=0;        
  42.             delayms(1);                         //稍作延時,讓燈管亮起來                        
  43.                 {  //消除疊影及誤亮,陰極置1不亮,低6位置1,高2位保留并鎖定
  44.                 P0=preState;
  45.                 wela=1;        _nop_();                        
  46.                 wela=0;        
  47.             }
  48.         }
  49. }
復制代碼




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

使用道具 舉報

沙發
ID:207882 發表于 2019-7-26 11:08 | 只看該作者
你好,為什么我用邏輯分析儀測出來第一個按鍵值是A25DH呢。。用的是同樣的東西,我用邏輯分析儀測試
回復

使用道具 舉報

板凳
ID:590753 發表于 2019-7-26 13:44 | 只看該作者
所有的這種遙控器碼都一樣
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表