温馨提示:读者若要彻底理解并会灵活使用DS18B20温度传感器,请详细阅读中文手册,并且对照代码注释充分分析代码。请不要觉得中文手册内容繁多!如能静心分析,定能深有体会,获益匪浅!
一、DS18B20中文手册(节选)
主函数操作顺序(执行序列)
功能指令
数码管温度计详解代码如下:
#include <reg52.h>
#include <intrins.h>
#define MAIN_Fosc 11059200UL //宏定义主时钟HZ
/*====================================
自定义类型名
====================================*/
typedef unsigned char INT8U;
typedef unsigned char uchar;
typedef unsigned int INT16U;
typedef unsigned int uint;
/*====================================
硬件接口位声明
====================================*/
sbit DS = P2^2; //DS18B20单总线
sbit DU = P2^6; //数码管段选
sbit WE = P2^7; //数码管位选
/*====================================
共阴极数码管段选码
====================================*/
uchar code table[]={
//0 1 2 3 4 5 6 7 8
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F,
//9 A B C D E F - . 关显示
0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x40, 0x80, 0x00
};
/*====================================
数码管位选码
====================================*/
//第1位 2位 3位 4位 5位 6位 7位 8位
uchar code T_COM[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};//数码管位码
/*====================================
函数:void Delay_Ms(INT16U ms)
参数:ms,毫秒延时形参
描述:12T 51单片机自适应主时钟毫秒级延时函数
====================================*/
void Delay_Ms(INT16U ms)
{
INT16U i;
do{
i = MAIN_Fosc / 96000;
while(--i); //96T per loop
}while(--ms);
}
/*us延时函数,执行一次US--所需6.5us进入一次函数需要11.95us*/
void Delay_us(uchar us)
{
while(us--);
}
/*====================================
函数:void Display(INT16U Value)
参数:Value,显示值 取值0-65535
描述:共阴极数码管显示函数可显示一个字节的数
====================================*/
void Display(INT16U Value) //注意由于需要显示的数大于一个字节所有形参需为int型
{
//------------------------------
DU = 0; //关闭段选
P0 = table[Value/100]; //数码管显示百位
DU = 1; //打开段选
DU = 0; //关闭段选
WE = 0; //关闭位选
P0 = T_COM[0]; //第一位数码管
WE = 1; //打开位选
WE = 0; //关闭位选
Delay_Ms(3);
//-------------------------------
DU = 0;
P0 = table[Value%100/10]|0x80; //显示十位
DU = 1;
DU = 0;
WE = 0;
P0 = T_COM[1]; //第二位数码管
WE = 1;
WE = 0;
Delay_Ms(3);
//-------------------------------
DU = 0;
P0 = table[Value%10]; //显示个位
DU = 1;
DU = 0;
WE = 0;
P0 = T_COM[2]; //第三位数码管
WE = 1;
WE = 0;
Delay_Ms(3);
}
/*单总线初始化时序*/
/*出始化时序里包含了复位DS18B20和接收DS18B20返回的存在信号*/
bit ds_init()
{
bit i;
DS = 1;
_nop_();
DS = 0;
Delay_us(75); //拉低总线499.45us 挂接在总线上的18B20将会全部被复位
DS = 1; //释放总线(检测到上升沿)
Delay_us(4); //延时37.95us 等待18B20发回存在信号(存在脉冲)
i = DS;
Delay_us(20); //141.95us
DS = 1;
_nop_();
return (i); //返回一个存在信号
}
/*写一个字节*/
void write_byte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DS = 0;
_nop_();//产生些时序
DS = dat & 0x01; //0000 0001
Delay_us(10);//76.95us
DS = 1; //释放总线准备下一次数据写入
_nop_();
dat >>= 1;
}
}
uchar read_byte()
{
uchar i, j, dat;
for(i=0;i<8;i++)
{
DS = 0;
_nop_();//产生读时序 1us,延时一个指令周期,空指令
DS = 1; //释放总线
_nop_(); //延时时间可以通过单步调试来计算
j = DS;
Delay_us(10);//76.95us
DS = 1;
_nop_();
dat = (j<<7)|(dat>>1);
}
return (dat);
}
void main()
{
uint i;
uchar L, M;
while(1)
{
ds_init();//初始化DS18B20
write_byte(0xcc);//发送跳跃ROM指令
write_byte(0x44);//发送温度转换指令
ds_init();//初始化DS18B20
write_byte(0xcc);//发送跳跃ROM指令(注意:当只有一只从机在总线上时,无论如何,
//忽略ROM指令之后只能跟着发出一条暂存器指令【BEh】)
write_byte(0xbe);//读取DS18B20暂存器值,读取将从字节0开始,一直进行下去,直到第9字节(字节8,CRC)读完
L = read_byte();//总线控制器在发出温度转换指令之后进行读时序
M = read_byte();//总线控制器在发出温度转换指令之后进行读时序
i = M; //高速暂存器(共8位),详见中文手册
i <<= 8; //将最低位移至高位
i |= L;
i = i * 0.0625 * 10 + 0.5;
Display(i);
}
}
LCD1602温度显示
#include <reg52.H>
#include <intrins.H>
#include <math.H>
#define uchar unsigned char
#define uint unsigned int
sbit dula = P2^6;//数码管段选
sbit wela = P2^7;//数码管位选
sbit rw = P3^6; //LCD1602读/写选择端
sbit RS = P3^5;//LCD1602数据/命令选择端
sbit LCDEN = P3^4; //LCD1602使能端
void delayUs()
{
_nop_(); //空指令,延时一个指令周期
}
void delayMs(uint a)
{
uint i, j;
for(i = a; i > 0; i--)
for(j = 100; j > 0; j--);
}
void writeComm(uchar comm) //写指令
{
RS = 0;
P0 = comm;
LCDEN = 1;
delayUs();
LCDEN = 0;
delayMs(1);
}
//写数据:RS=1, RW=0;
void writeData(uchar dat)
{
RS = 1;
P0 = dat;
LCDEN = 1;
delayUs();
LCDEN = 0;
delayMs(1);
}
void init() //LCD1602初始化函数
{
rw = 0; //LCD1602读/写选择端
dula = wela = 0;
writeComm(0x38);//LCD1602显示设置
writeComm(0x0c);//开显示
writeComm(0x06);//当读或写一个字符后地址指针加一,且光标加一
writeComm(0x01);//清屏指令
}
void writeString(uchar * str, uchar length)//LCD1602写字符串
{
uchar i;
for(i = 0; i < length; i++)
{
writeData(str[i]);
}
}
/**//*****************************DS18B20*******************************/
/*温馨提示:读者若要彻底理解并会灵活使用DS18B20温度传感器,请详细阅读
中文手册,并且对照代码注释充分分析代码。如能静心分析,定能深有体会,获
益匪浅!*/
sbit ds = P2^2;
void dsInit()//初始化,详见中文手册
{
unsigned int i;
ds = 0;
i = 100;
while(i>0) i--; //用于延时(严格按照时序来写)
ds = 1;
i = 4;
while(i>0) i--;
}
void dsWait()//等待信号
{
unsigned int i;
while(ds);
while(~ds);
i = 4;
while(i > 0) i--;
}
bit readBit()//读一个bit位,一节数据共8个bit位,故后面会连续读到8次来实现读一个字节的数据
{
unsigned int i;
bit b;
ds = 0;
i++;
ds = 1;
i++; i++;
b = ds;
i = 8;
while(i>0) i--;
return b;//返回数据
}
unsigned char readByte() //读一个字节的数据
{
unsigned int i;
unsigned char j, dat;
dat = 0;
for(i=0; i<8; i++)//每一次读一位,一节数据共8位,读8次
{
j = readBit();
dat = (j << 7) | (dat >> 1);
}
return dat;
}
void writeByte(unsigned char dat)//写一节数据
{
unsigned int i;
unsigned char j;
bit b;
for(j = 0; j < 8; j++)//每次写一位,写8次
{
b = dat & 0x01;//取最低位,从最低位泄气
dat >>= 1; //右移一位
if(b)
{
ds = 0;
i++; i++;//延时以产生时序
ds = 1;
i = 8;
while(i>0) i--; //延时以产生时序
}
else
{
ds = 0;
i = 8;
while(i>0) i--;//延时以产生时序
ds = 1;
i++; i++;//延时以产生时序
}
}
}
void sendChangeCmd()//发送指令
{
dsInit();
dsWait();
delayMs(1);
writeByte(0xcc);//发送跳跃ROM指令(注意:当只有一只从机在总线上时,无论如何,
//忽略ROM指令之后只能跟着发出一条暂存器指令【BEh】)
writeByte(0x44);//发送温度转换指令
}
void sendReadCmd()//读操作
{
dsInit();
dsWait();
delayMs(1);
writeByte(0xcc);//发送跳跃ROM指令
writeByte(0xbe);//发送温度转换指令
}
int getTmpValue() //获取温度值
{
unsigned int tmpvalue;
int value;
float t;
unsigned char low, high;
sendReadCmd();
low = readByte();
high = readByte();
tmpvalue = high;
tmpvalue <<= 8;
tmpvalue |= low;
value = tmpvalue;
t = value * 0.0625;
value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5
return value;
}
void display(int v) //LCD1602显示内容设置
{
unsigned char count;
unsigned char datas[] = {0, 0, 0, 0, 0};
unsigned int tmp = abs(v);
datas[0] = tmp / 10000;
datas[1] = tmp % 10000 / 1000;
datas[2] = tmp % 1000 / 100;
datas[3] = tmp % 100 / 10;
datas[4] = tmp % 10;
writeComm(0xc0+3);
if(v < 0)
{
writeString("- ", 2);
}
else
{
writeString("+ ", 2);
}
if(datas[0] != 0)
{
writeData('0'+datas[0]);
}
for(count = 1; count != 5; count++)
{
writeData('0'+datas[count]);
if(count == 2)
{
writeData('.');
}
}
}
/**//*****************************DS18B20*******************************/
void main()
{
uchar table[] = " xianzaiwendu: ";
sendChangeCmd();
init();
writeComm(0x80);
writeString(table, 16);//发送" xianzaiwendu: "
while(1)
{
delayMs(1000); //温度转换时间需要750ms以上
writeComm(0xc0);
display(getTmpValue());//通过LCD1602显示温度转换值
sendChangeCmd();//发送转换指令
}
}
最后希望我的分享对你有所帮助!敬请关注,持续更新!
考虑到一些读者需要相关资料和解决一些疑问,因此我新建立了一个学习交流群,我在群文件里上传了一些资料,需要的读者可以入群下载。
群中文件资料我会时常更新,主要资料是51单片机开发、32单片机开发、编程、嵌入式学习、算法控制等。
由于群中文件还在不断更新上传,有些方面的资料还不太完善,希望大家理解。若群中涉及违规行为,欢迎举报!
文章来源:https://www.toymoban.com/news/detail-520687.html
文章来源地址https://www.toymoban.com/news/detail-520687.html
到了这里,关于51单片机DS18B20温度传感器使用及数码管温度计、LCD1602温度显示代码详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!