新手,小试牛刀,通过18b20采集温度,然后通过四位数码管显示出来。
以下是proteus仿真和源程序。
大家多多指教
单片机源程序:
- #include <REGX52.H>
- #define uint8 unsigned char
- #define uint16 unsigned int
- sbit DQ =P3^7;//DS18B20数据端
- sbit KEY1=P1^0;
- sbit KEY2=P1^1;
- sbit KEY3=P1^2;
- uint16 Temperature;
- uint16 TemperatureSave;
- uint8 ReadFlag;//温度读取标志位
- uint16 RecTemperature[10];//记录的温度
- uint8 RecSum=0;//记录的数量最多10
- uint8 Fin;
- uint8 mode=0;
- uint8 code DuCode[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
- 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //共阴数码管段选码表,0-F无小数点
- uint8 code WeiCode[4]={0xFE,0xFD,0xFB,0xF7};//
- uint8 SegBus[4]={0x40,0x40,0x40,0x40};//数码管显示缓存
- code uint8 DecimalNum[16]={0,1,1,2,3,3,4,
- 4,5,6,6,7,8,8,9,9};//DS18B20读取的16bit数据最低4位对应的小数4舍5入取一位
- void SegShow(void);//数码管显示函数
- void Timer0Init(void);//定时器初始化函数
- uint16 ReadTemp(uint8 mode);//读取温度函数
- void ShowTemperature(uint16 temperature,uint8* str);
- void main(void)
- {Timer0Init();
- ReadTemp(0);
- while(1)
- {
- if(KEY1==0)
- {
- mode=(mode+1)%2;//模式
- while(KEY1==0);
- }
- if(mode==1)//温度查询 +
- {
- if(KEY2==0)
- {
- Fin=(Fin+1)%10;
- while(KEY2==0);
- }
- if(KEY3==0)
- {
- if(--Fin==255)Fin=0;
- while(KEY3==0);
- }
-
- }
- if(ReadFlag)//已经读取到温度
- {
- ReadFlag=0;
- if(TemperatureSave!=Temperature)
- {
- TemperatureSave=Temperature;
- RecTemperature[RecSum++]=Temperature;
- RecSum=RecSum%10;
- }
- if(mode==0)
- {
- ShowTemperature(Temperature,SegBus);
- }
- else
- {
- ShowTemperature(RecTemperature[Fin],SegBus);
- }
- SegBus[2]|=0x80;//添加小数点;
- }
- SegShow();
- }
- }
- /**************************************************
- 定时器初始化函数50ms定时中断
- **************************************************/
- void Timer0Init(void)
- {
- TMOD=0x01;
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- TR0=1;
- ET0=1;
- EA=1;
- }
- /**************************************************
- 定时器中断函数
- **************************************************/
- void Timer0_ISR(void) interrupt 1
- {
- static uint8 cnt=0;
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- cnt++;
- if(cnt>15)//每隔750ms读取一次温度
- {
- Temperature=ReadTemp(1);//读取温度
- cnt=0;
- ReadTemp(0);//启动温度转换
- ReadFlag=1;
- }
- }
- /**************************************************
- 数码管用延时函数
- **************************************************/
- void DelaySeg(void)
- {
- uint8 i;
- for(i=0;i<110;i--);
- }
- /**************************************************
- 1位十进制转数码管段码
- **************************************************/
- void Dec1ToSeg(uint8 dec,uint8 *str)
- {
- str[0]=0;//百位不显示
- str[1]=0;//个位不显示
- str[2]=DuCode[dec];
- }
- /**************************************************
- 2位十进制转数码管段码
- **************************************************/
- void Dec2ToSeg(uint8 dec,uint8 *str)
- {
- str[0]=0;
- str[1]=DuCode[dec/10];
- str[2]=DuCode[dec%10];
- }
- /**************************************************
- 3位十进制转数码管段码
- **************************************************/
- void Dec3ToSeg(uint8 dec,uint8 *str)
- {
- str[0]=DuCode[dec/100];
- str[1]=DuCode[dec%100/10];
- str[2]=DuCode[dec%10];
- }
- /**************************************************
- 显示温度信息
- **************************************************/
- void ShowTemperature(uint16 temperature,uint8* str)
- {
- if(temperature&0x8000)//负温度
- {
- temperature=~temperature+1;
- str[3]=DuCode[DecimalNum[temperature&0x0f]];//计算小数部分
- temperature=temperature>>4;
- if(temperature>9)//负温度的时候最多只有2位整数部分
- {
- Dec3ToSeg(temperature,str);
- str[0]=0x40;//-
- }
- else
- {
- Dec2ToSeg(temperature,str);
- str[1]=0x40;//-;
- }
- }
- else
- {
- str[3]=DuCode[DecimalNum[temperature&0x0f]];//计算小数部分
- temperature=temperature>>4;
- if(temperature>99)
- {
- Dec3ToSeg(temperature,str);
- }
- else if(temperature>9)
- {
- Dec2ToSeg(temperature,str);
- }
- else
- {
- Dec1ToSeg(temperature,str);
- }
- }
- }
- /**************************************************
- 数码管显示
- **************************************************/
- void SegShow(void)
- {
- P0=0x00;
- P2=WeiCode[0];
- P0=SegBus[0];
- DelaySeg();
- P0=0x00;
- P2=WeiCode[1];
- P0=SegBus[1];
- DelaySeg();
- P0=0x00;
- P2=WeiCode[2];
- P0=SegBus[2];
- DelaySeg();
- P0=0x00;
- P2=WeiCode[3];
- P0=SegBus[3];
- DelaySeg();
- }
- /**************************************************
- 大致延时一次延时2*t+7us
- **************************************************/
- void DelayUs(uint8 t)
- {
- while(--t);
- }
- /**************************************************
- DS18B20初始化
- **************************************************/
- void DS18B20Init(void)
- {
- DQ = 1; //DQ复位
- DelayUs(10); //稍做延时
- DQ = 0; //单片机将DQ拉低
- DelayUs(200);//精确延时 大于 480us 小于960us
- DelayUs(200);
- DQ = 1; //拉高总线
- DelayUs(75); //15~60us 后 接收60-240us的存在脉冲
- DelayUs(75);
- }
- /**************************************************
- 读取一个字节数据,返回uchar类型数据
- **************************************************/
- uint8 DS18B20Read(void)
- {
- uint8 i=0;
- uint8 cdat=0;
- for(i=8;i>0;i--)
- {
- DQ=0;//给脉冲信号
- cdat>>=1;
- DQ = 1; // 给脉冲信号
- if(DQ)
- cdat|=0x80;
- DelayUs(50);
- }
- return (cdat);
- }
- /**************************************************
- * 功能描述: 向DS18B20写一个字节数据
- **************************************************/
- void DS18B20Write(uint8 cdat)
- {
- unsigned char i=0;
- for(i=8;i>0;i--)
- {
- DQ=0;
- DQ=cdat&0x01;
- DelayUs(50);
- DQ=1;
- cdat>>=1;
- }
- DelayUs(50);
- }
- /**************************************************
- * 功能描述: 读取温度值,返回uint类型数据
- **************************************************/
- uint16 ReadTemp(uint8 mode)
- {
- unsigned char a=0;
- unsigned int b,t;
- DS18B20Init();
- DS18B20Write(0xCC); // 跳过读序号列号的操作
- switch(mode)
- {
- case 0:
- DS18B20Write(0x44); // 启动温度转换
- return 0;
- case 1:
- DS18B20Write(0xBE); //读取温度寄存器
- a=DS18B20Read(); //低位
- b=DS18B20Read(); //高位
- b<<=8;
- t=a+b;
- return (t);
- default:return 0;
- }
- return (0);
- }
复制代码
下载:
数码管DS18B20温度整点记录.zip
(70.75 KB, 下载次数: 122)
|