【前言】
红外遥控器常用的调制制式主要分为两种,这里主要讲解以NEC调制方式的遥控器解码过程。
废话不多说,直接上时序图!( 更多详细资料自行查询)
总时序图:
前导码:
' 0 ' 和 ' 1 ' 编码表示:
【解码思路】
-----1、 使用定时器计算高低电平的时间
-----2、 使用数组存放一组完整的电平时间编码
-----3、 计算电平的时长
-----4、 组合数据,获得编码值,存放于数组
-----5、 LCD1602管显示
【编写程序】
/*--------------------------------------------------------
程序功能: 51红外遥控器解码程序
功能详情: 遥控解码后送数码管依次显示,共4字节 .( 12MHz晶振 )
编写时间: 2017/9/7
编写人: 吴**
--------------------------------------------------------*/
#include #include #define uchar unsigned char #define uint unsigned int #define display_data P0 sbit LCD_RS=P1^0; sbit LCD_RW=P1^1; sbit LCD_EN=P1^2; uchar irtime = 0; uchar startflag = 0; // 起始标志位 uchar ir_rc_ok = 0; // 红外高/低电平时间接收完成标志位 uchar bitnum = 0; uchar ir_change_ok = 0; // 转码完成标志位 uchar irdata[33]; // 电平时间数组 uchar ircode[4]; // 遥控解码数组 // 字符编码 uchar str[17]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F',' '}; /********* 延时函数 **********/ void delayms(uint xms) { uint i,j; for(i=xms;i>0;i--) for(j=110;j>0;j--); } /********** 系统初始化 ********/ void sysinit() { // 初始化定时器 TMOD = 0x02; // 设置定时器0为工作方式2 (0~255) TH0 = 0x00; // 赋初值 TL0 = 0x00; TR0 = 1; // 启动定时器0 ET0 = 1; // 使能定时器0 // 初始换外部中断1 IT1 = 1; // 下降沿触发 EX1 = 1; // 开外部中断0 EA = 1; // 开总中断 } /************ 转换编码 *************/ void changecode() { uchar k = 1; uchar i,j; uchar value; if(ir_rc_ok ==1) // 如果ir接收完成就进行转码 { for(i=0;i<4;i++) // 获取前导码后的4个字节数据 { for(j=0;j<8;j++) { value = value>>1; // 因低位在前,所以需右移 if(irdata[k]>6&&irdata[k]<10) // 判断数据是否为" 1 ",从第2位开始接收 { value |= 0x80; } k++; } ircode[i] = value; // 存储1个字节数据 } ir_change_ok = 1; // 编码转换完成标志位 ir_rc_ok = 0; // ir接收标志复位 } } /********** 1602写指令 ***********/ void write_com(uchar com) { LCD_RS=0; //RS =‘low’为写指令 LCD_RW=0; display_data=com; delayms(5); LCD_EN=1; delayms(5); LCD_EN=0; } /*********** 1602写数据 ***********/ void write_data(uchar wdata) { LCD_RS=1; //RS ='high'为写数据 LCD_RW=0; display_data=wdata; delayms(3); LCD_EN=1; delayms(5); LCD_EN=0; } /*********** 1602显示屏初始化 ***********/ void disinit() { LCD_EN=0; //初始化使能 write_com(0x38); //设置显示模式 write_com(0x0f); //设置显示开/关及光标 write_com(0x06); //设置指针位置及移屏 write_com(0x80); //数据指针初始化( +0x10 指针移至显示区外) } /************* 1602显示解码结果 *****************/ void display() { uchar num,high,low; if(ir_change_ok == 1) // 判断编码是否转换完毕 { ir_change_ok = 0; write_com(0x80); // 重复调用时,显示指针复位 for(num=0;num<4;num++) { high = ircode[num]/16; low = ircode[num]%16; write_data(str[high]); write_data(str[low]); write_data(str[16]); // 显示空格 } } } /********** 主函数 *************/ void main() { sysinit(); // 初始化 disinit(); // 显示屏初始化 while(1) { changecode(); // 获取编码 display(); // 显示解码后的编码 } } /********* 定时器0中断服务函数 ***********/ void t0()interrupt 1 { irtime++; } /********* 外部中断1服务函数 ***********/ void exint1() interrupt 2 { if(startflag) { if(irtime>32) // 检测前导码 { bitnum=0; } irdata[bitnum]=irtime; // 从前导码开始接收数据 irtime=0; bitnum++; if(bitnum==33) // 前导码+4字节数据,共 33 比特 { bitnum=0; ir_rc_ok = 1; } } else { startflag = 1; irtime = 0; } }
上一篇:51单片机工作于方式0的定时器模式
下一篇:51单片机定时器工作方式1、2原理详解
推荐阅读最新更新时间:2024-11-12 11:01