求一个DS18B20使数码管显示十位和个位温度的程序,段选是P2.5口,位选是P2.6口,很急呀!
没有你的硬件,用PROTEUS仿真了一个显示电路,见插图。
稍稍改了一下程序,显示效果不错,数值随着温度调整,可以发生变化。
……
temp = TMPH;
temp <<= 8;
temp = temp | TMPL;
tt = temp * 0.0625;
a = tt * 10000;
a = a + 1235; //加上了四位小数
//温度百位
P2 = 255; //先消隐
P0 = table1[a / 1000000];
P2 = 255 - 0x80; delayms(5); //延时5ms
//温度十位
P2 = 255; P0 = table1[a % 1000000 / 100000];
P2 = 255 - 0x40; delayms(5);
//温度个位,此位带小数点
P2 = 255; P0 = table2[a % 1000000 / 10000 % 10];
P2 = 255 - 0x20; delayms(5);
//温度十分位
P2 = 255; P0 = table1[a % 1000000 / 1000 % 10];
P2 = 255 - 0x10; delayms(5);
//温度百分位
P2 = 255; P0 = table1[ a % 1000000 / 100 % 10];
P2 = 255 - 8; delayms(5);
//温度千分位
P2 = 255; P0 = table1[a % 1000000 / 10 % 10];
P2 = 255 - 4; delayms(5);
//温度万分位
P2 = 255; P0 = table1[a % 1000000 % 10];
P2 = 255 - 2; delayms(5);
}
}
楼主你在时序上有些错误
1。在转换时没有留够足够的转换时间。根据DS18B20芯片手册,9位精度转换时间为93.75ms。12位精度转换时间为750ms。而DS18B20默认为12位精度。所以我加了750ms延时
2。在写函数的时候
void ds18b20_write_byte(uchar date) //写一个字节
{
uchar i;
for(i=0;i<8;i++) //一个字节八位
{
if((date&&0x01)==1) //写入1
{
ds18b20=0;
delay_15us();
ds18b20=1;
}
else //写入0
{
ds18b20=0;
delay_60us();
ds18b20=1;
}
date>>=1; //右移一位
}
}
应该是if((dat&0x01)==0x01)这里多了一个&号,导致结果错误。
3。我增加了用1602显示的模块,删除了用液晶显示的模块。
/**********************************
以下是程序,并附上仿真图一张
**********************************/
#include
#include
#define uchar unsigned char
#define uint unsigned int
uchar temp,tmph,tmpl;
sbit ds18b20=P2^3;
sbit rw=P2^6;
sbit lcde=P2^7;
sbit rs=P2^5;
//下面是1602的驱动程序
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_com(uchar com,bit i) //是命令写0 数据写1
{
rs=i;
P0=com;
delay(5);
lcde=1;
delay(5);
lcde=0;
}
void lcd1602init(void)
{
rw=0;
write_com(0x01,0);
write_com(0x02,0);
write_com(0x06,0);
write_com(0x0c,0);
write_com(0x38,0);
}
void display(uchar x,uchar y,uchar date)
{
x&=0x01;
y&=0x0f;
if(x)
{
y+=0x40;
}
y+=0x80;
write_com(y,0);
write_com(date,1);
}
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
/////////////////////////////////////////////////////////
/////DS18B20部分////////////
///////////////////////////
//延时部分
void delay_600us(void)
{
uchar i;
for(i=0;i<180;i++);
}//延时600us
void delay_400us(void)
{
uchar i;
for(i=0;i<120;i++);
}
void delay_60us(void)
{
uchar i;
for(i=0;i<18;i++);
}//延时60us
void delay_15us(void)
{
uchar i;
for(i=0;i<3;i++);
}//延时15us
//复位脉冲
bit resetpulse(void)
{
ds18b20=0;
delay_600us();
ds18b20=1;
delay_60us();
return ds18b20;
}
//ds18b20初始化
void ds18b20_init(void)
{
while(1)
{
if(!resetpulse()) //收到ds18b20的低电平信号
{
ds18b20=1;
delay_400us();
break;
}
else
resetpulse(); //继续发送复位信号
}
}
void ds18b20_write_byte(uchar date) //写一个字节
{
uchar i;
for(i=0;i<8;i++) //一个字节八位
{
// if((date&&0x01)==1) //写入1
//这里错了
if((date&0x01)==0x01)
{
ds18b20=0;
_nop_();
ds18b20=1;
delay_60us();
} //end if
else //写入0
{
ds18b20=0;
delay_60us();
ds18b20=1;
} //end else
delay_15us();
date>>=1; //右移一位
}
}
uchar ds18b20_read_byte(void) //读一个字节
{
uchar i,u;
for(i=0;i<8;i++)
{
u>>=1;
ds18b20=0;
_nop_();
//释放总线
ds18b20=1;
_nop_();
_nop_();
if(ds18b20==1) //读1
{
u|=0x80;
}
else
{ u=u&0x7f; //读0
}
delay_60us();
}
return u;
}
uchar read_temperaturn()
{
ds18b20_init(); //初始化;
ds18b20_write_byte(0xcc); //跳过ram;
ds18b20_write_byte(0x44); //启动温度测量 当为高电平时转换完成
delayms(750); //转换时间要求
ds18b20_init(); //初始化;
ds18b20_write_byte(0xcc); //跳过ram;
ds18b20_write_byte(0xbe); //采集温度
delayms(750);
tmpl=ds18b20_read_byte(); //低位温度数据
tmph=ds18b20_read_byte(); //高位温度数据
tmph<<=4; //左移4位
tmph+=(tmpl&0xf0)>>4;
return(tmph);
}
void main()
{
uchar temph=0;
uchar templ=0;
lcd1602init();
while(1)
{ temp=read_temperaturn();
temph=temp/10+'0';
templ=temp%10+'0';
delayms(20);
display(0,0,temph);
display(0,1,templ);
}
}
#define uchar unsigned char
#define uint unsigned int
uchar bai,shi,ge,xiaoshu,fuhao;
bit sign; //负数的标志位
bit f; //DS18B20初始化成功标志位
sbit DQ=P1^7;
sbit LS138A = P2^0; //定义138译码器的输入A脚由P2.0控制
sbit LS138B = P2^1; //定义138译码器的输入脚B由P2.1控制
sbit LS138C = P2^2; //定义138译码器的输入脚C由P2.2控制
uchar Temp[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40/*负号*/};
void delayms(uint z) //延时大约1ms
{
uchar i,j;
for(i=0;i<z;i++)
for(j=0;j<115;j++);
}
void delayus(uchar i) //延时大约6us
{
while(i--);
}
void init_ds18b20()
{
DQ=1;
delayus(8);
DQ=0;
delayus(80);
DQ=1;
delayus(8);
delayus(4);
while(DQ==0)
f=1;
}
//写一个字节的数据,低位在前
void write_ds18b20(uchar date)
{
uchar i=0;
for(i=0;i<8;i++)
{
DQ=0;
DQ=date&0x01;
delayus(4); //延时约48us
DQ=1;
date>>=1;
}
delayus(4);
}
//读一个字节的数据
uchar read_ds18b20()
{
uchar i=0,dat=0;
for(i=0;i<8;i++)
{
DQ=0;
dat>>=1;
DQ=1;
if(DQ==1)
dat|=0x80;
delayus(4);
}
return dat;
}
//温度的转换,获取温度
uint wendu()
{
uchar temph,templ;
uint temp;
//float t;
init_ds18b20();
write_ds18b20(0xcc);
write_ds18b20(0x44);
delayms(10);
init_ds18b20();
write_ds18b20(0xcc);
write_ds18b20(0xbe);
templ=read_ds18b20();
temph=read_ds18b20();
if((temph&0xf8)!=0x00)
{
sign=1; //此时温度为零下,即为负数
temph=~temph;
templ=~templ;
templ+=1;
if(templ>255)
temph++;
}
temp=temph;
temp&=0x07;
temp=((temph*256)+templ)*0.625+0.5;
return temp;
}
void smg()
{
LS138A=0;
LS138B=0;
LS138C=0;
P0=0;
}
void display()
{
uint LedOut[10],i=4;
uint num;
num=wendu();
bai=num/1000;
shi=num%1000/100;
ge=num%100/10;
xiaoshu=num%10;
fuhao=10;
if(!f)
P0=0x00;
else
{
LedOut[4]=Temp[bai]; //百位
if(bai==0)
{
i=5;
if(sign==1) // 负号
{
i=4;
LedOut[4]=Temp[fuhao];
}
}
LedOut[5]=Temp[shi]; //十位
if(bai==0&&shi==0)
{
i=6;
if(sign==1) //负号
{
i=5;
LedOut[5]=Temp[fuhao];
}
}
LedOut[6]=Temp[ge]|0x80; //个位带小数点儿
LedOut[7]=Temp[xiaoshu]; //小数位
for( i; i<9; i++) //实现8位动态扫描循环
{
P0 = LedOut[i]; //将字模送到P0口显示
switch(i)
{
case 0:LS138A=0; LS138B=0; LS138C=0; break;
case 1:LS138A=1; LS138B=0; LS138C=0; break;
case 2:LS138A=0; LS138B=1; LS138C=0; break;
case 3:LS138A=1; LS138B=1; LS138C=0; break;
case 4:LS138A=0; LS138B=0; LS138C=1; break;
case 5:LS138A=1; LS138B=0; LS138C=1; break;
case 6:LS138A=0; LS138B=1; LS138C=1; break;
case 7:LS138A=1; LS138B=1; LS138C=1; break;
}
delayms(1);
}
}
}
void main()
{
smg();
while(1)
{
wendu();
display();
}
}
这是我写的,带负数显示的,你自己看看吧!
干嘛把段选和位选都定的那么死,搞一个,自己改改不久成了吗。网上那么多程序。
DS18B20一个函数看不懂
DS18B20 的数据,是串行的,8位数,最先出来的最低位(bit0)。那么,单片机,每读出来一位数,就把 DAT 右移一次,并把新数据放到 DAT 的最高位(bit7),操作八次之后,最先读出的一位数,就放在 DAT 的最低位了。dat=(j<<7)|(dat>>1);这就是《把 j 移动到 bit7》、《dat 右移一位...
求一个关于DS18B20的汇编程序
***; Read a temperature from the DS18B20DSWD: LCALL RSTSNR ; Init of the DS18B20 JNB F0,KEND MOV R0,#0CCH LCALL SEND_BYTE MOV R0,#44H LCALL SEND_BYTE ; Send a Convert Command SETB EA MOV 48H,#1 SS2: MOV ...
我做了一个DS18B20的测温显示程序,在Proteus上模拟完全正确,但实际电 ...
接线没有问题了,程序有点问题,断开后还能检测到数据 是不对的。程序上没有做断开18B20的检测。要么你就断开后显示断开前读到的温度值也行啊。
各位大侠,我是单片机新手,做个DS18B20的温测小系统,数码管老显示“00...
1.先不考虑检测值,单显示测试正常否。2.温度检测值应该是没检测到
问一下高手们刚做了一个DS18B20温度显示的,但是显示在数码管上的数总...
如果你采用动态扫描方式数码管闪烁说明你的刷新扫描时间太长,以致于人眼能感觉出闪烁。当然,如果你确认你的扫描时间没问题,那就要确认一下你在刷新显示的时候会不会被中断,如果被中断后会不会影响你显示时序等以及中断时间会不会太长。如果你要通过中断来显示也行,只需用定时器定时,每隔一断时间(...
STM8S207做一个DS18B20的程序,结果一直显示95.9,也就是说,高8位和低8...
上拉电阻(和18b20连的电阻)连到GND了,应连VCC
用51单片机和18b20做一个温度计,求一个完整程序,要求用12864显示。_百度...
1.DS18B20基本知识 DS18B20数字温度计是DALLAS公司生产的1-Wire,即单总线器件,具有线路简单,体积小的特点。因此用它来组成一个测温系统,具有线路简单,在一根通信线,可以挂很多这样的数字温度计,十分方便。1、DS18B20产品的特点 (1)、只要求一个端口即可实现通信。(2)、在DS18B20中的每个器件上...
4个DS18B20与单片机相连 怎么区分呢 方便给个程序吗谢谢
DS18B20是一线制通信,一个DS18B20和单片机只需要一个GPIO引脚连接即可。4个DS18B20连接单片机的四个GPIO,所用IO引脚名称和DS18B20对应起来,这样通过驱动不同的GPIO,就知道程序读取的是哪个DS18B20了 每一个DS18B20打包写一个驱动函数,在主循环里,加载这四个驱动函数,并把读上来到数据保存到4个全局变量...
求一个51单片机 用DS18B20芯片实现 的温控程序
DO EQU P3.4 CLK EQU P3.5 CS EQU P3.6 ; LCD端口定义 D2RS EQU P2.7 D2RW EQU P2.6 D2E EQU P2.5 KEYPORT EQU P1 ; DS18B20端口定义 TEMPER_L EQU 36H TEMPER_H EQU 35H TEMPER_NUM EQU 38H FLAG1 BIT 00H DQ BIT P2.4 ORG 00...
虿受胆维: 参考下吧! 18B20数字温度显示系统 综合实验:用18B20(数字温度采集)74LS47(数码管译码)74LS138(三八译码) DS18B20是DALLAS公司生产的一线式数字温度传感器,具有3引脚TO-92小体积封装形式;温度测量范围为-55℃~+125...
东台市19587192205: 单片机 通过DS18B20测试当前环境温度, 并通过数码管显示当前温度值 - ?
虿受胆维: void dsInit() //初使化DS18b20 dsWait() //等待,延时 bit readBit() //读取一bit(一位),返回值为一个bit unsigned char readByte() //读取一个字节(Byte),就是读ds18b20一个字节的信息 void writeByte(unsigned char dat) //写一个字节给ds18b20,参数就是要写进的数据 int getTmpValue() //获取温度值,这个会返回一个整型的温度值
东台市19587192205: 求一个ds18b20数字温度测量的C程序 - ?
虿受胆维: #include"reg51.h"#include"intrins.h" unsigned char templ=0; unsigned char temph=0; unsigned char tempdot=0; bit fuhao_flag=0; float temperature=0; unsigned char t=0; unsigned char tab[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,...
东台市19587192205: avr单片机18B20温度传感器编程 - ?
虿受胆维: ;这是关于DS18B20的读写程序,数据脚P2.2,晶振12MHZ ;温度传感器18B20汇编程序,采用器件默认的12位转化,最大转化时间750微秒 ;可以将检测到的温度直接显示到AT89C51开发实验板的两个数码管上 ;显示温度00到99度,很准...
东台市19587192205: 单片机ds18b20测温数码管显示程序,我参照原来程序改的,为何一个显示十进制一个显示16进制??
虿受胆维: 我发现了三个不同之处. 不知道你有没有仔细比较 : 1、uchar readbyte()中i应该<=8; 2、显示十位时,原程序是 table1[]; 3、结尾 display(tmp());后没有延时一个机器周期,1ms.
东台市19587192205: DS18B20采集温度用4位八段数码管显示的编码 - ?
虿受胆维: /*DS18b20温度传感器 p3.4作为数据传输口 p1.0~3控制显示led的位选 共阳极 经过PNP后 低电平有效 p0口是led的字形码 晶振:11.0592M 设计者:陈仲库 设计日期:2006年3月29日*/#include//#include//#include//#include sbit DQ= P3^4; sbit p...
东台市19587192205: 高分悬赏...ds18b20+单片机+数码管显示,结果是只显示0到9个数字.求助大虾帮忙!如能解决问题, - ?
虿受胆维: 我先简单说一下,程序很长,大概看了看,假设你的程序工作起来没有问题的话,我认为是7段码显示的问题,7段码显示属于扫描机制,你可以把display()函数里面的延时时间延长10倍-100倍看看有没有改善.
东台市19587192205: DS18B20检测到的温度用数码管显示出来,用C程序写,电路图如下(数码管为共阴极). - ?
虿受胆维: 你好:我有LCD1602和LCD12864的DS1820程序,数码管的更简单,我可以给你LCD的程序,你自己修改一点.希望我的回答能帮助到你.
东台市19587192205: 51单片机、一个18b20测温,数码管显示的电路图 - ?
虿受胆维: 51单片机连接多个数码管,不使用锁存器等附加元件,需要进行扫描来显示.八个数据口,每个数码管再占用一个使能位选.给你一张图片看看.图上的三极管是增加驱动能力的,用普通数码管时可以不加. 18b20是单线的,就是说加个两条电源线,和一条单条数据线(自己选51单片机的一个引脚就可以了).连接非常简单,但对时序要求非常严格哦,建议你参考几份程序,手边在对照18b20的器件手册来看.
东台市19587192205: 求助:51单片机使用74hc595、DS18B20温度显示,我现在单片机能用的口只有10个,有没有可行的C语言程序? - ?
虿受胆维: 用两片74hc595就可以连接8位LED数码管显示电路,足够显示温度了.只需要3个I/O脚,而DS18B20只需要1个I/O脚.所以,你的单片机还有10个脚,是足够的.用两片74hc595就可以连接8位LED数码管显示电路和程序,在这里可以搜索到无数例子的.