在这里插入图片描述
当温度转换命令(44H)发布后,经转换所得的温度值以二字节补码形式存放在高速暂存存储器的旁手第 0 和第 1 个字节。存储的两个字节,高字节的前 5 位是符号位 S,单片机可通过单线接口读到该数据,读取时低位在前,高位在后, 数据格式如下:
在这里插入图片描述
如果测得的温度大于 0,这 5 位为‘ 0’,只要将测到的数值乘以 0.0625 (默认精度是 12 位)即可得到实际温度;如果温度小于 0,这 5 位为‘ 1’, 测到的数值需要取反加 1 再乘以 0.0625 即可得到实际温度。温度与数据对应关系如下:
在这里插入图片描述
比如我们要计算+85 度,数据输出十六进制是 0X0550,因为高字节的高 5 位为 0,表明检测的温度是正温度,0X0550 对应的十进制为 1360,将这个值乘以12 位精度 0.0625,李祥所以可以得到+85 度。
3、信号时序
由于 DS18B20 是单总线器件,所有的单总线器件都要求采用严格的信号时序,以保证 数据的 完整性。DS18B20 时序包括如下几种:初始化时序、写(0 和 1)时序、 读(0 和 1)时序。 DS18B20 发送所有的命令和数据都是字节的低位在前。这里我们 简单介绍这几个信号的时序:
(1)初始化时序
单总线上的所有通信都是以初始化序列开始。主机输出低电平,保持低电平时间至少 480us(该时间的时间范围可以从 480 到 960 微妙),以产生复位脉冲。接着主机释放总线,外部的上拉电阻将单总线拉高,延时 15~60 us,并进入接收模式。接着 DS18B20 拉低总线 60~240 us,以产生低电平应答脉冲,若为低电平哪启搏,还要做延时,其延时的时间从外部上拉电阻将单总线拉高算起最少要480 微妙。初始化时序图如下:
在这里插入图片描述
(2)写时序
写时序包括写 0 时序和写 1 时序。所有写时序至少需要 60us,且在 2 次独立的写时序之间至少需要 1us 的恢复时间,两种写时序均起始于主机拉低总线。写 1 时序:主机输出低电平,延时 2us,然后释放总线,延时 60us。写 0 时序:主机输出低电平,延时 60us,然后释放总线,延时 2us。写时序图如下:
用51做处理器,外围电路如图,一片双积分转换芯片ICL7135做AD,它的时钟需要125K,用51的ALE经过一片CD4024分频得到。1403提供基准源。另外,一片7660提供7135工作所需要的负压。为了省电,把所有模拟电路部分电源用一个晶体管管理起来,由培衫P1.0来控制。(上图为示意图,省去了电阻没画)P1.0为地的时候,模拟系统才上电
现在怪现象如下:
仿真机正常运行,烧写芯片后无反应。
仿真正常,说明外围芯片完全正常,电路也没有错误。
经过检查,晶体正常,复位可靠,EA高,程序堆栈都没有溢出,并排除其它一切低级错误的可能。
再编写一程序,
main()
{
while(1) {P1.1=0}
}
P1.1和VCC间接有一发光管,开机无反应。
后来,发现更奇怪的现象:
拔除CD4024,MC1403,ICL7135,ICL7660中的任何一个,系统就可以正常运行!
百思不得其解,茶饭不思,郁闷了N久
更换全部芯片,如故。
更换ATMEL/PHILIPS/WINBOND的N款单片机,如故。
检查,排除配大腔电路故障的可能,
后来又发现,只要上电之前把P1.0对地短路,(也就是模拟部分强加电源),上电,系统正常运行。
但是,如果开机前P1.0不对地短路,上电一定不能运行,此后即使再把P1.0对地接,也不行。
顺这个思路,应该是和模拟部分有关……
又是郁闷N久,之后,无意间翻看CD4024内部图,茅塞顿开……
CD4024等TTL/CMOS逻辑芯片,为了防止静电或错误的IO电平,内部都有保护电路
51单片机故障分析一个 - cryinrain_cug - cryinrain_cug的博客
如图2,每个IO口都有如图的2个二极管,集成在芯片内部。保证IO口电压在-0.6~5.6V之间
复位的过程中,全部IO为高,P1.0和ALE当然也是高。这样模拟部分不上电。
那么,ALE的输出角就等效于通过一个二极管向这四块模拟芯片供电!!!(如图)
ALE的输出能力不强,自然,ALE就被拉低了。
在查看51的手册,ALE和/PROG脚是复用的!!
在复位过程中,ALE如果为低,芯片进入编程状态!!!
也就是说,我的系统在上电复位的过程中就进入了PROG编程模式,难怪一条语句都不能仿仔执行
那么,也很好解释为什么四个芯片中拔掉一个就能正常工作了,因为负载轻了,ALE可能还没有被拉到2.5V以下,所以正常复位进入程序。
解决的办法:ALE接2K的上拉,再通过47K电阻接到Cd4024上,上电,一切正常!
结论:单片机编程模式/ISP模式是通过用户很不容易出现的一个时序来启动的,在一些特殊应用时要小心避开这些非用户代码模式。
//保证正确,请给最佳回答//安装目录下的EXE文件打开后可在电脑上显示当前温度兄睁值
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit DS=P2^2 //define interface
uint temp// variable of temperature
uchar flag1 // sign of the result positive or negative
sbit dula=P2^6
sbit wela=P2^7
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}
unsigned char code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,
0x87,0xff,0xef}
void delay(uint count) //delay
{
uint i
while(count)
{
i=200
while(i>0)
i--
count--
}
}
///////功能:串口初始化,波特率羡袜岁9600,方式1///////
void Init_Com(void)
{
TMOD = 0x20
PCON = 0x00
SCON = 0x50
TH1 = 0xFd
TL1 = 0xFd
TR1 = 1
}
void dsreset(void) //send reset and initialization command 18B20复位,初始化函数
{
uint i
DS=0
i=103
while(i>0)i--
DS=1
i=4
while(i>0)i--
}
bit tmpreadbit(void) //read a bit 读1位数据函数
{
uint i
bit dat
DS=0i++ //i++ for delay
DS=1i++i++
dat=DS
i=8while(i>0)i--
return (dat)
}
uchar tmpread(void) //read a byte date 读1字节函数
{
uchar i,j,dat
dat=0
for(i=1i<=8i++)
{
j=tmpreadbit()
dat=(j<<7)|(dat>>1) //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
return(dat)
}
void tmpwritebyte(uchar dat) //write a byte to ds18b20 向1820写一个字节数据函好凯数
{
uint i
uchar j
bit testb
for(j=1j<=8j++)
{
testb=dat&0x01
dat=dat>>1
if(testb) //write 1
{
DS=0
i++i++
DS=1
i=8while(i>0)i--
}
else
{
DS=0 //write 0
i=8while(i>0)i--
DS=1
i++i++
}
}
}
void tmpchange(void) //DS18B20 begin change 开始获取数据并转换
{
dsreset()
delay(1)
tmpwritebyte(0xcc) // address all drivers on bus 写跳过读ROM指令
tmpwritebyte(0x44) // initiates a single temperature conversion 写温度转换指令
}
uint tmp() //get the temperature 读取寄存器中存储的温度数据
{
float tt
uchar a,b
dsreset()
delay(1)
tmpwritebyte(0xcc)
tmpwritebyte(0xbe)
a=tmpread() //读低8位
b=tmpread() //读高8位
temp=b
temp<<=8//two byte compose a int variable 两个字节组合为1个字
temp=temp|a
tt=temp*0.0625 //温度在寄存器中是12位,分辨率是0.0625
temp=tt*10+0.5 //乘10表示小数点后只取1位,加0.5是四折五入
temp=temp+4//误差补偿
return temp
}
void readrom() //read the serial
{
uchar sn1,sn2
dsreset()
delay(1)
tmpwritebyte(0x33)
sn1=tmpread()
sn2=tmpread()
}
void delay10ms()//delay
{
uchar a,b
for(a=10a>0a--)
for(b=60b>0b--)
}
void display(uint temp) //显示程序
{
uchar A1,A2,A2t,A3,ser
ser=temp/10
SBUF=ser
A1=temp/100
A2t=temp%100
A2=A2t/10
A3=A2t%10
dula=0
P0=table[A1] //显示百位
dula=1
dula=0
wela=0
P0=0x7e
wela=1
wela=0
delay(2)
dula=0
P0=table1[A2] //显示十位
dula=1
dula=0
wela=0
P0=0x7d
wela=1
wela=0
delay(2)
P0=table[A3] //显示个位
dula=1
dula=0
P0=0x7b
wela=1
wela=0
delay(1)
}
void main()
{
uchar a
Init_Com()
do
{
tmpchange()
// delay(200)
for(a=10a>0a--)
{ display(tmp())
}
}while(1)
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)