DS18B20初始化C语言程序,求解释,越详细越好

DS18B20初始化C语言程序,求解释,越详细越好,第1张

第一个程序是初始化DS18B20用的,是根据时序先置0后置1的过程,这个过程中延时时间的精度很重要,需要根据实际使用的硬件情况时行计算,置0需要保持480-960us

第二个程序很少看到用,一般是计算时长,在过了相应的时间后直接去读取数据,楼主程序使用循环255次的时间需要根据编译后的汇编代码来计算,请楼主行算一下;感觉楼主的这个程序采用不停检测和循环的做法有些夸张。

楼主要深入了解这个程序,最好还是直接看MAXIM-IC.COM网站上DS18B20的相关资料,重点是时序图和相关的命令流程图,看懂了是很有帮助的。

#include <reg52.h>

#include <intrins.h>

#define uchar unsigned char

#define uint unsigned int

sbit DS=P3^3 //定义DS18B20接口

int temp

uchar flag1

void display(unsigned char *lp,unsigned char lc)//数字的显示函数;lp为指向数组的地址,lc为显示的个数

void delay()//延时子函数,5个空指令

code unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x08,0x00}

//共阴数码管 0-9 - _ 空 表

unsigned char l_tmpdate[8]={0,0,10,0,0,0,0,0}//定义数组变量,并赋值1,2,3,4,5,6,7,8,就是本程序显示的八个数

int tmp(void)

void tmpchange(void)

void tmpwritebyte(uchar dat)

uchar tmpread(void)

bit tmpreadbit(void)

void dsreset(void)

void delayb(uint count)

void main() //主函数

{

uchar i

int l_tmp

while(1)

{

tmpchange() //温度转换

l_tmp=tmp()

if(l_tmp<0)

l_tmpdate[0]=10//判断温度为负温度,前面加"-"

else

{

l_tmpdate[0]=temp/1000//显示百位,这里用1000,是因为我们之前乖以10位了

if(l_tmpdate[0]==0)

l_tmpdate[0]=12//判断温度为正温度且没有上百,前面不显示

}

l_tmp=temp%1000

l_tmpdate[1]=l_tmp/100//获取十位

l_tmp=l_tmp%100

l_tmpdate[2]=l_tmp/10//获取个位

l_tmpdate[3]=11

l_tmpdate[4]=l_tmp%10//获取小数第一位

for(i=0i<10i++){ //循环输出10次,提高亮度

display(l_tmpdate,5)

}

}

}

void display(unsigned char *lp,unsigned char lc)//显示

{

unsigned char i //定义变量

P2=0//端口2为输出

P1=P1&0xF8 //将P1口的前3位输出0,对应138译门输入脚,全0为第一位数码管

for(i=0i<lci++){ //循环显示

P2=table[lp[i]] //查表法得到要显示数字的数码段

delay() //延时5个空指令

if(i==7)//检测显示完8位否,完成直接退出,不让P1口再加1,否则进位影响到第四位数据

break

P2=0//清0端口,准备显示下位

P1++//下一位数码管

}

}

void delay(void)//空5个指令

{

_nop_()_nop_()_nop_()_nop_()_nop_()

}

void delayb(uint count) //delay

{

uint i

while(count)

{

i=200

while(i>0)

i--

count--

}

}

void dsreset(void) //DS18B20初始化

{

uint i

DS=0

i=103

while(i>0)i--

DS=1

i=4

while(i>0)i--

}

bit tmpreadbit(void) // 读一位

{

uint i

bit dat

DS=0i++ //小延时一下

DS=1i++i++

dat=DS

i=8while(i>0)i--

return (dat)

}

uchar tmpread(void) //读一个字节

{

uchar i,j,dat

dat=0

for(i=1i<=8i++)

{

j=tmpreadbit()

dat=(j<<7)|(dat>>1) //读出的数据最低位在最前面,这样刚好//一个字节在DAT里

}

return(dat)//将一个字节数据返回

}

void tmpwritebyte(uchar dat)

{ //写一个字节到DS18B20里

uint i

uchar j

bit testb

for(j=1j<=8j++)

{

testb=dat&0x01

dat=dat>>1

if(testb) // 写1部分

{

DS=0

i++i++

DS=1

i=8while(i>0)i--

}

else

{

DS=0 //写0部分

i=8while(i>0)i--

DS=1

i++i++

}

}

}

void tmpchange(void) //发送温度转换命令

{

dsreset()//初始化DS18B20

delayb(1)//延时

tmpwritebyte(0xcc) // 跳过序列号命令

tmpwritebyte(0x44) //发送温度转换命令

}

int tmp() //获得温度

{

float tt

uchar a,b

dsreset()

delayb(1)

tmpwritebyte(0xcc)

tmpwritebyte(0xbe) //发送读取数据命令

a=tmpread() //连续读两个字节数据

b=tmpread()

temp=b

temp<<=8

temp=temp|a//两字节合成一个整型变量。

tt=temp*0.0625 //得到真实十进制温度值,因为DS18B20

//可以精确到0.0625度,所以读回数据的最低位代表的是

//0.0625度。

temp=tt*10+0.5 //放大十倍,这样做的目的将小数点后第一位

//也转换为可显示数字,同时进行一个四舍五入 *** 作。

return temp//返回温度值

}

void readrom() //read the serial 读取温度传感器的序列号

{ //本程序中没有用到此函数

uchar sn1,sn2

dsreset()

delayb(1)

tmpwritebyte(0x33)

sn1=tmpread()

sn2=tmpread()

}

void delay10ms()

{

uchar a,b

for(a=10a>0a--)

for(b=60b>0b--)

}

单片机DS18B20温度计C语言程序

标签:单片机 c语言 ds18b20 温度计 51 mcu

http://www.dzkfw.com.cn

#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 = 0j <125j++)

}

}

//初始化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=0i<8i++)

{

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 = 0j <8j++)

{

b = dat &0x01

dat >>= 1

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

if(b)

{

ds = 0

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

ds = 1

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

}

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

ds = 0

i = 8while(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 = 0count != 5count++)

{

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

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 = 0i <40i++)

{

display(tempValue)

}

tempValue = getTmpValue()

}

http://www.dzkfw.com.cn/myxin/51c_language.chm 单片机c语言最好用的教程


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7810117.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-10
下一篇 2023-04-10

发表评论

登录后才能评论

评论列表(0条)

保存