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

QQ登錄

只需一步,快速開(kāi)始

帖子
查看: 10915|回復(fù): 4
收起左側(cè)

只用一個(gè)單片機(jī)定時(shí)器的紅外接收解碼程序

[復(fù)制鏈接]
ID:110653 發(fā)表于 2016-3-28 23:29 | 顯示全部樓層 |閱讀模式
本帖最后由 hubaba 于 2016-3-28 23:31 編輯

1電路圖

1號(hào)單片機(jī)與紅外接收頭連接電路如圖所示,紅外接收頭一般都可互換使用。



電路和介紹詳見(jiàn):http://www.torrancerestoration.com/bbs/dpj-47282-1.html (在這貼附件中可下載完整的4個(gè)紅外解碼的源碼壓縮包)
程序預(yù)覽:
  1. /****************《51單片機(jī)輕松入門-基于STC15W4K系列》配套例程 *************
  2. ★★★★★★★★★★★★★★★★★★★★★★★★
  3. 《51單片機(jī)輕松入門-基于STC15W4K系列》 一書已經(jīng)由北航出版社正式出版發(fā)行。
  4.   作者親手創(chuàng)作的與教材配套的51雙核實(shí)驗(yàn)板(2個(gè)MCU)對(duì)程序下載、調(diào)試、仿真方便,不需要外部
  5.   仿真器與編程器,這種設(shè)計(jì)方式徹底解決了系統(tǒng)中多個(gè)最高優(yōu)先級(jí)誰(shuí)也不能讓誰(shuí)的中斷競(jìng)爭(zhēng)問(wèn)題。
  6.   QQ群:STC51-STM32(3) :515624099 或 STC51-STM32(2):99794374。
  7.         驗(yàn)證信息:STC15單片機(jī)
  8.   郵箱:xgliyouquan@126.com
  9.   ★★★★★★★★★★★★★★★★★★★★★★★★*/

  10. ///*************        功能說(shuō)明        **************        
  11. //紅外接收程序。適用于市場(chǎng)上用量最大的HT6121/6122及其兼容IC的編碼。
  12. //當(dāng)遙控器用戶碼與程序定義的用戶碼不同時(shí),程序會(huì)將遙控器的用戶碼一起從串口輸出。
  13. //使用模擬串口發(fā)送用戶碼與鍵碼,波特率9600,接收端要求使用字符格式顯示。        
  14. /******************************************/        
  15. #include        "STC15W4K.H"
  16. #define MAIN_Fosc                22.1184        // 定義主時(shí)鐘, 紅外接收會(huì)自動(dòng)適應(yīng),5~36MHZ,但模擬串口輸出部分不能自動(dòng)適應(yīng)。

  17. #define        User_code                0xFD02                // 定義紅外接收用戶碼  
  18. sbit        Ir_Pin = P3^6;                        // 定義紅外接收輸入端口
  19. sbit        TXD1 = P3^1;                          // 定義模擬串口發(fā)送腳
  20. /*************        用戶系統(tǒng)配置        **************/
  21. #define TIME                125                              // 選擇定時(shí)器時(shí)間125us, 紅外接收要求在60us~250us之間
  22. /*************        以下宏定義用戶請(qǐng)勿修改        **************/
  23. #define Timer0_Reload (unsigned int)(65536 - (TIME * MAIN_Fosc /12.0))  // 定時(shí)器初值
  24.                                    
  25. /*************        本地變量聲明        **************/
  26. unsigned char        IR_SampleCnt;                // 采樣次數(shù)計(jì)數(shù)器,通用定時(shí)器對(duì)紅外口檢測(cè)次數(shù)累加記錄
  27. unsigned char        IR_BitCnt;                        // 記錄位數(shù)
  28. unsigned char        IR_UserH;                        // 用戶碼(地址)高字節(jié)
  29. unsigned char        IR_UserL;                        // 用戶碼(地址)低字節(jié)
  30. unsigned char        IR_data;                        // 鍵原碼
  31. unsigned char        IR_DataShit;                // 鍵反碼
  32. unsigned char        IR_code;                        // 紅外鍵碼                 
  33. bit                Ir_Pin_temp;                        // 記錄紅外引腳電平的臨時(shí)變量
  34. bit                IR_Sync;                                // 同步標(biāo)志(1——已收到同步信號(hào),0——沒(méi)收到)
  35. bit                IrUserErr;                            // 用戶碼錯(cuò)誤標(biāo)志
  36. bit                IR_OK;                        // 完成一幀紅外數(shù)據(jù)接收的標(biāo)志(0,未收到,1,收到一幀完整數(shù)據(jù))

  37. /******************** 紅外采樣時(shí)間宏定義, 用戶不要隨意修改        *******************/
  38. //數(shù)據(jù)格式: Synchro,AddressH,AddressL,data,/data, (total 32 bit).
  39. #if ((TIME <= 250) && (TIME >= 60))                        // TIME決定測(cè)量誤差,TIME太大防錯(cuò)能力降低,TIME太小會(huì)干擾其它中斷函數(shù)執(zhí)行。
  40.         #define        IR_sample                        TIME                // 定義采樣時(shí)間,在60us~250us之間,
  41. #endif

  42. #define IR_SYNC_MAX                (15000/IR_sample)        // 同步信號(hào)SYNC 最大時(shí)間 15ms(標(biāo)準(zhǔn)值9+4.5=13.5ms)
  43. #define IR_SYNC_MIN                (9700 /IR_sample)        // 同步信號(hào)SYNC 最小時(shí)間 9.5ms,(連發(fā)信號(hào)標(biāo)準(zhǔn)值9+2.25=11.25ms)
  44. #define IR_SYNC_DIVIDE        (12375/IR_sample)        // 區(qū)分13.5ms同步信號(hào)與11.25ms連發(fā)信號(hào),11.25+(13.5-11.25)/2=12.375ms
  45. #define IR_DATA_MAX                (3000 /IR_sample)        // 數(shù)據(jù)最大時(shí)間3ms    (標(biāo)準(zhǔn)值2.25 ms)
  46. #define IR_DATA_MIN                (600  /IR_sample)        // 數(shù)據(jù)最小時(shí),0.6ms   (標(biāo)準(zhǔn)值1.12 ms)
  47. #define IR_DATA_DIVIDE        (1687 /IR_sample)        // 區(qū)分?jǐn)?shù)據(jù) 0與1,1.12+ (2.25-1.12)/2 =1.685ms
  48. #define IR_BIT_NUMBER                32                                // 32位數(shù)據(jù)

  49. //****************************  紅外接收模塊  ********************************************
  50. // 信號(hào)第1個(gè)下降沿時(shí)刻清零計(jì)數(shù)器并讓計(jì)數(shù)器從0開(kāi)始計(jì)數(shù),第2個(gè)下降沿時(shí)刻計(jì)算計(jì)數(shù)器運(yùn)行時(shí)間
  51. // 因此檢測(cè)的是每個(gè)信號(hào)從低電平開(kāi)始到高電平結(jié)束這段時(shí)間,也就是脈沖周期。
  52. void IR_RX_HT6121(void)
  53. {
  54.         unsigned char        SampleTime;                                // 信號(hào)周期
  55.         IR_SampleCnt++;                                                        // 定時(shí)器對(duì)紅外口檢測(cè)次數(shù)

  56.         F0 = Ir_Pin_temp;                                                // 保存前一次此程序掃描到的紅外端口電平         
  57.         Ir_Pin_temp = Ir_Pin;                                        // 讀取當(dāng)前紅外接收輸入端口電平
  58.         if(F0 && !Ir_Pin_temp)                                        // 前一次采樣高電平并且當(dāng)前采樣低電平,說(shuō)明出現(xiàn)了下降沿
  59.         {
  60.                 SampleTime = IR_SampleCnt;                        // 脈沖周期
  61.                 IR_SampleCnt = 0;                                        // 出現(xiàn)了下降沿則清零計(jì)數(shù)器
  62.                 //******************* 接收同步信號(hào) **********************************
  63.                 if(SampleTime > IR_SYNC_MAX)                IR_Sync = 0;        // 超出最大同步時(shí)間, 錯(cuò)誤信息。
  64.                 else if(SampleTime >= IR_SYNC_MIN)                // SYNC
  65.                 {
  66.                         if(SampleTime >= IR_SYNC_DIVIDE)    // 區(qū)分13.5ms同步信號(hào)與11.25ms連發(fā)信號(hào)
  67.                         {
  68.                                 IR_Sync = 1;                                    // 收到同步信號(hào) SYNC
  69.                                 IR_BitCnt = IR_BIT_NUMBER;          // 賦值32(32位有用信號(hào))
  70.                         }
  71.                 }
  72.                 //********************************************************************
  73.                 else if(IR_Sync)                                                // 已收到同步信號(hào) SYNC
  74.                 {
  75.                         if((SampleTime < IR_DATA_MIN)|(SampleTime > IR_DATA_MAX)) IR_Sync=0;        // 數(shù)據(jù)周期過(guò)短或過(guò)長(zhǎng),錯(cuò)誤
  76.                         else
  77.                         {
  78.                                 IR_DataShit >>= 1;                                        // 鍵反碼右移1位(發(fā)送端是低位在前,高位在后的格式)
  79.                                 if(SampleTime >= IR_DATA_DIVIDE)        IR_DataShit |= 0x80;        // 區(qū)別是數(shù)據(jù) 0還是1

  80.                                 //***********************  32位數(shù)據(jù)接收完畢 ****************************************
  81.                                 if(--IR_BitCnt == 0)                                 
  82.                                 {
  83.                                         IR_Sync = 0;                                        // 清除同步信號(hào)標(biāo)志
  84.                                         if(~IR_DataShit == IR_data)                // 判斷數(shù)據(jù)正反碼
  85.                                         {
  86.                                                 if((IR_UserH == (User_code / 256)) && IR_UserL == (User_code % 256))
  87.                                                 {
  88.                                                                 IrUserErr = 0;            // 用戶碼正確
  89.                                                 }
  90.                                                 else        IrUserErr = 1;            // 用戶碼錯(cuò)誤
  91.                                                         
  92.                                                 IR_code      = IR_data;                // 鍵碼值
  93.                                                 IR_OK   = 1;                            // 數(shù)據(jù)有效
  94.                                         }
  95.                                 }
  96.                                 // 格式:  用戶碼L —— 用戶碼H —— 鍵碼 —— 鍵反碼
  97.                                 // 功能:  將 “用戶碼L —— 用戶碼H —— 鍵碼”通過(guò)3次接收交換后存入對(duì)應(yīng)字節(jié),
  98.                                 //         這樣寫代碼可以節(jié)省內(nèi)存RAM占用,但是不如用數(shù)組保存好理解。        
  99.                                 //         鍵反碼前面部分代碼已保存好了        :IR_DataShit |= 0x80;                  
  100.                                 //**************************** 將接收的************************************************
  101.                                 else if((IR_BitCnt & 7)== 0)                // 1個(gè)字節(jié)接收完成
  102.                                 {
  103.                                         IR_UserL = IR_UserH;                        // 保存用戶碼高字節(jié)
  104.                                         IR_UserH = IR_data;                                // 保存用戶碼低字節(jié)
  105.                                         IR_data  = IR_DataShit;                        // 保存當(dāng)前紅外字節(jié)
  106.                                 }
  107.                         }
  108.                 }  
  109.         }
  110. }

  111. /**************** Timer0初始化函數(shù) ******************************/
  112. void InitTimer0(void)
  113. {
  114.         TMOD = 0x01;                         // 16位計(jì)數(shù)方式.
  115.         TH0 = Timer0_Reload / 256;         
  116.         TL0 = Timer0_Reload % 256;
  117.         ET0 = 1;                                         
  118.         TR0 = 1;
  119.         EA  = 1;
  120. }  

  121. /********************** Timer0中斷函數(shù)************************/
  122. void timer0 (void) interrupt 1
  123. {
  124.         IR_RX_HT6121();
  125.         TH0 = Timer0_Reload / 256;           // 重裝定時(shí)器初值   
  126.         TL0 = Timer0_Reload % 256;           // 重裝定時(shí)器初值   
  127. }

  128. /********************** 模擬串口相關(guān)函數(shù)************************/
  129. void delay104us(void)
  130. {
  131.    unsigned char i,j,k;
  132.    for(i=1;i>0;i--)       // 注意后面沒(méi)分號(hào)
  133.    for(j=3;j>0;j--)       // 注意后面沒(méi)分號(hào)
  134.    for(k=189;k>0;k--);    // 注意后面有分號(hào)        101
  135. }

  136. //模擬串口發(fā)送
  137. void Tx1Send(unsigned char dat)                //9600,N,8,1                發(fā)送一個(gè)字節(jié)
  138. {
  139.         unsigned char        i;
  140.         EA = 0;
  141.         TXD1 = 0;
  142.         delay104us();
  143.         for(i=0; i<8; i++)
  144.         {
  145.                 if(dat & 1)                TXD1 = 1;
  146.                 else                        TXD1 = 0;
  147.                 dat >>= 1;
  148.                 delay104us();
  149.         }
  150.         TXD1 = 1;
  151.         EA = 1;
  152.         delay104us();
  153.         delay104us();
  154. }

  155. void PrintString(unsigned char code *puts)                    // 發(fā)送一串字符串
  156. {
  157.     for (; *puts != 0;        puts++)  Tx1Send(*puts);         // 遇到停止符0結(jié)束
  158. }

  159. /********************* 十六進(jìn)制轉(zhuǎn)ASCII函數(shù) *************************/
  160. unsigned char        HEX2ASCII(unsigned char dat)
  161. {
  162.         dat &= 0x0f;
  163.         if(dat <= 9)        return (dat + '0');        //數(shù)字0~9
  164.         return (dat - 10 + 'A');                        //字母A~F
  165. }

  166. /********************* 主函數(shù) *************************/
  167. void main(void)
  168. {
  169.         InitTimer0();                                    // 初始化Timer0        
  170.         PrintString("定時(shí)器0初始化完畢\r\n");        // 上電后串口發(fā)送一條提示信息

  171.         while(1)
  172.         {
  173.                 if(IR_OK)                                     // 接收到一幀完整的紅外數(shù)據(jù)
  174.                 {
  175.                         PrintString("紅外鍵碼: 0x");                // 提示紅外鍵碼
  176.                         Tx1Send(HEX2ASCII(IR_code >> 4));        // 鍵碼高半字節(jié)
  177.                         Tx1Send(HEX2ASCII(IR_code));                // 鍵碼低半字節(jié)
  178.                         if(IrUserErr)                                                // 用戶碼錯(cuò)誤,則發(fā)送用戶碼
  179.                         {
  180.                                 Tx1Send(' ');                                        // 發(fā)空格
  181.                                 Tx1Send(' ');                                        // 發(fā)空格
  182.                                 PrintString("用戶碼: 0x");                // 提示用戶碼
  183.                                 Tx1Send(HEX2ASCII(IR_UserH >> 4));        // 用戶碼高字節(jié)的高半字節(jié)
  184.                                 Tx1Send(HEX2ASCII(IR_UserH));                // 用戶碼高字節(jié)的低半字節(jié)
  185.                                 Tx1Send(HEX2ASCII(IR_UserL >> 4));        // 用戶碼低字節(jié)的高半字節(jié)
  186.                                 Tx1Send(HEX2ASCII(IR_UserL));                // 用戶碼低字節(jié)的低半字節(jié)
  187.                         }
  188.                         Tx1Send(0x0d);                          // 發(fā)回車
  189.                         Tx1Send(0x0a);                          // 發(fā)回車
  190.                         IR_OK = 0;                              // 清除IR鍵按下標(biāo)志
  191.                 }
  192.         }
  193. }
復(fù)制代碼


相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

ID:154878 發(fā)表于 2016-12-14 23:38 | 顯示全部樓層
請(qǐng)問(wèn)一下,移值到C51 只要修改一下引腳和晶振就可以了么?
回復(fù)

使用道具 舉報(bào)

ID:365500 發(fā)表于 2018-8-10 17:27 | 顯示全部樓層
好厲害,,,,不知道什么時(shí)候才有這個(gè)水平�。�
回復(fù)

使用道具 舉報(bào)

ID:60263 發(fā)表于 2019-4-6 00:11 | 顯示全部樓層
STC官方網(wǎng)站上有這個(gè)例程,一樣的,可以下載,我用的STC15F104實(shí)測(cè)可用。
回復(fù)

使用道具 舉報(bào)

ID:363812 發(fā)表于 2019-10-17 18:25 | 顯示全部樓層
大哥  我用兩個(gè)新唐的8位單片機(jī)做紅外對(duì)射去解碼   套用這個(gè)怎么弄?   謝謝大哥回下
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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