📄 thermometer.c
字号:
/****************************************************/
/*
*文件名:Thermomete.c
*功能描述:单片机系统复位后在液晶上显示当前温度值,测量温度范围为 -55°C~+125,可显示负温度值
*/
/****************************************************/
/*
DS18B20为"一线总线"数字温度传感器,测量温度范围为 -55°C~+125°C,分辨率为12,相当于温度分辨率为0.0625摄氏
在对DS18B20进行读写编程时,必须严格的保证读写时序,否则将无法读取测温结果.
*/
#include "Thermomete.h"
sbit DQ=P1^1;//定义数据通信端口
bit Negative=0;//温度负值标志位
void delay_us(unsigned int x);//延时1us函数
void delay(unsigned int t);//延时函数
void lcd_code(unsigned char lcdcode);//向液晶写一个命令的函数
void lcd_data(unsigned char lcddata);//向液晶写一个数据的函数
void init_lcd(void);//初始化液晶屏函数
void delay_ms(unsigned int x);//延时1ms函数
void display_char(unsigned char *displaychar);//显示字符串函数
void display_tem(float f);//显示温度值函数
void Reset(void);//DS18B20复位函数
void Built(void);//自制摄氏温度符号函数
unsigned char read_data(void);//读一个字节数据函数
void write_data(unsigned char value);//写一个字节数据函数
float Read_Temperature(void);//读取温度并转换函数
void main(void)
{
float temp;
EA=0;
init_lcd();
Built();
lcd_code(0x80);
display_char("Currently Temer:");
while(1)
{
temp=Read_Temperature();//温度转换
display_tem(temp);//显示当前温度
}
}
/***************延时1us函数*************/
void delay_us(unsigned int x)
{
while(x--);
}//x<255时,精确延时为(6*x)us
/***************延时1ms函数*************/
void delay_ms(unsigned int x)
{
unsigned char i;
while(x--)
{
for(i=0;i<125;i++);
}
}
/****************DS18B20复位函数******************/
void Reset(void)
{
unsigned char ch=0;
DQ = 1;//DQ复位
delay_us(8);//延时
DQ = 0;//DQ拉低
delay_us(80); //精确延时大于480us
DQ = 1;
//控制器应该将数据单总线拉高,以便于在15~60uS后接收存在脉冲
delay_us(14);//延时,存在脉冲为一个60~240uS的低电平信号
ch=DQ;//接收存在脉冲
delay(20);
}
/****************读一个字节数据函数******************/
unsigned char read_data(void)
{
unsigned char i;
unsigned char value = 0;
for (i=0;i<8;i++)
{
DQ = 0; //给脉冲信号
value=value>>1;//产生至少1uS的低电平,表示读时间的起始
DQ = 1; //给脉冲信号,在总线被释放后的15uS中DS18B20会发送内部数据位
if(DQ)
{
value=value|0x80;
}
delay_us(4);
}
return(value);
}
/****************写一个字节数据函数******************/
void write_data(unsigned char value)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ=0;
//写数据时间隙的前15uS总线需要是被控制器拉置低电平
DQ=value&0x01;
delay_us(5);//芯片对总线数据的采样时间,采样时间在15~60uS
DQ=1;
value=value>>1;
}//字节的读写是从低位开始的
delay(4);
}
/****************读取温度并转换函数******************/
//DS18b20一线工作协议流程为:
//复位 发送ROM指令 发送存储器指令 数据通信
float Read_Temperature(void)
{
unsigned char first_byte,second_byte,num=0;
float Temperature_value;
unsigned int buf;
Reset();//复位
write_data(0xcc);//跳跃ROM指令,跳过读序列号
write_data(0x44);//启动温度转换
delay_ms(750);//延时大于转换时间
Reset();//复位
write_data(0xcc);//跳跃ROM指令,跳过读序列号
write_data(0xbe);//从RAM中读数据,前两个字节为温度值
first_byte=read_data();//读取温度值低八位
second_byte=read_data();//读取温度值高八位
//Reset();//复位中止读数
num=second_byte&0x80;//判断温度值的正负
buf=second_byte;
buf=buf<<8;//温度值高八位存放在整型变量buf高八位
buf=buf|first_byte;//相或运算将温度值低八位存放在整型变量buf低八位
if(num!=0)
{
buf=(~buf)+1;
Negative=1;
}//温度值为负数,取反后加一
Temperature_value=buf*0.0625;//分辨率为12位,LSB=0.0625
return(Temperature_value);
}
/*********************延时函数********************/
void delay(unsigned int t)
{
unsigned int i;
for(i=0;i<=t;i++);
}
/************向液晶写一个命令的函数***************/
void lcd_code(unsigned char lcdcode)
{
delay(3);
A_LCDCOM=lcdcode;
delay(200);
}
/**************向液晶写一个数据的函数*************/
void lcd_data(unsigned char lcddata)
{
delay(3);
A_LCDDATA=lcddata;
delay(200);
}
/******************初始化液晶屏函数**************/
void init_lcd(void)
{
delay(1000);
lcd_code(0x38);//功能设定,5*7点阵,8位数据接口
delay(1000);
lcd_code(0x0c);//显示画面设置,开显示
delay(1000);
lcd_code(0x01);//清屏指令
delay(1000);
lcd_code(0x06);//当读或写一个字符后地址指针加1,且光标加1
delay(1000);
}
/***************显示字符串的函数*******************/
void display_char(unsigned char *displaychar)
{
while(*displaychar>0)
{
lcd_data(*displaychar);
displaychar++;
}
}
/***************显示温度值的函数*******************/
void display_tem(float f)
{
unsigned int num0,num1;
num0=f;//小数部分舍去,留下整数部分
f=f-num0;//减去整数部分得到小数部分
num1=f*10000;
lcd_code(0xc3);
if(Negative==1)
{
Negative=0;
lcd_data('-');
}//若温度为负,则先显示负号
lcd_data((num0/100)%10+0x30);
delay(30);
lcd_data((num0/10)%10+0x30);
delay(30);
lcd_data((num0%10)+0x30);
delay(30);
lcd_data('.');
delay(30);
lcd_data((num1/1000)%10+0x30);
delay(30);
lcd_data((num1/100)%10+0x30);
delay(30);
lcd_data((num1/10)%10+0x30);
delay(30);
lcd_data((num1%10)+0x30);
delay(30);//将温度值转换成各位显示
lcd_data(0x00);//显示摄氏温度符号
delay(30);
}
/***************自制摄氏温度符号函数*******************/
void Built(void)
{
lcd_code(0x40);//设置CGRAM地址,自定义字符字模就可以写入CGRAM中
lcd_data(0x08);//自定义字符°C,字符码为00
lcd_data(0x14);
lcd_data(0x0b);
lcd_data(0x04);
lcd_data(0x04);
lcd_data(0x04);
lcd_data(0x03);
lcd_data(0x00);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -