📄 ds18b20_drive.c
字号:
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar tplsb, tpmsb;//温度值低位、高位字节
sbit DQ = P0^7;
//延时t毫秒
void delay(uint t)
{
uint i;
for(;t>0;t--)
//对于11.0592MHz时钟,延时约1ms
for(i=125;i>0;i--);
}
//产生复位脉冲初始化DS18B20
void txReset()
{
uint i;
DQ = 0;
//DQ拉低约900us
i = 100;
while(i>0) i--;
//产生上升沿
DQ = 1;
i = 4;
while(i>0) i--;
}
//等待应答脉冲
void rxWait()
{
uint i;
while(DQ);
while(~DQ);//检查到应答脉冲
i = 4;
while(i>0) i--;
}
//读取数据的一位,满足读时隙要求
bit readBit()
{
uint i;
bit b;
DQ = 0;
i++;//保持低至少1us
DQ = 1;
i++; i++;//延时15us以上,读时隙下降沿后15us,DS18B20输出数据才有效
b = DQ;
i = 8;
while(i>0) i--;//读时隙不低于60us
return(b);
}
//读取数据的一个字节
uchar readByte()
{
uchar i, j, b;
b = 0;
for(i=0;i<8;i++)
{
j = readBit();
b = (j<<7)|(b>>1);
}
return(b);
}
//写数据的一个字节,满足写1和写0的时隙要求
void writeByte(uchar b)
{
uint i;
uchar j;
bit btemp;
for(j=0;j<8;j++)
{
btemp = b&0x01;
b >>= 1;//取下一位,由低位向高位
if(btemp)
{
//写1
DQ = 0;
i++; i++;//延时,使得15us以内拉高
DQ = 1;
i = 8;
while(i>0) i--;//整个写1时隙不低于60us
}
else
{
//写0
DQ = 0;
i = 8;
while(i>0) i--;//保持低电平在60us到120us之间
DQ = 1;
i++;
i++;
}
}
}
//启动温度转换
void convert()
{
txReset();//产生复位脉冲,初始化DS18B20
rxWait();//等待DS18B20给出应答脉冲
delay(1);//延时1ms
writeByte(0xcc);//skip rom命令
writeByte(0x44);//convert T 命令
}
//读取温度值
void readTemp()
{
txReset();//产生复位脉冲,初始化DS18B20
rxWait();//等待DS18B20给出应答脉冲
delay(1);//延时1ms
writeByte(0xcc);//skip rom命令
writeByte(0xbe);//read scratchpad命令
tplsb = readByte();//温度值低位字节(其中低4位为二进制的“小数”部分)
tpmsb = readByte();//温度值高位字节(其中高5位为符号位)
}
//开始测试
//温度值显示在LCD上,显示格式如下:
//LCD字符位置:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
//LCD的第一行:R e a l t i m e T e m p :
//LCD的第二行: + x x x. x x x x 。 C
sbit LCDRS = P3^3;
sbit LCDRW = P3^4;
sbit LCDEN = P3^5;
uchar code NumTable[] = "0123456789";
uchar code HeadLine[] = "Real time Temp:";//15个字符
uchar code SecoLine[] = " + xxx.xxxx。C";//14个字符
void write_com(uchar com) //写命令
{
LCDRS = 0;
LCDRW = 0;
LCDEN = 0;
P1 = com;
LCDEN = 1;
delay(5);
LCDEN = 0;
}
void write_data(uchar dat) //写数据
{
LCDRS = 1;
LCDRW = 0;
LCDEN = 0;
P1 = dat;
LCDEN = 1;
delay(5);
LCDEN = 0;
}
void init()
{
uchar i;
//初始化LCD
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
//在LCD上显示第一行:“Real time Temp:”//15个字符
for(i=0;i<15;i++)
{
write_data(HeadLine[i]);
}
//在LCD上显示第二行:“ + xxx.xxxx。C”//14个字符
write_com(0x80+0x40);//换行
for(i=0;i<12;i++)
{
write_data(SecoLine[i]);
}
write_com(0x80+0x40+0x0d);
write_data(0xdf);//显示“。”
write_data(0x43);//显示“C”
}
void main()
{
uint tempMsb, tempLsb, temp;
uchar bai, shi, ge;//温度整数部分的数据
uchar xiao1, xiao2, xiao3, xiao4;//温度小数部分的数据
bit unit;//温度的正负情况
init();
while(1)
{
delay(1);//延时1ms
convert();//启动温度转换,需要750ms
delay(1000);//延时1s
readTemp();//读取温度
//将当前温度的整数部分及符号位存入tpmsb,小数部分存入tplsb
tpmsb <<= 4; //将其高四位符号位移出
temp = tplsb;
temp >>= 4; //将小数部分移出
temp &= 0x0f; //将高四位清0
tpmsb |= temp; //当前温度的整数部分
//温度的整数部分
//当温度变化时数据逐位提出
if(tempMsb!=tpmsb)//整数部分有变化,刷新LCD的整数部分
{
tempMsb = tpmsb;
temp = tpmsb;
temp <<= 1;
unit = CY;//温度的正负情况
temp = tpmsb;
temp &= 0x7f;//将温度的符号位屏蔽
bai = temp/100; //提出温度的百位数字
temp = temp%100;//减掉温度的百位
shi = temp/10; //提出温度的十位数字
ge = temp%10; //提出温度的个位数字
//显示当前温度
//百位如果为0,则百位不显示;
//百位和十位均为0,则只显示各位
//显示当前温度的正负情况
write_com(0x80+0x40+0x03);
if(unit)
{
write_data(0x2d);//显示负号
}
else
{
write_data(0x2b);//显示正号
}
//显示当前温度的百位,如果为0则不显示
write_com(0x80+0x40+0x05);
if(bai)
{
write_data(NumTable[bai]);//显示百位数字
}
else
{
write_data(0x20);//显示空格
}
//显示当前温度的十位,如果百位和十位均为0,则不显示
if(bai|shi)
{
write_data(NumTable[shi]);//显示十位数字
}
else
{
write_data(0x20);//显示空格
}
//显示当前温度的个位
write_data(NumTable[ge]);
}
//温度小数部分的处理
tplsb &= 0x0f; //将tplsb的温度整数部分屏蔽,仅保留小数部分
if(tempLsb!=tplsb)//小数部分有变化,刷新LCD的小数部分
{
tempLsb = tplsb;
//小数部分数值转换
temp = tplsb;
temp *= 625;
//分析出小数部分各位数字
xiao1 = temp/1000;//提出小数部分的第一位数字
temp = temp%1000;//去除小数部分的第一位
xiao2 = temp/100;//提出小数部分的第二位数字
temp = temp%100;//去除小数部分的第二位
xiao3 = temp/10;//提出小数部分的第三位数字
xiao4 = temp%10;//提出小数部分的第四位数字
//显示小数部分
write_com(0x80+0x49);//指针指向小数的第一位
write_data(NumTable[xiao1]);//刷新小数部分的第一位数字
write_data(NumTable[xiao2]);//刷新小数部分的第一位数字
write_data(NumTable[xiao3]);//刷新小数部分的第一位数字
write_data(NumTable[xiao4]);//刷新小数部分的第一位数字
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -