51单片机移植的NEC协议的通用红外外解码程序
搞了几天的关于NEC协议的红外位置遥控器解码程序,发现好多网上帖子给出的参考代码移植代码解码程序尤为困难,特此在参考了STC15w4k系列参考范例后,在其基础上增加了数字按键解码到数码管显示,所有键位解码到8位LED显示代码,特别说明移植相当方便!!!只是其晶振频率要求22.1148mhz,其他晶振频率范围需要修改相关寄存器值,会比较麻烦,解码成功案列遥控器型号为car MP3,同时适用该协义下所有遥控器,并且支持解码数据串口发送到电脑端显示,由于芯片和遥控器型号都是资源比较少的,特此分享好东西,希望大家积极指
有效程序在测试一中.7z
(34.2 KB, 下载次数: 17)
正批评,共同讨论学习。
串口接收成功:
单片机源程序如下:
- ////////////////////////////////////////////////////////////
- // 红外接收数据,查询方式,并通过串口发送输出
- // 晶振:22.1184MHz ,波特率:9600
- ////////////////////////////////////////////////////////////
- #include <STC8.H>
- #define dataport P1
- typedef unsigned char uchar;
- typedef unsigned char uint;
- sbit LADUAN=P3^5;
- sbit LAWEI=P3^6;
- #define LED P0
- sbit Ir_Pin = P2^7; // 红外接收头信号输出脚
- uchar code lhc_duan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
- unsigned char Ir_Buf[4]; // 用于保存解码结果(Ir_Buf[0]--用户码L,Ir_Buf[3] --键反码)
- // 获取低电平时间 (其实是16位计数器的计数值,STC15系列定时器默认为16位自动重装方式)
- unsigned int Ir_Get_Low()
- {
- TL0 = 0; // 清空16位计数器0
- TH0 = 0; // 清空16位计数器0
- TR0 = 1; // 计数器0开始运行
- while (!Ir_Pin && (TH0<0x80)); // 信号引脚变成高或低电平时间>17ms退出(只要>12ms即可)
- // 0x8000=32768, 32768*0.54253uS=17777.62 uS
- TR0 = 0; // 这里 ! 优先级大于&&
- return (TH0 * 256 + TL0); // 返回16位计数器的计数值。
- }
- // 获取高电平时间(其实是16位计数器的计数值,STC15系列定时器默认为16位自动重装方式)
- unsigned int Ir_Get_High()
- {
- TL0 = 0; // 清空16位计数器0
- TH0 = 0; // 清空16位计数器0
- TR0 = 1;
- while (Ir_Pin && (TH0<0x40)); // 信号引脚变成低电平或高电平时间>17ms退出
- TR0 = 0;
- return (TH0 * 256 + TL0);
- }
- void UART_init(void) // 9600@22.1184MHz
- {
- //下面代码设置定时器1
- TMOD = 0x20; // 0010 0000 定时器1工作于方式2(8位自动重装方式)
- TH1 = 0xFA; // 波特率:57600 /22.1184MHZ
- TL1 = 0xFA; // 波特率:57600 /22.1184MHZ
- TR1 = 1;
- //下面代码设置定串口
- AUXR = 0x00; // 很关键,使用定时器1作为波特率发生器,S1ST2=0
- SCON = 0x50; // 0101 0000 SM0.SM1=01(最普遍的8位通信),REN=1(允许接收)
- }
-
- // UART发送一字节
- void UART_Send_Byte(unsigned char dat)
- {
- SBUF = dat;
- while (TI == 0);
- TI = 0; // 此句可以不要,不影响后面数据的发送,只供代码查询数据是否发送完成
- }
- void IR_work() //红外解码程序
- {
- switch(Ir_Buf[2])
- {
- case 0x0c:dataport=lhc_duan[1];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
- case 0x18:dataport=lhc_duan[2];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
- case 0x5e:dataport=lhc_duan[3];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
- case 0x08:dataport=lhc_duan[4];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
- case 0x1c:dataport=lhc_duan[5];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
- case 0x5a:dataport=lhc_duan[6];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
- case 0x42:dataport=lhc_duan[7];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
- case 0x52:dataport=lhc_duan[8];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
- case 0x4a:dataport=lhc_duan[9];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
- default:dataport=lhc_duan[0];LADUAN=1;LADUAN=0;LED=~Ir_Buf[2];break;
- }
- }
- void main()
- {
- unsigned int time;
- unsigned char i,j;
- LED=Ir_Pin;
- UART_init();
- UART_Send_Byte(0X55); // 测试串口工作是否正常
- dataport=0xfe;//取位码 第一位数码管选通,即二进制1111 1110
- LAWEI=1;
- LAWEI=0;
- dataport=lhc_duan[0];
- LADUAN=1;
- LADUAN=0;
- while (1)
- {
- start:
- ///////////// 接收同步信号 ///////////
- while (Ir_Pin); // 等待低电平出现
- time = Ir_Get_Low(); // 低电平区间16位计数器的计数值
- if ((time < 15667) || (time > 17510)) goto start;
- // 引导脉冲低电平8500~9500us,T=12/22.1184=0.54253uS
- // 8500/0.54253uS=15667.3 9500/0.54253uS=17510.5
- time = Ir_Get_High();
- if ((time < 7372) || (time > 9216)) goto start; // 引导脉冲高电平4000-5000us
- // 4000/0.54253uS=7372.8 5000/0.54253uS=9216
- ////////// 接收后续的4 字节数据 ////////
- for (i=0; i<4; i++) // 4个字节
- {
- for (j=0; j<8; j++) // 每个字节8位
- {
- time = Ir_Get_Low(); // 接收每位560us 低电平
- if ((time < 626) || (time > 1438)) goto start; // 340-780us
- // 340/0.54253uS=626.7 780/0.54253uS=1437.7
- time = Ir_Get_High(); // 接收每位560us或1690us高电平时间
- if ((time>626) && (time<1438)) // 时间范围为340-780us(中心值560us),
- {
- Ir_Buf[i] >>= 1; // 因低位在先,所以数据右移,移入的最高位为0
- }
- else if ((time>2728) && (time<3502))
- { // 时间判定范围为1480~1900us(中心值1690us)
- // 1480/0.54253uS=2727.9 1900/0.54253uS=3502.1
- Ir_Buf[i] >>= 1; // 因低位在先,所以数据右移,移入的最高位为0
- Ir_Buf[i] |= 0x80; // 最高位置1
- }
- else // 不在上述范围内则说明为误码,直接退出
- {
- goto start;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
|