郭天祥51单片机的实时环境温度(AD/DA芯片的应用)

阅读: 评论:0

郭天祥51单片机的实时环境温度(AD/DA芯片的应用)

郭天祥51单片机的实时环境温度(AD/DA芯片的应用)


  如果学习51单片机,郭天祥的开发板是比较经典的一款,学习到最后可能会需要做一个综合应用的作业,我们的综合作业就是在单片机上实现实时监测环境温度,并且当温度改变时通过串口通信发送给串口调试助手,同时需要将温度通过I2C储存。
   程序有三个模式:
   第一个模式是单片机刚启动时,显示上次断电时的温度;
   第二个模式是显示实时温度,同时在温度变化时通过串口通信发送给串口调试助手,并且通过I2C储存。
   第三个模式是PC通过串口调试助手发送0-7来调节DA芯片控制的LED灯的亮度,亮度为8个等级,通过开发板上的8个LED灯来表示目前处于第几级亮度。
   模式的切换通过外部中断1来控制,可以将外部中断1口与P3.7通过杜邦线连接起来,这样就可以通过独立按键的最后一个来切换模式。
   实现的代码如下:

#include <reg52.h>
#define uchar unsigned char;
#define uint unsigned int;//码字表部分//段选码字表0~9
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//ASCII码字表
uchar code tableAscii[]={'0','1','2','3','4','5','6','7','8','9'};
//把电流分为八个大等级,形成码字表(32是一个大等级)
uchar code electricLevel[]={0x1f,0x3f,0x5f,0x7f,0x9f,0xbf,0xdf,0xff};
//LED灯指示等级
uchar code showLevel[]={0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01,0x00};
//位选码字表
uchar code tablewela[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
//显示数组--AD
uchar ToDisplay[6]={0,0,0,0,0,0};//位定义部分
sbit dula=P2^6;				//段选
sbit wela=P2^7;				//位选
sbit sda=P2^0;				//数据线
sbit scl=P2^1;				//时钟线
sbit csda=P3^2;				//DA片选
sbit wr=P3^6;				//DA写入
sbit DS18B20_IO=P2^2; 		//温度传感器io口//全局变量定义部分
uchar buf;					//承接接收的数据
uchar current=0;			//用于数码管动态显示
uint temperture;			//温度
uchar last_temperture;		//记录上次温度
uchar ge,shi,bai;			//将显示的温度分为三位
uchar flag=0;				//运行模式
uchar number1,number2;		//帮助掉电重连//函数申明部分
void initial();				//初始化
void Display();				//数码管显示
void whenGetValue();		//当收到串口调试助手数据时
void IIC_init();			//IIC初始化
void write();				//写入数据
void read();				//读取数据
void update();				//温度数据更新
void DS18B20_change();		//开始温度转换
void restart();				//掉电重连//延时函数部分
void someNop(){					//微秒级延时;;;
}
void delay8ms(){				//8ms的延时unsigned int a,b;for(a=24;a>0;--a){Display();for(b=0;b<300;++b);	}
}
void delayXms(unsigned int x){	//延时Xmsunsigned char a,b,c;for(a=x;a>0;a--)for(b=10;b>0;b--)for(c=100;c>0;c--);
}//主函数部分
void main(){initial();read();restart();while(1){while(flag==0){delay8ms();}while(flag==1){Display();update();}wela=1;P0=0xff;wela=0;dula=1;P0=0;dula=0;while(flag==2);}
}//掉电重连部分
void restart(){										//上电后将掉电前的值发送给电脑char i;for(i=0;i<10;i++){if(ToDisplay[0]==table[i]){number1=i;break;}}for(i=0;i<10;i++){if(ToDisplay[1]==table[i]){number2=i;break;}}SBUF=number1*16+number2;delay8ms();delay8ms();delay8ms();for(i=0;i<10;i++){if(ToDisplay[2]==table[i]){number1=i;break;}}SBUF=number1;
}//DA转换部分
void Exchange(){									//将ASCII码转换成对应码字表位if(buf>=48&&buf<=57)		//'0'<buf<'9'{buf=buf-48;				//buf-'0'}
}
void DA_SignalControl_LED(unsigned char input_DA){  //进行DA转换csda=0;wr=0;P0=input_DA;
}
void initial(){										//初始化TMOD=0x20;				//设置定时器1为工作方式2TH1=0xfd;				//设置常量值	TL1=0xfd;				//设置初值TR1=1;					//打开定时器1SCON=0x50;				//选择方式1,REN置1EA=1;					//打开总中断ES=1;					//打开串口中断EX1=1;					//外部中断1				IT1=1;					//跳边沿触发IIC_init();				//IIC初始化DS18B20_change();		//开始温度转换
}//串行口中断程序
void ser() interrupt 4{							//串口中断if(RI==1){RI=0; 				//数据buf=SBUF;			//承接接收到的数据Exchange();			//将ASCII码转换成对应码字表位DA_SignalControl_LED(electricLevel[buf]);P1=showLevel[buf];}else if(TI==1){TI=0;}
}
void INT_1() interrupt 2{						//外部中断1flag++;if(flag==3){flag=1;}P1=~P1;
}//DS18B20部分
unsigned char DS18B20_delay;					//用于温度传感器分脉冲延时
void DS18B20_reset(){							//DS18B20复位DS18B20_IO=1;someNop();DS18B20_IO=0;DS18B20_delay=108;while(DS18B20_delay>0)DS18B20_delay--;DS18B20_IO=1;DS18B20_delay=8;while(DS18B20_delay>0)DS18B20_delay--;
}
bit DS18B20_read_bit(){							//DB18B20读取一位bit B;DS18B20_IO=0;DS18B20_delay++;DS18B20_IO=1;DS18B20_delay++;DS18B20_delay++;B=DS18B20_IO;DS18B20_delay=8;while(DS18B20_delay>0)DS18B20_delay--;return B;
}
uchar DS18B20_read_byte(){						//DB18B20读取一个字节unsigned char i,j,byte_data;byte_data=0;for(i=0;i<8;i++){j=DS18B20_read_bit();byte_data=(j<<7)|(byte_data>>1);//把获得的字节逆序}return byte_data;
}
void DS18B20_write_byte(unsigned char byte_data){//DB18B20写入一个字节unsigned char i,j;bit tmp_bit;for(i=0;i<8;i++){tmp_bit=byte_data&0x01;byte_data=byte_data>>1;if(tmp_bit){DS18B20_IO=0;j++;j++;DS18B20_IO=1;DS18B20_delay=8;while(DS18B20_delay--);}else{DS18B20_IO=0;j++;j++;DS18B20_delay=8;while(DS18B20_delay--);DS18B20_IO=1;DS18B20_delay++;DS18B20_delay++;}}
}
void DS18B20_change(){							//开始温度转换DS18B20_reset();			//复位delayXms(1);DS18B20_write_byte(0xcc);	//跳过DS18B20_write_byte(0x44);	//开始温度转换
}
uint DS18B20_getTemperature(){					//获得温度unsigned char a,b;float real_temperture;DS18B20_reset();		//复位delayXms(1);DS18B20_write_byte(0xcc);//跳过ROM选择DS18B20_write_byte(0xbe);//获取温度a=DS18B20_read_byte();b=DS18B20_read_byte();temperture=b;			//获取高位temperture<<=8;temperture=temperture|a;//获取低位real_temperture=temperture*0.0625;//获取真实温度temperture=real_temperture*10+0.5;//四舍五入法保留一位小数return temperture;
}
void Display(){		 							//数码管显示wela=1;P0=tablewela[current];	//取位选值wela=0;P0=0x0;dula=1;P0=ToDisplay[current];	//取段选值dula=0;P0=0xff;current++;				if(current==3){current=0;}
}
void update(){									//更新ToDisplay中的值int tmp;DS18B20_change();		//开始温度转换Display();				//延时一下tmp=DS18B20_getTemperature();bai=tmp/100;shi=tmp/10%10;ge=tmp%10;ToDisplay[0]=table[bai];ToDisplay[1]=table[shi]+0x80;		ToDisplay[2]=table[ge];if(tmp!=last_temperture){last_temperture=tmp;tmp=bai*16+shi;SBUF=tmp;write();SBUF=ge;}	}//IIC部分
void IIC_init(){							//IIC初始化sda=1;someNop();scl=1;someNop();
}
void start(){								//开始接收数据sda=1;someNop();scl=1;someNop();sda=0;someNop();scl=0;someNop();
}
void stop(){								//停止接收数据sda=0;someNop();scl=1;someNop();sda=1;someNop();scl=0;someNop();
}
void ack(){									//等待应答unsigned char i=0;IIC_init();while((sda==0)&&(i<250))i++;scl=0;someNop();
}
void write_byte(unsigned char _data){		//写入数据unsigned char tmp,i;tmp=_data;scl=0;someNop();for(i=0;i<8;++i){tmp=tmp<<1;sda=CY;someNop();scl=1;someNop();scl=0;someNop();}
}
uchar read_byte(){							//读取数据unsigned char i,j,k;scl=0;someNop();for(i=0;i<8;++i){scl=1;someNop();j=sda;someNop();k=(k<<1)|j;scl=0;someNop();}return k;
}
void write(){								//将数码管内容写入24C02unsigned char i;for(i=0;i<3;++i){start();write_byte(0xa0);ack();write_byte(i);ack();write_byte(ToDisplay[i]);ack();stop();delay8ms();}}
void read(){								//从24C02中读出六位数据unsigned char i;for(i=0;i<3;++i){start();write_byte(0xa0);ack();write_byte(i);ack();start();write_byte(0xa1);ack();ToDisplay[i]=read_byte();stop();}}


  由于时间问题,以上的代码有些细节未经过处理,如外部中断可能触发多次,这个问题可以通过延时来解决,可以延时200ms或者更多的时间,只要保证在这个时间段内使用者不会想要连续按两次即可。或者通过按键消抖加上松手检测也可以解决。

本文发布于:2024-02-03 01:38:56,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170689553447799.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23