本系统由两部分组成:
>>>>上述“0”和“1”组成的32位二进制码经38kHz的载频进行二次调制以提高发射效率,达到降低电源功耗的目的。
>>>>然后再通过红外发射二极管产生红外线向空间发射。编码数据,载波,发射.
》》》接收解码如下图所示:
----》温度传感器DS18B20采集的温度
----》通过单片机处理显示在液晶上
----》对温度数据进行编码,通过红外发射电路将温度信息发射出去。
此次用的是DSl8B20作为温度传感器进行温度采集,然后将温度数据转化为电信号,通过红外线发射,再让接受端收到温度信息,并显示出来。因为焊接的是单片机最小系统,所以,我们用的就是无线红外发射管和无线红外接收管来实现发送端与接收端数据的传输,基本可以实现五米以上距离的信息传输。
接收端主循环一直检测红外是否接收完成,如果完成清除完成标志,并进行数据校验,校验通过则对红外数据进行转换,temperature为全局,将在display.c由定时器扫描数码管进行显示。信号灯的闪烁则利用ledcount变量自减进行控制
发送端主循环以一定间隔进行18B20温度读取,再将温度数据转换为红外数据码,进行红外发射,伴随信号灯闪烁
定时器0进行38K载波的产生。红外数据存入IR_Code数组,前两位为引导码 3——18为校验码 19——41数据具体编码0 和1 的表示参考NEC红外协议,对0 1的编码时间适当增大了,以避免其他红外遥控的干扰。
#include"18b20.h" void DelayUs2x(unsigned char t) { while(--t); } void DelayMs(unsigned char t) //延时tms { while(t--) { DelayUs2x(245);DelayUs2x(245); } //大致延时1mS } /*------------------------------------------------ 18b20初始化 ------------------------------------------------*/ bit Init_DS18B20(void) { bit dat=0;DQ = 1; //DQ复位 DelayUs2x(10);DQ = 0; //稍做延时 //单片机将DQ拉低 DelayUs2x(200); DelayUs2x(200); //精确延时 大于 480us 小于960us DQ = 1; DelayUs2x(50); //拉高总线 //15~60us 后 接收60-240us的存在脉冲 dat=DQ; DelayUs2x(25); //如果x=0则初始化成功, x=1则初始化失败 //稍作延时返回 return dat; } /*------------------------------------------------ 读取一个字节 ------------------------------------------------*/ unsigned char ReadOneChar(void) { unsigned char i=0; unsigned char dat = 0; for (i=8;i>0;i--) { DQ = 0; dat>>=1; DQ = 1; // 给脉冲信号 // 给脉冲信号 if(DQ) dat|=0x80; DelayUs2x(25); } return(dat); } /*------------------------------------------------ 写入一个字节 ------------------------------------------------*/ void WriteOneChar(unsigned char dat) { unsigned char i=0; for (i=8; i>0; i--) {DQ = 0; DQ = dat&0x01; DelayUs2x(25); DQ = 1; dat>>=1; } DelayUs2x(25); } /*------------------------------------------------ 读取温度 ------------------------------------------------*/ unsigned int ReadTemperature(void) { unsigned char a=0;unsigned int b=0;unsigned int t=0; Init_DS18B20(); WriteOneChar(0xCC); // 跳过读序号列号的操作 WriteOneChar(0x44); // 启动温度转换 DelayMs(20); Init_DS18B20(); WriteOneChar(0xCC); //跳过读序号列号的操作 WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度 a=ReadOneChar(); //低位 b=ReadOneChar(); //高位 t = ((int)b << 8) + a; return(t); }
/**************数据转换函数************** ***函数名 :DataConversion ***参 数 :待转换的数值num,红外码存放地址 irdata ***功 能 :将数值转换为红外发射码 ***返回值 :无 #define IR_CODE_0 20 //发射码的0 #define IR_CODE_1 50 #define IR_CODE_START 240 //发射码起始 #define IR_CODE_SIZI 42 //发射码个数 *****************************************/ void DataConversion(unsigned int num,unsigned char* irdata) { unsigned char i=IR_CODE_SIZI-3,n=1,f=1; IrcodeReset(); //存储区初始化 for(n=3;n<18;n+=2) //前8个存放校验码10101010 0xAA { if(f) { irdata[n] = IR_CODE_1; f=0; } else { irdata[n] = IR_CODE_0;f=1;} } while(num!=0) //数据码存放 十进制转二进制 { if(num%2) { irdata[i] = IR_CODE_1; } else { irdata[i] = IR_CODE_0; } num = num/2; i-=2; } } /**************红外波发射函数************** ***函数名 :SendIrWave() ***参 数 :储存红外编码数据的首地址irdata ***功 能 :以红外的方式发送irdata 的红外波形数据 ***返回值 :无 *****************************************/ void SendIrWave(unsigned char* irdata) { unsigned char count=0; unsigned char i=0; while(1) //发射引导码 校验码 数据码 { ON_CARR; for(i=irdata[count]; i>0; i--) //载波发射延时 { CarrierWave_DELAY; } OFF_CARR; IR_SEND_OFF; //低电平保持 count++; for(i=irdata[count]; i>0; i--) //低电平延时 { Low_DELAY; } if(count == IR_CODE_SIZI-1) //发射结束 { break; } count++; } }
/*******红外数据接收初始化函数********* ***函数名 :InitIrReceive ***参 数 :无 ***功 能 :配置红外接收需要的定时器和中断 ***返回值 :无 *****************************************/
void InitIrReceive(void) { /*------------------------------------------------ 定时器0初始化 ------------------------------------------------*/ TMOD|= 0x02;//定时器0工作方式2,TH0是重装值,TL0是初值 //8位自动重装 TH0 = 0x00;//重载值 TL0 = 0x00;//初始化值 ET0 = 1; //开中断 TR0 = 1; //定时器/计数器启动 /*------------------------------------------------ 外部中断0初始化 ------------------------------------------------*/ IT0 = 1; //指定外部中断0下降沿触发,INT0 (P3.2) EX0 = 1; //使能外部中断 EA = 1; }
/*******红外数据时间计数函数********* ***函数名 :IRTimeCount() ***参 数 :无 ***功 能 :记录每两个红外脉冲时间间隔 ***返回值 :无 *****************************************/ void IRTimeCount() interrupt 1 { Ir_Time_count++; } /*************红外码接收中断函数*********** ***函数名: IRReceive(void) ***参 数: 无 ***功能描述:接收红外码,存入IR_CODE ***返回值: 无 *****************************************/ void IRReceive() interrupt 0 { static startflag=0,bitnum=0; if(startflag) { if(Ir_Time_count<IR_START_TIEM_MAX && Ir_Time_count>IR_START_TIEM_MIN) //引导码判断 {bitnum=0; } IR_CODE[bitnum]=Ir_Time_count; //引导码 TC9012的头码,9ms+4.5ms Ir_Time_count=0; bitnum++; if(bitnum==IR_CODE_SIZI) //接收完成 {IR_RECEIVE_OK=1; bitnum=0;} } else //第一个触发信号 {Ir_Time_count=0; startflag=1; } }
/************红外码数据转换函数*********** ***函数名: DataConversion() ***参 数: 无 ***功能描述:接收红外码,存入IR_CODE ***返回值: 数据区的数据 *****************************************/ unsigned int DataConversion(void) { unsigned char i=9; unsigned int num=0; for(i=9;i<IR_CODE_SIZI-1;i++) { if(IR_CODE[i]>IR_CODE_1) { num+=pow(2,IR_CODE_SIZI-2-i);//二进制转十进制 } } return num; } /*************红外码数据校验*********** ***函数名: CheckSucceed() ***参 数: 无 ***功能描述:转换IR_CODE 1——8的校验码,与事先设定值进行比较判断 ***返回值: 成功1 失败0 *****************************************/ unsigned char CheckSucceed(void) { unsigned char i=1; unsigned int num=0; for(i=1;i<9;i++) //校验码位于1——8 { if(IR_CODE[i]>IR_CODE_1) { num+=pow(2,8-i); //转换 } } if(num==CHECK_NUM && IR_CODE[0]>IR_START_TIEM_MIN && IR_CODE[0]<IR_START_TIEM_MAX) //校验码和引导码均校验 { return 1; } else { return 0; } }