基于51单片机的红外遥控切换数码管显示系统设计
一、项目背景
1.1 设计背景
随着现代电子技术的快速发展,红外遥控技术因其抗干扰能力强、传输可靠、功耗低等优点,已经广泛应用于各种家用电器和电子设备中。红外遥控系统具有以下特点:
非接触式控制 :无需物理连接,操作方便
抗电磁干扰 :红外线不易受到电磁信号的干扰
安全性好 :红外信号不会穿透墙壁,具有较好的保密性
成本低廉 :红外发射和接收器件价格低廉,易于集成
1.2 设计目的
本项目旨在设计并实现一个基于51单片机的红外遥控数码管显示系统,主要目的包括:
掌握51单片机的基本编程方法和中断处理机制
理解红外遥控编码协议(NEC协议)的工作原理
学习数码管的动态扫描显示技术
培养嵌入式系统的软硬件协同设计能力
1.3 应用场景
该系统可应用于:
教学实验平台,用于学习红外通信和单片机开发
简单的遥控显示设备原型开发
家用电器的遥控接收显示模块
智能家居控制系统的输入显示单元
1.4 红外遥控的原理
红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点,被诸多电子设备特别是家用电器广泛采用,并越来越多的应用到计算机系统中。
由于红外线遥控不具有像无线电遥控那样穿过障碍物去控制被控对象的能力,所以,在设计红外线遥控器时,不必要像无线电遥控器那样,每套(发射器和接收器)要有不同的遥控频率或编码(否则,就会隔墙控制或干扰邻居的家用电器),所以同类产品的红外线遥控器,可以有相同的遥控频率或编码,而不会出现遥控信号“串门”的情况。这对于大批量生产以及在家用电器上普及红外线遥控提供了极大的方便。由于红外线为不可见光,因此对环境影响很小,再由红外光波动波长远小于无线电波的波长,所以红外线遥控不会影响其他家用电器,也不会影响临近的无线电设备。
红外遥控通信系统一般由红外发射装置和红外接收设备两大部分组成。
二、方案设计
2.1 系统功能需求
本系统要求实现以下功能:
红外信号接收 :系统能够接收标准NEC协议的红外遥控信号
按键识别 :识别红外遥控器的21个按键(0-20),每行3个按钮,共7行
数码管显示 :
对于0-20号按键:显示对应的十进制数字(两位数码管)
对于其他按键:显示按键编码的十六进制值
始终显示"H"标识符,表示十六进制模式
2.2 总体方案
系统采用模块化设计思想,主要分为以下几个模块:
graph LR
A[红外遥控器] -->|红外信号| B[红外接收模块]
B -->|电平信号| C[51单片机]
C -->|段码/位选| D[数码管显示模块]
style A fill:#e1f5ff
style B fill:#ffe1e1
style C fill:#fff4e1
style D fill:#e1ffe1
核心控制器 :STC89C52单片机(或兼容的51系列)
主频:12MHz晶振
内存:8KB Flash,256B RAM
I/O口:充足,满足数码管和红外接收需求
系统工作流程 :
红外接收头接收遥控器发出的红外信号
信号经解调后输入单片机的外部中断0引脚(P3.2)
单片机解析NEC协议,提取控制码
根据控制码查表,确定按键编号
将结果转换为数码管段码
通过动态扫描方式驱动数码管显示
2.3 技术特点
中断驱动 :采用外部中断方式接收红外信号,提高系统响应速度
协议解析 :完整实现NEC红外协议的引导码、数据位和校验机制
动态显示 :采用数码管动态扫描技术,节省I/O口资源
模块化设计 :代码按功能分层,便于维护和扩展
三、电路设计
3.1 系统硬件组成
本系统主要由以下硬件模块组成:
3.1.1 核心控制模块
芯片 :STC89C52RC单片机
晶振 :12MHz石英晶振
复位电路 :上电复位电路(RC复位)
电源 :5V直流电源供电
3.1.2 红外接收模块
接收头 :一体化红外接收头(如HS0038、VS1838等)
工作频率 :38kHz载波频率
接口 :数据输出引脚连接到单片机P3.2(INT0)
示意图如下
红外接收头引脚说明 :
引脚
功能
连接
OUT
数据输出
P3.2(INT0)
GND
地
系统地
VCC
电源
+5V
3.1.3 数码管显示模块
显示器 :8位共阴极数码管
段码控制 :P0口输出段码(A-G和DP)
位选控制 :使用74HC138译码器进行位选
P2.2(LSA)→ 74HC138的A
P2.3(LSB)→ 74HC138的B
P2.4(LSC)→ 74HC138的C
74HC138译码器真值表 :
LSC
LSB
LSA
选中位
0
0
0
第8位
0
0
1
第7位
0
1
0
第6位
0
1
1
第5位
1
0
0
第4位
1
0
1
第3位
1
1
0
第2位
1
1
1
第1位
3.2 电路设计要点
3.2.1 红外接收电路
红外接收头的输出端接单片机外部中断0(P3.2)
下降沿触发中断,接收红外信号的起始位
无需外加上拉电阻(接收头内部已集成)
3.2.2 数码管驱动电路
段码驱动 :P0口直接驱动(或通过ULN2003驱动芯片增强驱动能力)
位选驱动 :74HC138三线译码器,节省3个I/O口控制8位数码管
限流电阻 :每个段需串联限流电阻(约220Ω-470Ω)
3.2.3 电源电路
5V稳压电源供电
建议添加去耦电容(0.1μF和10μF)在电源引脚附近
3.3 引脚分配表
功能
引脚
说明
红外接收
P3.2
外部中断0输入
数码管段码
P0.0-P0.7
段码A-G和DP
位选A
P2.2
74HC138的A输入
位选B
P2.3
74HC138的B输入
位选C
P2.4
74HC138的C输入
3.4 电路示意图
开发板上红外接收模块电路,如下图所示:
从上图中可以看出,该电路是独立的,红外接收头的输出管脚接至J11端子上,为了保证红外接收头输出管脚默认为高电平,需外接一个10K上拉电阻,可在上图并没有看到有上拉电阻,在前面介绍最小系统时已知道,单片机I0口都增加了10K上拉电阻。
由于该模块电路是独立的,所以红外接收头的输出管脚J11端子可以使用任意单片机管脚连接,这里使用单片机的P3.2管脚与红外接收头输出管脚连接。
四、软件设计
4.1 软件架构
系统软件采用分层模块化设计,代码结构清晰,便于维护和扩展。
graph TD
A[main.c 主程序] --> B[ired模块<br/>红外接收]
A --> C[smg模块<br/>数码管显示]
A --> D[public模块<br/>公共函数]
B --> E[ired_init<br/>红外初始化]
B --> F[中断服务函数<br/>信号解析]
C --> G[smg_display<br/>动态扫描显示]
D --> H[delay_10us<br/>微秒延时]
D --> I[delay_ms<br/>毫秒延时]
style A fill:#ffcccc
style B fill:#ccffcc
style C fill:#ccccff
style D fill:#ffffcc
4.2 程序流程设计
4.2.1 主程序流程
flowchart LR
A([开始]) --> B[红外初始化] --> C[主循环] --> D{按键0-20?}
D -->|是| E[十进制显示] --> F[刷新数码管]
D -->|否| G[十六进制显示] --> F
F --> C
主程序设计要点 :
初始化红外接收模块(配置外部中断0)
进入主循环,持续检测红外数据
根据接收到的控制码,映射到对应的按键编号(0-20)
根据按键编号选择显示模式:
0-9:左位空白,右位显示个位
10-20:左位显示十位,右位显示个位
其他:显示十六进制编码
调用数码管显示函数更新显示内容
4.2.2 红外接收流程
flowchart LR
A([中断触发]) --> B[检测引导码] --> C[接收4字节数据] --> D{校验通过?}
D -->|是| E[保存数据]
D -->|否| F[清零数据]
E --> G([返回])
F --> G
NEC协议解析要点 :
引导码识别 :9ms低电平 + 4.5ms高电平
数据位解码 :
每位以0.56ms低电平开始
数据"0":0.56ms高电平
数据"1":1.68ms高电平
数据格式 :4字节(地址码 + 地址反码 + 控制码 + 控制反码)
校验机制 :控制码与控制反码互为按位取反,用于验证数据正确性
4.2.3 数码管显示流程
flowchart LR
A([smg_display]) --> B[循环8位] --> C[位选控制] --> D[输出段码] --> E[延时] --> F{继续?}
F -->|是| B
F -->|否| G([返回])
动态扫描原理 :
利用人眼视觉暂留效应(>50Hz刷新率)
依次点亮每一位数码管,快速循环扫描
每位显示时间约1-2ms,总刷新周期约8-16ms
4.3 核心代码分析
4.3.1 按键映射表(main.c)
本系统将红外遥控器的21个按键映射到0-20的编号:
1 2 3 4 5 6 7 8 switch (gired_data[2 ]) { case 0x45 : num = 0 ; break ; case 0x46 : num = 1 ; break ; case 0x47 : num = 2 ; break ; case 0x4A : num = 20 ; break ; }
4.3.2 显示逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 if (num>=0 && num<=20 ) { if (num<10 ) { ired_buf[0 ]=0x00 ; ired_buf[1 ]=gsmg_code[num]; } else { ired_buf[0 ]=gsmg_code[num/10 ]; ired_buf[1 ]=gsmg_code[num%10 ]; } } else { ired_buf[0 ]=gsmg_code[gired_data[2 ]/16 ]; ired_buf[1 ]=gsmg_code[gired_data[2 ]%16 ]; } ired_buf[2 ]=0X76 ;
4.4 模块接口设计
4.4.1 public模块(公共函数)
1 2 3 4 5 6 7 8 typedef unsigned int u16;typedef unsigned char u8;typedef unsigned long u32;void delay_10us (u16 ten_us) ; void delay_ms (u16 ms) ;
4.4.2 ired模块(红外接收)
1 2 3 4 5 extern u8 gired_data[4 ]; void ired_init (void ) ;
初始化配置 :
IT0=1:设置外部中断0为下降沿触发
EX0=1:使能外部中断0
EA=1:开启全局中断
4.4.3 smg模块(数码管显示)
1 2 3 4 5 6 extern u8 gsmg_code[17 ]; void smg_display (u8 dat[], u8 pos) ;
段码表(共阴极) :
1 2 3 0:0x3f 1:0x06 2:0x5b 3:0x4f 4:0x66 5:0x6d 6:0x7d 7:0x07 8:0x7f 9:0x6f A:0x77 B:0x7c C:0x39 D:0x5e E:0x79 F:0x71
4.5 具体函数实现
4.5.1 红外初始化函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include "ired.h" u8 gired_data[4 ]; void ired_init (void ) { IT0=1 ; EX0=1 ; EA=1 ; IRED=1 ; }
因为我们使用外部中断 0 来解码红外遥控数据,所以需初始化配置外部中断 0
4.5.2 红外解码函数
初始化外部中断后,中断就已经开启了,当P32引脚来一个下降沿,就会触发一次中断,在中断内我们可以计算高电平时间,通过高电平时间判断是否进入引导码及数据0和1。具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 void ired () interrupt 0 { u8 ired_high_time=0 ; u16 time_cnt=0 ; u8 i=0 ,j=0 ; if (IRED==0 ) { time_cnt=1000 ; while ((!IRED)&&(time_cnt)) { delay_10us(1 ); time_cnt--; if (time_cnt==0 )return ; } if (IRED) { time_cnt=500 ; while (IRED&&time_cnt) { delay_10us(1 ); time_cnt--; if (time_cnt==0 )return ; } for (i=0 ;i<4 ;i++) { for (j=0 ;j<8 ;j++) { time_cnt=600 ; while ((IRED==0 )&&time_cnt) { delay_10us(1 ); time_cnt--; if (time_cnt==0 )return ; } time_cnt=20 ; while (IRED) { delay_10us(10 ); ired_high_time++; if (ired_high_time>20 )return ; } gired_data[i]>>=1 ; if (ired_high_time>=8 ) gired_data[i]|=0x80 ; ired_high_time=0 ; } } } if (gired_data[2 ]!=~gired_data[3 ]) { for (i=0 ;i<4 ;i++) gired_data[i]=0 ; return ; } } }
进入中断函数,表示以来下降沿,然后判断管脚是否为低电平,如果为低电平则首先判断引导信号,根据前面NEC协议可知,引导信号有9ms的低电平和4.5ms的高电平,因此通过time_cnt赋值1000,然后在while循环内判断,time_cnt每递减一次约10us,1000次则为10ms,在解码时,这个时间要适当放宽一点范围,因为不同传感器性能会有差异,所以此处以10ms的低电平为界限,如果超过10ms则强制退出,防止系统死机。判断完引导信号的低电平,接着判断高电平,实现方法一样。当引导信号判断完成后进入地址码、地址反码、控制码及控制反码共4个字节的数据判断,也就是数据0和1的判断,实现方法也是和前面判断引导信号一样,这里使用到了嵌套循环,外层循环次数是4,表示读取4个字节,内层循环次数是8,表示读取每个字节的8位。注意,红外遥控解码数据是从低位开始,最后是高位。最后将读取的4个字节数据存储在全局变量数组gired_data中,外部可直接使用这四个字节。
4.5.3 主函数
打开main.c文件,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 #include "public.h" #include "smg.h" #include "ired.h" void main () { u8 ired_buf[3 ]; ired_init(); while (1 ) { int num = -1 ; switch (gired_data[2 ]) { case 0x45 : num = 0 ; break ; case 0x46 : num = 1 ; break ; case 0x47 : num = 2 ; break ; case 0x44 : num = 3 ; break ; case 0x40 : num = 4 ; break ; case 0x43 : num = 5 ; break ; case 0x07 : num = 6 ; break ; case 0x15 : num = 7 ; break ; case 0x09 : num = 8 ; break ; case 0x16 : num = 9 ; break ; case 0x19 : num = 10 ; break ; case 0x0D : num = 11 ; break ; case 0x0C : num = 12 ; break ; case 0x18 : num = 13 ; break ; case 0x5E : num = 14 ; break ; case 0x08 : num = 15 ; break ; case 0x1C : num = 16 ; break ; case 0x5A : num = 17 ; break ; case 0x42 : num = 18 ; break ; case 0x52 : num = 19 ; break ; case 0x4A : num = 20 ; break ; default : num = -1 ; break ; } if (num>=0 && num<=20 ) { if (num<10 ) { ired_buf[0 ]=0x00 ; ired_buf[1 ]=gsmg_code[num]; } else { ired_buf[0 ]=gsmg_code[num/10 ]; ired_buf[1 ]=gsmg_code[num%10 ]; } } else { ired_buf[0 ]=gsmg_code[gired_data[2 ]/16 ]; ired_buf[1 ]=gsmg_code[gired_data[2 ]%16 ]; } ired_buf[2 ]=0X76 ; smg_display(ired_buf,6 ); } }
4.5 时序关键点
4.5.1 红外信号时序参数
参数
时间
检测阈值
引导码低电平
9ms
10ms超时
引导码高电平
4.5ms
5ms超时
数据位低电平
0.56ms
6ms超时
数据"0"高电平
0.56ms
<0.8ms
数据"1"高电平
1.68ms
≥0.8ms
4.5.2 延时函数精度
基于12MHz晶振(1个机器周期=1μs):
delay_10us(1):约10μs
delay_ms(1):约1ms
4.6 软件特色
健壮的超时机制 :每个等待阶段都有超时保护,防止程序死循环
数据校验 :通过反码校验确保接收数据的正确性
位操作高效 :使用位移和位或运算,提高数据处理效率
模块化封装 :各功能模块独立,接口清晰,便于移植和复用
五、完整开源代码
main.c文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 #include "public.h" #include "smg.h" #include "ired.h" void main () { u8 ired_buf[3 ]; ired_init(); while (1 ) { int num = -1 ; switch (gired_data[2 ]) { case 0x45 : num = 0 ; break ; case 0x46 : num = 1 ; break ; case 0x47 : num = 2 ; break ; case 0x44 : num = 3 ; break ; case 0x40 : num = 4 ; break ; case 0x43 : num = 5 ; break ; case 0x07 : num = 6 ; break ; case 0x15 : num = 7 ; break ; case 0x09 : num = 8 ; break ; case 0x16 : num = 9 ; break ; case 0x19 : num = 10 ; break ; case 0x0D : num = 11 ; break ; case 0x0C : num = 12 ; break ; case 0x18 : num = 13 ; break ; case 0x5E : num = 14 ; break ; case 0x08 : num = 15 ; break ; case 0x1C : num = 16 ; break ; case 0x5A : num = 17 ; break ; case 0x42 : num = 18 ; break ; case 0x52 : num = 19 ; break ; case 0x4A : num = 20 ; break ; default : num = -1 ; break ; } if (num>=0 && num<=20 ) { if (num<10 ) { ired_buf[0 ]=0x00 ; ired_buf[1 ]=gsmg_code[num]; } else { ired_buf[0 ]=gsmg_code[num/10 ]; ired_buf[1 ]=gsmg_code[num%10 ]; } } else { ired_buf[0 ]=gsmg_code[gired_data[2 ]/16 ]; ired_buf[1 ]=gsmg_code[gired_data[2 ]%16 ]; } ired_buf[2 ]=0X76 ; smg_display(ired_buf,6 ); } }
smg.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include "smg.h" u8 gsmg_code[17 ]={0x3f ,0x06 ,0x5b ,0x4f ,0x66 ,0x6d ,0x7d ,0x07 , 0x7f ,0x6f ,0x77 ,0x7c ,0x39 ,0x5e ,0x79 ,0x71 }; void smg_display (u8 dat[],u8 pos) { u8 i=0 ; u8 pos_temp=pos-1 ; for (i=pos_temp;i<8 ;i++) { switch (7 -i) { case 0 : LSC=1 ;LSB=1 ;LSA=1 ;break ; case 1 : LSC=1 ;LSB=1 ;LSA=0 ;break ; case 2 : LSC=1 ;LSB=0 ;LSA=1 ;break ; case 3 : LSC=1 ;LSB=0 ;LSA=0 ;break ; case 4 : LSC=0 ;LSB=1 ;LSA=1 ;break ; case 5 : LSC=0 ;LSB=1 ;LSA=0 ;break ; case 6 : LSC=0 ;LSB=0 ;LSA=1 ;break ; case 7 : LSC=0 ;LSB=0 ;LSA=0 ;break ; } SMG_A_DP_PORT=dat[i-pos_temp]; delay_10us(100 ); SMG_A_DP_PORT=0x00 ; } }
smg.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #ifndef _smg_H #define _smg_H #include "public.h" #define SMG_A_DP_PORT P0 sbit LSA=P2^2 ; sbit LSB=P2^3 ; sbit LSC=P2^4 ; extern u8 gsmg_code[17 ];void smg_display (u8 dat[],u8 pos) ;#endif
public.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #ifndef _public_H #define _public_H #include "reg52.h" typedef unsigned int u16; typedef unsigned char u8;typedef unsigned long u32;void delay_10us (u16 ten_us) ;void delay_ms (u16 ms) ;#endif
reg52.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 #ifndef __REG52_H__ #define __REG52_H__ sfr P0 = 0x80 ; sfr P1 = 0x90 ; sfr P2 = 0xA0 ; sfr P3 = 0xB0 ; sfr PSW = 0xD0 ; sfr ACC = 0xE0 ; sfr B = 0xF0 ; sfr SP = 0x81 ; sfr DPL = 0x82 ; sfr DPH = 0x83 ; sfr PCON = 0x87 ; sfr TCON = 0x88 ; sfr TMOD = 0x89 ; sfr TL0 = 0x8A ; sfr TL1 = 0x8B ; sfr TH0 = 0x8C ; sfr TH1 = 0x8D ; sfr IE = 0xA8 ; sfr IP = 0xB8 ; sfr SCON = 0x98 ; sfr SBUF = 0x99 ; sfr T2CON = 0xC8 ; sfr RCAP2L = 0xCA ; sfr RCAP2H = 0xCB ; sfr TL2 = 0xCC ; sfr TH2 = 0xCD ; sbit CY = PSW^7 ; sbit AC = PSW^6 ; sbit F0 = PSW^5 ; sbit RS1 = PSW^4 ; sbit RS0 = PSW^3 ; sbit OV = PSW^2 ; sbit P = PSW^0 ; sbit TF1 = TCON^7 ; sbit TR1 = TCON^6 ; sbit TF0 = TCON^5 ; sbit TR0 = TCON^4 ; sbit IE1 = TCON^3 ; sbit IT1 = TCON^2 ; sbit IE0 = TCON^1 ; sbit IT0 = TCON^0 ; sbit EA = IE^7 ; sbit ET2 = IE^5 ; sbit ES = IE^4 ; sbit ET1 = IE^3 ; sbit EX1 = IE^2 ; sbit ET0 = IE^1 ; sbit EX0 = IE^0 ; sbit PT2 = IP^5 ; sbit PS = IP^4 ; sbit PT1 = IP^3 ; sbit PX1 = IP^2 ; sbit PT0 = IP^1 ; sbit PX0 = IP^0 ; sbit RD = P3^7 ; sbit WR = P3^6 ; sbit T1 = P3^5 ; sbit T0 = P3^4 ; sbit INT1 = P3^3 ; sbit INT0 = P3^2 ; sbit TXD = P3^1 ; sbit RXD = P3^0 ; sbit SM0 = SCON^7 ; sbit SM1 = SCON^6 ; sbit SM2 = SCON^5 ; sbit REN = SCON^4 ; sbit TB8 = SCON^3 ; sbit RB8 = SCON^2 ; sbit TI = SCON^1 ; sbit RI = SCON^0 ; sbit T2EX = P1^1 ; sbit T2 = P1^0 ; sbit TF2 = T2CON^7 ; sbit EXF2 = T2CON^6 ; sbit RCLK = T2CON^5 ; sbit TCLK = T2CON^4 ; sbit EXEN2 = T2CON^3 ; sbit TR2 = T2CON^2 ; sbit C_T2 = T2CON^1 ; sbit CP_RL2 = T2CON^0 ; #endif
ired.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 #include "ired.h" u8 gired_data[4 ]; void ired_init (void ) { IT0=1 ; EX0=1 ; EA=1 ; IRED=1 ; } void ired () interrupt 0 { u8 ired_high_time=0 ; u16 time_cnt=0 ; u8 i=0 ,j=0 ; if (IRED==0 ) { time_cnt=1000 ; while ((!IRED)&&(time_cnt)) { delay_10us(1 ); time_cnt--; if (time_cnt==0 )return ; } if (IRED) { time_cnt=500 ; while (IRED&&time_cnt) { delay_10us(1 ); time_cnt--; if (time_cnt==0 )return ; } for (i=0 ;i<4 ;i++) { for (j=0 ;j<8 ;j++) { time_cnt=600 ; while ((IRED==0 )&&time_cnt) { delay_10us(1 ); time_cnt--; if (time_cnt==0 )return ; } time_cnt=20 ; while (IRED) { delay_10us(10 ); ired_high_time++; if (ired_high_time>20 )return ; } gired_data[i]>>=1 ; if (ired_high_time>=8 ) gired_data[i]|=0x80 ; ired_high_time=0 ; } } } if (gired_data[2 ]!=~gired_data[3 ]) { for (i=0 ;i<4 ;i++) gired_data[i]=0 ; return ; } } }
ired.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #ifndef _ired_H #define _ired_H #include "public.h" sbit IRED=P3^2 ; extern u8 gired_data[4 ];void ired_init (void ) ;#endif