51单片机DS18B20温度计C语言程序(附详解)

来源:本站
导读:目前正在解读《51单片机DS18B20温度计C语言程序(附详解)》的相关信息,《51单片机DS18B20温度计C语言程序(附详解)》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《51单片机DS18B20温度计C语言程序(附详解)》的详细说明。

#include<reg51.h>

#include<intrins.h>

#include <math.H> //要用到取绝对值函数abs()

//通过DS18B20测试当前环境温度, 并通过数码管显示当前温度值, 目前显示范围: -55~ +125度

sbit wela = P2^7; //数码管位选

sbit dula = P2^6; //数码管段选

sbit ds = P2^2;

int tempValue;

//0-F数码管的编码(共阳极)

unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,

0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};

//0-9数码管的编码(共阳极), 带小数点

unsigned char code tableWidthDot[]={0x40, 0x79, 0x24, 0x30,

0x19, 0x12, 0x02,0x78, 0x00, 0x10};

//延时函数, 对于11.0592MHz时钟, 例i=10,则大概延时10ms.

void delay(unsigned int i)

{

unsigned int j;

while(i--)

{

for(j = 0; j < 125; j++);

}

}

//初始化DS18B20

//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动

void dsInit()

{

//对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于?us

unsigned int i;

ds = 0;

i = 100; //拉低约800us, 符合协议要求的480us以上

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--;

}

//向DS18B20读取一位数据

//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,

//之后DS18B20则会输出持续一段时间的一位数据

bit readBit()

{

unsigned int i;

bit b;

ds = 0;

i++; //延时约8us, 符合协议要求至少保持1us

ds = 1;

i++; i++; //延时约16us, 符合协议要求的至少延时15us以上

b = ds;

i = 8;

while(i>0) i--; //延时约64us, 符合读时隙不低于60us要求

return b;

}

//读取一字节数据, 通过调用readBit()来实现

unsigned char readByte()

{

unsigned int i;

unsigned char j, dat;

dat = 0;

for(i=0; i<8; i++)

{

j = readBit();

//最先读出的是最低位数据

dat = (j << 7) | (dat >> 1);

}

return dat;

}

//向DS18B20写入一字节数据

void writeByte(unsigned char dat)

{

unsigned int i;

unsigned char j;

bit b;

for(j = 0; j < 8; j++)

{

b = dat & 0x01;

dat >>= 1;

//写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1

if(b)

{

ds = 0;

i++; i++; //拉低约16us, 符号要求15~60us内

ds = 1;

i = 8; while(i>0) i--; //延时约64us, 符合写时隙不低于60us要求

}

else //写"0", 将DQ拉低60us~120us

ds = 0;

i = 8; while(i>0) i--; //拉低约64us, 符号要求

ds = 1;

i++; i++; //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us了

}

}

//向DS18B20发送温度转换命令

void sendChangeCmd()

{

dsInit(); //初始化DS18B20, 无论什么命令, 首先都要发起初始化

dsWait(); //等待DS18B20应答

delay(1); //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号

writeByte(0xcc); //写入跳过序列号命令字 Skip Rom

writeByte(0x44); //写入温度转换命令字 Convert T

}

//向DS18B20发送读取数据命令

void sendReadCmd()

{

dsInit();

dsWait();

delay(1);

writeByte(0xcc); //写入跳过序列号命令字 Skip Rom

writeByte(0xbe); //写入读取数据令字 Read Scratchpad

}

//获取当前温度值

int getTmpValue()

{

unsigned int tmpvalue;

int value; //存放温度数值

float t;

unsigned char low, high;

sendReadCmd();

//连续读取两个字节数据

low = readByte();

high = readByte();

//将高低两个字节合成一个整形变量

//计算机中对于负数是利用补码来表示的

//若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的

value

tmpvalue = high;

tmpvalue <<= 8;

tmpvalue |= low;

value = tmpvalue;

//使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度

t = value * 0.0625;

//将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入

//如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度

//如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度

value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5

return value;

}

unsigned char const timeCount = 3; //动态扫描的时间间隔

//显示当前温度值, 精确到小数点后一位

//若先位选再段选, 由于IO口默认输出高电平, 所以当先位选会使数码管出现乱码

void display(int v)

{

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;

if(v < 0)

{

//关位选, 去除对上一位的影响

P0 = 0xff;

wela = 1; //打开锁存, 给它一个下降沿量

wela = 0;

//段选

P0 = 0x40; //显示"-"号

dula = 1; //打开锁存, 给它一个下降沿量

dula = 0;

//位选

P0 = 0xfe;

wela = 1; //打开锁存, 给它一个下降沿量

wela = 0;

delay(timeCount);

}

for(count = 0; count != 5; count++)

{

//关位选, 去除对上一位的影响

P0 = 0xff;

wela = 1; //打开锁存, 给它一个下降沿量

wela = 0;

//段选

if(count != 2)

{

P0 = table[datas[count]]; //显示数字

}

else

{

P0 = tableWidthDot[datas[count]]; //显示带小数点数字

}

dula = 1; //打开锁存, 给它一个下降沿量

dula = 0;

//位选

P0 = _crol_(0xfd, count); //选择第(count + 1) 个数码管

wela = 1; //打开锁存, 给它一个下降沿量

wela = 0;

delay(timeCount);

}

}

void main()

{

unsigned char i;

while(1)

{

//启动温度转换

sendChangeCmd();

//显示5次

for(i = 0; i < 40; i++)

{

display(tempValue);

}

tempValue = getTmpValue();

}

提醒:《51单片机DS18B20温度计C语言程序(附详解)》最后刷新时间 2024-03-14 01:00:32,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《51单片机DS18B20温度计C语言程序(附详解)》该内容的真实性请自行鉴别。