1 /**************************************************************************************
2 * 红外通信实验 *
3 实现现象:下载程序后,数码管显示红外遥控键值数据
4 注意事项: 红外遥控器内的电池绝缘片一定要抽掉
5 通过该函数可以控制很多东西,因为每个按键都有一个固定的16定制的编码,故而通过if语句来进行判断这个
6 键是否按下,当按下的时候,就可以执行相应的动作
7 ***************************************************************************************/
8
9 #include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
10
11
12 typedef unsigned int u16; //对数据类型进行声明定义
13 typedef unsigned char u8;
14
15 sbit LSA=P2^2;
16 sbit LSB=P2^3;
17 sbit LSC=P2^4;
18
19 sbit IRIN=P3^2;
20
21 u8 IrValue[6];
22 u8 Time;
23
24 u8 DisplayData[8];
25 u8 code smgduan[17]={
26 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
27 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0X76};
28 //0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F、H的显示码
29
30 /*******************************************************************************
31 * 函 数 名 : delay
32 * 函数功能 : 延时函数,i=1时,大约延时10us
33 *******************************************************************************/
34 void delay(u16 i)
35 {
36 while(i--);
37 }
38
39
40 /*******************************************************************************
41 * 函数名 :DigDisplay()
42 * 函数功能 :数码管显示函数
43 * 输入 : 无
44 * 输出 : 无
45 *******************************************************************************/
46 void DigDisplay()
47 {
48 u8 i;
49 for(i=0;i<3;i++)
50 {
51 switch(i) //位选,选择点亮的数码管,
52 {
53 case(0):
54 LSA=0;LSB=0;LSC=0; break;//显示第0位
55 case(1):
56 LSA=1;LSB=0;LSC=0; break;//显示第1位
57 case(2):
58 LSA=0;LSB=1;LSC=0; break;//显示第2位
59 }
60 P0=DisplayData[2-i];//发送数据
61 delay(100); //间隔一段时间扫描
62 P0=0x00;//消隐
63 }
64 }
65
66
67 /*******************************************************************************
68 * 函数名 : IrInit()
69 * 函数功能 : 初始化红外线接收
70 * 输入 : 无
71 * 输出 : 无
72 *******************************************************************************/
73
74 void IrInit()
75 {
76 IT0=1;//下降沿触发 由于P3^2的引脚刚好连的是单片机的外部中断0 ,故而通过外部中断0来判断起始码9ms和4.5ms
77 EX0=1;//打开中断0允许
78 EA=1; //打开总中断
79
80 IRIN=1;//初始化端口 红外接收端的引脚
81 }
82
83
84 /*******************************************************************************
85 * 函 数 名 : main
86 * 函数功能 : 主函数
87 * 输 入 : 无
88 * 输 出 : 无
89 *******************************************************************************/
90 void main()
91 {
92 IrInit();
93 while(1)
94 {
95 DisplayData[0] = smgduan[IrValue[2]/16];//得到16位数的高位
96 DisplayData[1] = smgduan[IrValue[2]%16];//得到16位数的低位
97 DisplayData[2] = smgduan[16];//数码管前面定义的16为字母 H
98 DigDisplay();
99 }
100 }
101
102 /*******************************************************************************
103 * 函数名 : ReadIr()
104 * 函数功能 : 读取红外数值的中断函数
105 * 输入 : 无
106 * 输出 : 无
107 *******************************************************************************/
108
109 void ReadIr() interrupt 0
110 {
111 u8 j,k;
112 u16 err;
113 Time=0;
114 delay(700); //7ms
115 if(IRIN==0) //确认是否真的接收到正确的信号
116 {
117
118 err=1000; //1000*10us=10ms,超过说明接收到错误的信号
119 /*当两个条件都为真是循环,如果有一个条件为假的时候跳出循环,免得程序出错的时
120 侯,程序死在这里*/
121 while((IRIN==0)&&(err>0)) //等待前面9ms的低电平过去
122 {
123 delay(1);
124 err--;
125 }
126 if(IRIN==1) //如果正确等到9ms低电平
127 {
128 err=500;
129 while((IRIN==1)&&(err>0)) //等待4.5ms的起始高电平过去
130 {
131 delay(1);
132 err--;
133 }
134 for(k=0;k<4;k++) //共有4组数据
135 {
136 for(j=0;j<8;j++) //接收一组数据
137 {
138
139 err=60;
140 while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去
141 {
142 delay(1);
143 err--;
144 }
145 err=500;
146 while((IRIN==1)&&(err>0)) //计算高电平的时间长度。
147 {
148 delay(10); //0.1ms
149 Time++;
150 err--;
151 if(Time>30)
152 {
153 return;
154 }
155 }
156 IrValue[k]>>=1; //k表示第几组数据 将四组字节放入其中
157 if(Time>=8) //如果高电平出现大于565us,那么是1 如果Time =8的时候,表示时间为0.1mS*8=0.8ms
158 {
159 IrValue[k]|=0x80; /*当时间大于565us的时候,为位1 这里相当于读取(因为已经通过时间确定了位0还是位1相当于写入了)
160 这个数据 ,因为是读,故而才将IrValue[k]>>=1;放在IrValue[k]|=0x80;的上面
161 将其先放在高位,之后通过上面的IrValue[k]>>=1;
162 这个语句将其移到下一位 ,这样就可以将其8位依次由低位移到高位 */
163 }
164 Time=0; //用完时间要重新赋值 当用Time确定完之后,就要重新赋0,一边下一次使用
165 }
166 }
167 }
168 if(IrValue[2]!=~IrValue[3]) //用于判断收到的数据是否正确 ,如果不正确,强行退出
169 {
170 return;
171 }
172 }
173 }