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 }