找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2756|回复: 0
打印 上一主题 下一主题
收起左侧

基于stc8a8k64s12芯片一位定时器移植的NEC协议的通用红外外解码程序

[复制链接]
跳转到指定楼层
楼主
51单片机移植的NEC协议的通用红外外解码程序
   搞了几天的关于NEC协议的红外位置遥控器解码程序,发现好多网上帖子给出的参考代码移植代码解码程序尤为困难,特此在参考了STC15w4k系列参考范例后,在其基础上增加了数字按键解码到数码管显示,所有键位解码到8位LED显示代码,特别说明移植相当方便!!!只是其晶振频率要求22.1148mhz,其他晶振频率范围需要修改相关寄存器值,会比较麻烦,解码成功案列遥控器型号为car MP3,同时适用该协义下所有遥控器,并且支持解码数据串口发送到电脑端显示,由于芯片和遥控器型号都是资源比较少的,特此分享好东西,希望大家积极指 有效程序在测试一中.7z (34.2 KB, 下载次数: 17)

正批评,共同讨论学习。

串口接收成功:


单片机源程序如下:
  1. ////////////////////////////////////////////////////////////
  2. //   红外接收数据,查询方式,并通过串口发送输出  
  3. //   晶振:22.1184MHz         ,波特率:9600
  4. ////////////////////////////////////////////////////////////
  5. #include <STC8.H>
  6. #define dataport P1
  7. typedef unsigned char uchar;
  8. typedef unsigned char uint;
  9. sbit LADUAN=P3^5;
  10. sbit LAWEI=P3^6;
  11. #define  LED P0
  12. sbit Ir_Pin = P2^7;             // 红外接收头信号输出脚

  13. uchar code lhc_duan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

  14. unsigned char Ir_Buf[4]; // 用于保存解码结果(Ir_Buf[0]--用户码L,Ir_Buf[3] --键反码)

  15. // 获取低电平时间 (其实是16位计数器的计数值,STC15系列定时器默认为16位自动重装方式)
  16. unsigned int Ir_Get_Low()
  17. {
  18.         TL0 = 0;                 // 清空16位计数器0
  19.         TH0 = 0;                 // 清空16位计数器0
  20.         TR0 = 1;                 // 计数器0开始运行
  21.         while (!Ir_Pin && (TH0<0x80));          // 信号引脚变成高或低电平时间>17ms退出(只要>12ms即可)
  22.                                       // 0x8000=32768,  32768*0.54253uS=17777.62 uS            
  23.         TR0 = 0;                          // 这里 ! 优先级大于&&     
  24.         return (TH0 * 256 + TL0);                  // 返回16位计数器的计数值。
  25. }

  26. // 获取高电平时间(其实是16位计数器的计数值,STC15系列定时器默认为16位自动重装方式)
  27. unsigned int Ir_Get_High()
  28. {
  29.         TL0 = 0;                    // 清空16位计数器0
  30.         TH0 = 0;                    // 清空16位计数器0
  31.         TR0 = 1;
  32.         while (Ir_Pin && (TH0<0x40));           // 信号引脚变成低电平或高电平时间>17ms退出
  33.         TR0 = 0;
  34.         return (TH0 * 256 + TL0);
  35. }  

  36. void UART_init(void)                      // 9600@22.1184MHz
  37. {                  
  38.         //下面代码设置定时器1
  39.         TMOD = 0x20;           // 0010 0000 定时器1工作于方式2(8位自动重装方式)
  40.         TH1  = 0xFA;           // 波特率:57600 /22.1184MHZ
  41.         TL1  = 0xFA;           // 波特率:57600 /22.1184MHZ
  42.         TR1  = 1;
  43.         //下面代码设置定串口
  44.         AUXR = 0x00;             // 很关键,使用定时器1作为波特率发生器,S1ST2=0
  45.         SCON = 0x50;         // 0101 0000 SM0.SM1=01(最普遍的8位通信),REN=1(允许接收)
  46. }       

  47. //  UART发送一字节       
  48. void UART_Send_Byte(unsigned char dat)
  49. {
  50.         SBUF = dat;
  51.         while (TI == 0);
  52.         TI = 0;             // 此句可以不要,不影响后面数据的发送,只供代码查询数据是否发送完成
  53. }

  54. void IR_work()  //红外解码程序
  55. {
  56.         switch(Ir_Buf[2])
  57.         {
  58.                 case 0x0c:dataport=lhc_duan[1];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
  59.                 case 0x18:dataport=lhc_duan[2];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
  60.                 case 0x5e:dataport=lhc_duan[3];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
  61.                 case 0x08:dataport=lhc_duan[4];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
  62.                 case 0x1c:dataport=lhc_duan[5];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
  63.                 case 0x5a:dataport=lhc_duan[6];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
  64.                 case 0x42:dataport=lhc_duan[7];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
  65.                 case 0x52:dataport=lhc_duan[8];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
  66.                 case 0x4a:dataport=lhc_duan[9];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
  67.                 default:dataport=lhc_duan[0];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
  68.         }       
  69. }

  70. void main()
  71. {
  72.         unsigned int time;
  73.         unsigned char i,j;
  74.         LED=Ir_Pin;
  75.         UART_init();
  76.         UART_Send_Byte(0X55);                // 测试串口工作是否正常
  77.         dataport=0xfe;//取位码 第一位数码管选通,即二进制1111 1110
  78.         LAWEI=1;
  79.         LAWEI=0;
  80.         dataport=lhc_duan[0];
  81.         LADUAN=1;
  82.         LADUAN=0;
  83.         while (1)
  84.         {
  85. start:
  86.                 ///////////// 接收同步信号 ///////////
  87.                 while (Ir_Pin);                    // 等待低电平出现
  88.                 time = Ir_Get_Low();        // 低电平区间16位计数器的计数值
  89.                 if ((time < 15667) || (time > 17510))   goto start;       
  90.                                                         // 引导脉冲低电平8500~9500us,T=12/22.1184=0.54253uS
  91.                                                         // 8500/0.54253uS=15667.3    9500/0.54253uS=17510.5
  92.                 time = Ir_Get_High();
  93.                 if ((time < 7372) || (time > 9216))  goto start;   // 引导脉冲高电平4000-5000us
  94.                                                                                      // 4000/0.54253uS=7372.8    5000/0.54253uS=9216
  95.                 ////////// 接收后续的4 字节数据        ////////
  96.                 for (i=0; i<4; i++)                  // 4个字节
  97.                 {
  98.                         for (j=0; j<8; j++)              // 每个字节8位
  99.                         {
  100.                                 time = Ir_Get_Low();                 // 接收每位560us 低电平
  101.                                 if ((time < 626) || (time > 1438))   goto start;                 // 340-780us
  102.                                                                                  // 340/0.54253uS=626.7    780/0.54253uS=1437.7
  103.                                 time = Ir_Get_High();                    // 接收每位560us或1690us高电平时间
  104.                                 if ((time>626) && (time<1438))  // 时间范围为340-780us(中心值560us),
  105.                     {
  106.                          Ir_Buf[i] >>= 1;                // 因低位在先,所以数据右移,移入的最高位为0
  107.                                 }
  108.                     else if ((time>2728) && (time<3502))
  109.                 {                           // 时间判定范围为1480~1900us(中心值1690us)
  110.                                                                             // 1480/0.54253uS=2727.9   1900/0.54253uS=3502.1
  111.                                         Ir_Buf[i] >>= 1;                // 因低位在先,所以数据右移,移入的最高位为0
  112.                                         Ir_Buf[i] |= 0x80;          // 最高位置1
  113.                                 }
  114.                     else                            // 不在上述范围内则说明为误码,直接退出
  115.                                 {
  116.                                         goto start;       
  117. ……………………

  118. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表