① 基于单片机的数字温度计设计用C语言写程序
//------------------------------------------------------------------
//DS18B20温度传感器输出显示,运行本例时,外界温度将显示在1602LCD上
//------------------------------------------------------------------
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP() {_nop_();_nop_();_nop_();_nop_();}
sbit DQ=P2^2;
sbit la=P2^6; //定义锁存器锁存端
sbit wela=P2^7;
sbit rs=P3^5; //定义1602液晶RS端
sbit lcden=P3^4;//定义1602液晶LCDEN端
sbit s1=P3^0; //定义按键--功能键
sbit s2=P3^1; //定义按键--增加键
sbit s3=P3^2; //定义按键--减小键
sbit s4=P3^6;//闹钟查看键
sbit rd=P3^7;
sbit beep=P2^3; //定义蜂鸣器端
uchar code Temp_Disp_Title[]={" Current Temp : "};
uchar Current_Temp_Display_Buffer[]={" TEMP: "};
uchar code Alarm_Temp[]={"ALARM TEMP Hi Lo"};
uchar Alarm_HI_LO_STR[]={"Hi: Lo: "};
uchar temp_data[2]={0x00,0x00};
uchar temp_alarm[2]={0x00,0x00};
uchar display[5]={0x00,0x00,0x00,0x00,0x00};
uchar display1[3]={0x00,0x00,0x00};
uchar code df_Table[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};
uchar CurrentT=0; //当前读取的温度整数部分
uchar Temp_Value[]={0x00,0x00}; //从DS18B20读取的温度值
uchar Display_Digit[]={0,0,0,0}; //待显示的各温度数位
bit DS18B20_IS_OK=1;//传感器正常标志
//-------------------------------------
//延时1
//-------------------------------------
void delay1(uint x)
{
uchar i;
while(x--) for(i=0;i<200;i++);
}
//-------------------------------------
//延时2
//-------------------------------------
void Delay(uint x)
{
while(x--);
}
//------------------------------------
//忙检查
//------------------------------------
void write_com(uchar com)//液晶写命令函数
{
rs=0;
lcden=0;
P0=com;
delay1(5);
lcden=1;
delay1(5);
lcden=0;
}
void Write_LCD_Data(uchar date)//液晶写数据函数
{
rs=1;
lcden=0;
P0=date;
delay1(5);
lcden=1;
delay1(5);
lcden=0;
}
//-----------------------------
//设置LCD显示位置
//---------------------------------
void Set_Disp_Pos(uchar Pos)
{
write_com(Pos|0x80);
}
//-----------------------------
//LCD初始化
//---------------------------------
void Initialize_LCD()
{
uchar num;
rd=0; //软件将矩阵按键第4列一端置低用以分解出独立按键
la=0;//关闭两锁存器锁存端,防止操作液晶时数码管会出乱码
wela=0;
lcden=0;
write_com(0x38);//初始化1602液晶
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);//设置显示初始坐标
for(num=0;num<14;num++)//显示年月日星期
{
Write_LCD_Data(Temp_Disp_Title[num]);
delay1(5);
}
}
//-------------------------------------
//函数功能:初始化DS18B20
//出口参数:status---DS18B20是否复位成功的标志
//-------------------------------------
uchar Init_DS18B20()
{
uchar status; //储存DS18B20是否存在的标志,status=0,表示存在;status=1,表示不存在
DQ=1;Delay(8); //先将数据线拉高 //略微延时约6微秒
DQ=0;Delay(90); //再将数据线从高拉低,要求保持480~960us
//略微延时约600微秒 以向DS18B20发出一持续480~960us的低电平复位脉冲
DQ=1;Delay(8); //释放数据线(将数据线拉高) //延时约30us(释放总线后需等待15~60us让DS18B20输出存在脉冲)
status=DQ;Delay(100); //让单片机检测是否输出了存在脉冲(DQ=0表示存在) //延时足够长时间,等待存在脉冲输出完毕
DQ=1; // 将数据线拉高
return status; //返回检测成功标志
}
//-------------------------------------
//函数功能:读一字节
//出口参数:dat---读出的数据
//-------------------------------------
uchar ReadOneByte()
{
uchar i,dat=0;
DQ=1;_nop_(); // 先将数据线拉高 //等待一个机器周期
for (i=0;i<8;i++)
{
DQ=0; //单片机从DS18B20读书据时,将数据线从高拉低即启动读时序
dat>>=1;
_nop_(); //等待一个机器周期
DQ=1; //将数据线"人为"拉高,为单片机检测DS18B20的输出电平作准备
_nop_();_nop_(); //延时约6us,使主机在15us内采样
if (DQ) dat|=0x80; //如果读到的数据是1,则将1存入dat,如果是0则保持原值不变
Delay(30); //延时3us,两个读时序之间必须有大于1us的恢复期
DQ=1; // 将数据线拉高,为读下一位数据做准备
}
return dat;
}
//-------------------------------------
//函数功能:写一字节
//入口参数:dat---待写入的数据
//-------------------------------------
void WriteOneByte(uchar dat)
{
uchar i;
for (i=0;i<8;i++)
{
DQ=0; //将数据线从高拉低时即启动写时序
DQ=dat & 0x01; //利用与运算取出要写的某位二进制数据,
//并将其送到数据线上等待DS18B20采样
Delay(5); //延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样
DQ=1; //释放数据线
dat>>=1; //将dat中的各二进制位数据右移1位
}
}
//-------------------------------------
//函数功能:读取温度值
//出入口参数:无
//-------------------------------------
void Read_Temperature()
{
if(Init_DS18B20() == 1) //DS18B20故障
DS18B20_IS_OK=0;
else
{
WriteOneByte(0xCC); // 跳过读序号列号的操作
WriteOneByte(0x44); // 启动温度转换
Init_DS18B20(); //将DS18B20初始化
WriteOneByte(0xCC); //跳过读序号列号的操作
WriteOneByte(0xBE); //读取温度寄存器,前两个分别是温度的低位和高位
Temp_Value[0]=ReadOneByte(); //温度低8位
Temp_Value[1]=ReadOneByte(); //温度高8位
DS18B20_IS_OK=1;
}
}
//-------------------------------------
//函数功能:在LCD上显示当前温度
//入口参数:
//-------------------------------------
void Display_Temperature()
{
uchar i;
//延时值与负数标识
uchar t=150,ng=0;
//高5位全为1(0xF8)则为负数,为负数时取反加1,并设置负数标示
if ((Temp_Value[1] & 0xF8)==0xF8)
{
Temp_Value[1]=~Temp_Value[1];
Temp_Value[0]=~Temp_Value[0]+1;
if(Temp_Value[0]==0x00) Temp_Value[1]++; //加1后如果低字节为00表示有进位,进位位再加到高字节上
ng=1; //负数标示置1
}
Display_Digit[0]=df_Table[Temp_Value[0] & 0x0F]; //查表得到温度小数部分
//获取温度整数部分(高字节的低3位与低字节中的高4位,无符号)
CurrentT=((Temp_Value[0] & 0xF0)>>4)|((Temp_Value[1] & 0x07)<<4);
//将整数部分分解为3位待显示数字
Display_Digit[3]=CurrentT/100; //百位 digit[CurrentT/100];
Display_Digit[2]=CurrentT%100/10; //十位
Display_Digit[1]=CurrentT%10; //个位
//刷新LCD显示缓冲
Current_Temp_Display_Buffer[11]=Display_Digit[0]+'0';//先将'0'转换成整数48,然后与前面数字相加,得到相应数字的ASCII字符
Current_Temp_Display_Buffer[10]='.';
Current_Temp_Display_Buffer[9]=Display_Digit[1]+'0'; //个位
Current_Temp_Display_Buffer[8]=Display_Digit[2]+'0'; //十位
Current_Temp_Display_Buffer[7]=Display_Digit[3]+'0'; //百位
//高位为0时不显示
if(Display_Digit[3]==0) Current_Temp_Display_Buffer[7]=' ';
//高位为0且次高位为0时,次高位不显示
if(Display_Digit[2]==0 && Display_Digit[3]==0)
Current_Temp_Display_Buffer[8]=' ';
//负数符号显示在恰当位置
if(ng)
{
if (Current_Temp_Display_Buffer[8]==' ')
Current_Temp_Display_Buffer[8]='-';
else if(Current_Temp_Display_Buffer[7]==' ')
Current_Temp_Display_Buffer[7]='-';
else
Current_Temp_Display_Buffer[6]='-';
}
//在第一行显示标题
Set_Disp_Pos(0x00);
for(i=0;i<16;i++)
{
Write_LCD_Data(Temp_Disp_Title[i]);
}
Set_Disp_Pos(0x40); //在第二行显示当前温度
for(i=0;i<16;i++)
{
Write_LCD_Data(Current_Temp_Display_Buffer[i]);
}
//显示温度符号
// Set_Disp_Pos(0x4D);Write_LCD_Data(0x00);
Set_Disp_Pos(0x4D);Write_LCD_Data(0xdf);
Set_Disp_Pos(0x4E); Write_LCD_Data('C');
}
//-------------------------------------
//函数功能:主函数
//入口参数:
//-------------------------------------
void main()
{
Initialize_LCD();
Read_Temperature();
Delay(50000);
Delay(50000);
while (1)
{
Read_Temperature();
if (DS18B20_IS_OK) Display_Temperature();
delay1(100);
}
}
② 基于单片机的数字温度计设计好做么
这种设计相对来说比较好做。
首先选择用什么洞此庆系列的单片机。目前常用的有51单片机,AVR单片机,MSP430单片机等等。
接下来选择用什么传感器。
采用有温敏电阻,通过对直流电压分压,测量其直流电压的变化,也就是AD检测,再纳握把电压值转换成温度值;(这种方式要求单片机具有AD检测功能,否则需要外接AD转换芯片。)
采用温度模块,例如常用的DS18B20,不需要AD检测,只需要进行I2C读写取扒仔得温度值;
最后确定如何显示检测到的数值。
常用的有:
1.数码管,可以显示段码数字或简单字符。
2.LCD1602液晶屏,可以显示两行16*2个英文字母和数字;
3.LCD12864液晶屏,可以显示四行8*4个汉字。也可以显示字母及数字,当然也可以显示自定义图形。
以上选择需要合理搭配。
接着就是绘制原理图和PCB图、采集元件、焊接,编写程序,调试。
③ 用单片机C语言设计数字温度计!求代码!急急急
//------------------------------------------------------------------
//DS18B20温度传感器输出显示,运行本例时,外界温度将显示在1602LCD上
//------------------------------------------------------------------
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP() {_nop_();_nop_();_nop_();_nop_();}
sbit DQ=P2^2;
sbit la=P2^6; //定义锁存器锁存端
sbit wela=P2^7;
sbit rs=P3^5; //定义1602液晶RS端
sbit lcden=P3^4;//定义1602液晶LCDEN端
sbit s1=P3^0; //定义按键--功能键
sbit s2=P3^1;//定义按键--增加键
sbit s3=P3^2;//定义按键--减小键
sbit s4=P3^6;//闹钟查看键
sbit rd=P3^7;
sbit beep=P2^3; //定义蜂鸣器端
uchar code Temp_Disp_Title[]={" Current Temp : "};
uchar Current_Temp_Display_Buffer[]={" TEMP: "};
uchar code Alarm_Temp[]={"ALARM TEMP Hi Lo"};
uchar Alarm_HI_LO_STR[]={"Hi: Lo: "};
uchar temp_data[2]={0x00,0x00};
uchar temp_alarm[2]={0x00,0x00};
uchar display[5]={0x00,0x00,0x00,0x00,0x00};
uchar display1[3]={0x00,0x00,0x00};
uchar code df_Table[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};
uchar CurrentT=0;//当前读取的温度整数部分
uchar Temp_Value[]={0x00,0x00};//从DS18B20读取的温度值
uchar Display_Digit[]={0,0,0,0}; //待显示的各温度数位
bit DS18B20_IS_OK=1;//传感器正常标志
//-------------------------------------
//延时1
//-------------------------------------
void delay1(uint x)
{
uchar i;
while(x--) for(i=0;i<200;i++);
}
//-------------------------------------
//延时2
//-------------------------------------
void Delay(uint x)
{
while(x--);
}
//------------------------------------
//忙检查
//------------------------------------
void write_com(uchar com)//液晶写命令函数
{
rs=0;
lcden=0;
P0=com;
delay1(5);
lcden=1;
delay1(5);
lcden=0;
}
void Write_LCD_Data(uchar date)//液晶写数据函数
{
rs=1;
lcden=0;
P0=date;
delay1(5);
lcden=1;
delay1(5);
lcden=0;
}
//-----------------------------
//设置LCD显示位置
//---------------------------------
void Set_Disp_Pos(uchar Pos)
{
write_com(Pos|0x80);
}
//-----------------------------
//LCD初始化
//---------------------------------
void Initialize_LCD()
{
uchar num;
rd=0; //软件将矩阵按键第4列一端置低用以分解出独立按键
la=0;//关闭两锁存器锁存端,防止操作液晶时数码管会出乱码
wela=0;
lcden=0;
write_com(0x38);//初始化1602液晶
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);//设置显示初始坐标
for(num=0;num<14;num++)//显示年月日星期
{
Write_LCD_Data(Temp_Disp_Title[num]);
delay1(5);
}
}
//-------------------------------------
//函数功能:初始化DS18B20
//出口参数:status---DS18B20是否复位成功的标志
//-------------------------------------
uchar Init_DS18B20()
{
uchar status; //储存DS18B20是否存在的标志,status=0,表示存在;status=1,表示不存在
DQ=1;Delay(8); //先将数据线拉高 //略微延时约6微秒
DQ=0;Delay(90); //再将数据线从高拉低,要求保持480~960us
//略微延时约600微秒 以向DS18B20发出一持续480~960us的低电平复位脉冲
DQ=1;Delay(8); //释放数据线(将数据线拉高) //延时约30us(释放总线后需等待15~60us让DS18B20输出存在脉冲)
status=DQ;Delay(100); //让单片机检测是否输出了存在脉冲(DQ=0表示存在) //延时足够长时间,等待存在脉冲输出完毕
DQ=1; // 将数据线拉高
return status; //返回检测成功标志
}
//-------------------------------------
//函数功能:读一字节
//出口参数:dat---读出的数据
//-------------------------------------
uchar ReadOneByte()
{
uchar i,dat=0;
DQ=1;_nop_(); // 先将数据线拉高 //等待一个机器周期
for (i=0;i<8;i++)
{
DQ=0; //单片机从DS18B20读书据时,将数据线从高拉低即启动读时序
dat>>=1;
_nop_();//等待一个机器周期
DQ=1; //将数据线"人为"拉高,为单片机检测DS18B20的输出电平作准备
_nop_();_nop_(); //延时约6us,使主机在15us内采样
if (DQ) dat|=0x80; //如果读到的数据是1,则将1存入dat,如果是0则保持原值不变
Delay(30); //延时3us,两个读时序之间必须有大于1us的恢复期
DQ=1; // 将数据线拉高,为读下一位数据做准备
}
return dat;
}
//-------------------------------------
//函数功能:写一字节
//入口参数:dat---待写入的数据
//-------------------------------------
void WriteOneByte(uchar dat)
{
uchar i;
for (i=0;i<8;i++)
{
DQ=0; //将数据线从高拉低时即启动写时序
DQ=dat & 0x01; //利用与运算取出要写的某位二进制数据,
//并将其送到数据线上等待DS18B20采样
Delay(5); //延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样
DQ=1; //释放数据线
dat>>=1; //将dat中的各二进制位数据右移1位
}
}
//-------------------------------------
//函数功能:读取温度值
//出入口参数:无
//-------------------------------------
void Read_Temperature()
{
if(Init_DS18B20() == 1) //DS18B20故障
DS18B20_IS_OK=0;
else
{
WriteOneByte(0xCC); // 跳过读序号列号的操作
WriteOneByte(0x44); // 启动温度转换
Init_DS18B20(); //将DS18B20初始化
WriteOneByte(0xCC); //跳过读序号列号的操作
WriteOneByte(0xBE); //读取温度寄存器,前两个分别是温度的低位和高位
Temp_Value[0]=ReadOneByte(); //温度低8位
Temp_Value[1]=ReadOneByte(); //温度高8位
DS18B20_IS_OK=1;
}
}
//-------------------------------------
//函数功能:在LCD上显示当前温度
//入口参数:
//-------------------------------------
void Display_Temperature()
{
uchar i;
//延时值与负数标识
uchar t=150,ng=0;
//高5位全为1(0xF8)则为负数,为负数时取反加1,并设置负数标示
if ((Temp_Value[1] & 0xF8)==0xF8)
{
Temp_Value[1]=~Temp_Value[1];
Temp_Value[0]=~Temp_Value[0]+1;
if(Temp_Value[0]==0x00) Temp_Value[1]++; //加1后如果低字节为00表示有进位,进位位再加到高字节上
ng=1; //负数标示置1
}
Display_Digit[0]=df_Table[Temp_Value[0] & 0x0F]; //查表得到温度小数部分
//获取温度整数部分(高字节的低3位与低字节中的高4位,无符号)
CurrentT=((Temp_Value[0] & 0xF0)>>4)|((Temp_Value[1] & 0x07)<<4);
//将整数部分分解为3位待显示数字
Display_Digit[3]=CurrentT/100;//百位 digit[CurrentT/100];
Display_Digit[2]=CurrentT%100/10;//十位
Display_Digit[1]=CurrentT%10;//个位
//刷新LCD显示缓冲
Current_Temp_Display_Buffer[11]=Display_Digit[0]+'0';//先将'0'转换成整数48,然后与前面数字相加,得到相应数字的ASCII字符
Current_Temp_Display_Buffer[10]='.';
Current_Temp_Display_Buffer[9]=Display_Digit[1]+'0'; //个位
Current_Temp_Display_Buffer[8]=Display_Digit[2]+'0'; //十位
Current_Temp_Display_Buffer[7]=Display_Digit[3]+'0'; //百位
//高位为0时不显示
if(Display_Digit[3]==0) Current_Temp_Display_Buffer[7]=' ';
//高位为0且次高位为0时,次高位不显示
if(Display_Digit[2]==0 && Display_Digit[3]==0)
Current_Temp_Display_Buffer[8]=' ';
//负数符号显示在恰当位置
if(ng)
{
if (Current_Temp_Display_Buffer[8]==' ')
Current_Temp_Display_Buffer[8]='-';
else if(Current_Temp_Display_Buffer[7]==' ')
Current_Temp_Display_Buffer[7]='-';
else
Current_Temp_Display_Buffer[6]='-';
}
//在第一行显示标题
Set_Disp_Pos(0x00);
for(i=0;i<16;i++)
{
Write_LCD_Data(Temp_Disp_Title[i]);
}
Set_Disp_Pos(0x40); //在第二行显示当前温度
for(i=0;i<16;i++)
{
Write_LCD_Data(Current_Temp_Display_Buffer[i]);
}
//显示温度符号
//Set_Disp_Pos(0x4D);Write_LCD_Data(0x00);
Set_Disp_Pos(0x4D);Write_LCD_Data(0xdf);
Set_Disp_Pos(0x4E);Write_LCD_Data('C');
}
//-------------------------------------
//函数功能:主函数
//入口参数:
//-------------------------------------
void main()
{
Initialize_LCD();
Read_Temperature();
Delay(50000);
Delay(50000);
while (1)
{
Read_Temperature();
if (DS18B20_IS_OK) Display_Temperature();
delay1(100);
}
}
④ 单片机数字温度计设计用C语言写程序
#include<reg51.h>
#defineucharunsignedchar
sbitBEEP=P3^7; //接控制继电器
sbitDQ=P3^6; //接温度传感器18B20
uchart[2],number=0,*pt; //温度值
ucharTempBuffer1[4]={0,0,0,0};
ucharTmax=50,Tmin=10;
uchardistab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0xfe,0xf7};
ucharcurrtemp;
voidt0isr()interrupt1
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
P2=1<<number;
if(number==2)P0=distab[TempBuffer1[0]]&0x7f;
elseP0=distab[TempBuffer1[0]];
number++;
if(number>3)number=0;
}
voiddelay_18B20(unsignedinti)
{
while(i--);
}
/**********ds18b20初始化函数**********************/
voidInit_DS18B20(void)
{
bitx=0;
do{
DQ=1;
delay_18B20(8);
DQ=0;//单片机将DQ拉低
delay_18B20(90);//精确延时大于480us
DQ=1;//拉高总线
delay_18B20(14);
x=DQ;//稍做延时后如果x=0则初始化成功x=1则初始化失败,继续初始化
}while(x);
delay_18B20(20);
}
/***********ds18b20读一个字节**************/
unsignedcharReadOneChar(void)
{
unsignedchari=0;
unsignedchardat=0;
for(i=8;i>0;i--)
{
DQ=0;//给脉冲信号
dat>>=1;
DQ=1;//给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(4);
}
return(dat);
}
/*************ds18b20写一个字节****************/
voidWriteOneChar(unsignedchardat)
{
unsignedchari=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
delay_18B20(5);
DQ=1;
dat>>=1;
}
}
/**************读取ds18b20当前温度************/
unsignedchar*ReadTemperature(unsignedcharrs)
{
unsignedchartt[2];
delay_18B20(80);
Init_DS18B20();
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0x44); //启动温度转换
delay_18B20(80);
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个就是温度
tt[0]=ReadOneChar();//读取温度值低位
tt[1]=ReadOneChar();//读取温度值高位
return(tt);
}
voidcovert1(void) //将温度转换为LED显示的数据
{
ucharx=0x00,y=0x00;
t[0]=*pt;
pt++;
t[1]=*pt;
if(t[1]&0x080)//判断正负温度
{
TempBuffer1[0]=0x0c; //c代表负
t[1]=~t[1]; /*下面几句把负数的补码*/
t[0]=~t[0]; /*换算成绝对值*********/
x=t[0]+1;
t[0]=x;
if(x==0x00)t[1]++;
}
elseTempBuffer1[0]=0x0a; //A代表正
t[1]<<=4; //将高字节左移4位
t[1]=t[1]&0xf0;
x=t[0]; //将t[0]暂存到X,因为取小数部分还要用到它
x>>=4; //右移4位
x=x&0x0f; //和前面两句就是取出t[0]的高四位
y=t[1]|x; //将高低字节的有效值的整数部分拼成一个字节
TempBuffer1[1]=(y%100)/10;
TempBuffer1[2]=(y%100)%10;
t[0]=t[0]&0x0f; //小数部分
TempBuffer1[3]=t[0]*10/16;
if(currtemp<Tmin||currtemp>Tmax)BEEP=1;
elseBEEP=0;
}
voidconvert(chartmp)
{
uchara;
if(tmp<0)
{
TempBuffer1[0]=0x0c;
a=~tmp+1;
}
else
{
TempBuffer1[0]=0x0a;
a=tmp;
}
TempBuffer1[1]=(a%100)/10;
TempBuffer1[2]=(a%100)%10;
}
main()
{
TMOD=0x01;
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
TR0=1;
ET0=1;
EA=1;
out=1;
flag=0;
ReadTemperature(0x3f);
delay_18B20(50000); //延时等待18B20数据稳定
while(1)
{
pt=ReadTemperature(0x7f);//读取温度,温度值存放在一个两个字节的数组中
if(dismod==0)covert1();
delay_18B20(30000);
}
}