DS18B20中,为什么用温度显示函数起到延时作用这样的代码可以延时多久呢
- DS18B20中,为什么用温度显示函数起到延时作用这样的代码可以延时多久呢
- 89C51控制DS18B20时,无用语句删除就不能编译,请高手前来解答,谢谢!下面是程序的源代码,在Keil里编写
- 单片机,DS18B20,代码中 if(DQ) dat|=0x80; 这个一段是什么意思,为什么这样用谢谢!!!!!
- DS18B20的控制方法
- DS18B20初始化C语言程序,求解释,越详细越好
- 温度计的设计,(使用DS18B20)
- 单片机AT89C51连接DS18B20然后将采集到的两个字节通过RS232发送到PC机界面中,请问单片机用C语言怎么编写
- 您好!如何用51单片机显示DS18b20温度传感器的温度变化,并通过蓝牙HC08传送数据给电脑代码有点难
你好:
因为执行代码需要时间,所以调用一次dis_temp(get_temp);
就消耗一定的时间。
至于这个函数到底需要多少时间,一根据单片机类型决定,二晶振大小。并且函数执行时间人为很难计算,一般都是通过编译器的Debug来调试,有一个时间计量的框,里边观察时间的变化。
希望我的回答能帮助到你。
这个可能是你复制程序里写错了的,可能是
tt= tt*10+0.5;
这里温度的精度可能取整数位,可能的函数返回值定义为 INT型,
RETURN (X) 时,根据函数定义直接截位,
其它同上一回答
整体时序 总线上只有一个传感器18B20时, 时序:复位→忽略ROM匹配(0xcc)→温度转换(0x44)→延时→复位→忽略ROM匹配→读指令→分别读取温度两个字节 总线上有多个传感器18B20时, 时序:复位→ROM匹配(0x55)→发送8字节ROM ID →温度转换(0x44)→延时→复位→ROM匹配→再次发送8字节ROMID→读指令→分别读取温度两个字节 当然,在第一次发送温度转换之前 可以忽略ROM匹配,此时所有的传感器都进行温度转换
DS18B20有六条控制命令,如表4.1所示:
表4.1 为DS18B20有六条控制命令
指 令 约定代码 操 作 说 明
温度转换 44H 启动DS18B20进行温度转换
读暂存器 BEH 读暂存器9字节二进制数字
写暂存器 4EH 将数据写入暂存器的TH、TL字节
复制暂存器 48H 把暂存器的TH、TL字节写到E2PROM中
重新调E2PROM B8H 把E2PROM中的TH、TL字节写到暂存器TH、TL字节
读电源供电方式 B4H 启动DS18B20发送电源供电方式的信号给主CPU (1) 先将数据线置高电平“1”。
(2) 延时(该时间要求的不是很严格,但是尽可能的短一点)
(3) 数据线拉到低电平“0”。
(4) 延时750微秒(该时间的时间范围可以从480到960微秒)。
(5) 数据线拉到高电平“1”。
(6) 延时等待(如果初始化成功则在15到60微秒时间之内产生一个由DS18B20所返回的低电平“0”。据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使程序进入死循环,所以要进行超时控制)。
(7) 若CPU读到了数据线上的低电平“0”后,还要做延时,其延时的时间从发出的高电平算起(第(5)步的时间算起)最少要480微秒。
(8) 将数据线再次拉高到高电平“1”后结束。
其时序如图4.13所示:
图4.13 初始化时序图 (1) 数据线先置低电平“0”。
(2) 延时确定的时间为15微秒。
(3) 按从低位到高位的顺序发送字节(一次只发送一位)。
(4) 延时时间为45微秒。
(5) 将数据线拉到高电平。
(6) 重复上(1)到(6)的操作直到所有的字节全部发送完为止。
(7) 最后将数据线拉高。
DS18B20的写操作时序图如图4.14所示。
图4.14 DS18B20的写操作时序图 (1)将数据线拉高“1”。
(2)延时2微秒。
(3)将数据线拉低“0”。
(4)延时3微秒。
(5)将数据线拉高“1”。
(6)延时5微秒。
(7)读数据线的状态得到1个状态位,并进行数据处理。
(8)延时60微秒。
DS18B20的读操作时序图如图4.15所示。
图1.15 DS18B20的读操作图
第一个程序是初始化DS18B20用的,是根据时序先置0后置1的过程,这个过程中延时时间的精度很重要,需要根据实际使用的硬件情况时行计算,置0需要保持480-960us;
第二个程序很少看到用,一般是计算时长,在过了相应的时间后直接去读取数据,楼主程序使用循环255次的时间需要根据编译后的汇编代码来计算,请楼主行算一下;感觉楼主的这个程序采用不停检测和循环的做法有些夸张。
楼主要深入了解这个程序,最好还是直接看MAXIM-IC.COM网站上DS18B20的相关资料,重点是时序图和相关的命令流程图,看懂了是很有帮助的。
#include?《reg52.h》
#include?《math.h》????//Keil?library??
#include?《stdio.h》???//Keil?library
#include?《INTRINS.H》
#define?uchar?unsigned?char?
#define?uint?unsigned?int
#define?display1??0x01??????//数码管1从左至右
#define?display2??0x02????//数码管2从左至右
#define?display3??0x04?????//数码管3从左至右
#define?display4??0x08??//数码管4从左至右
#define?display5??0x10???//数码管5从左至右
#define?display6??0x20??//数码管6从左至右
#define?display7??0x40??????//数码管7从左至右
#define?display8??0x80??//数码管8从左至右
sbit?led=P1^5;
sbit?TMDAT=P3^6;??????????//根据实实际情况设定
sbit?set=P1^0;//设定
sbit?up=P1^1;//加
sbit?down=P3^2;//减
uchar?tempint,f,bb,tempth,settemp;?//温度整数部分和小数部分
float?wendu;
int?tempdf,c;
????code?unsigned?char?ledmap={0xc0,0xf9,0xa4,0xb0,0x99,
???????????????????????????????0x92,0x82,0xf8,0x80,0x90,0xbf};
????code?unsigned?char?ledmap1={0x40,0x79,0x24,0x30,
?????????????????????????????????0x19,0x12,0x02,0x78,0x00,0x10};
?????????????????????????????????//7段数码管0~9数字的共阳显示代码和负号位代码(最后一位)
void?set_ds18b20();???????????????????//初始化DS18B20子程序
void?get_temperature();???????????????//获得温度子程序
void?read_ds18b20();??????????????????//读DS18B20子程序
void?write_ds18b20(uchar?command);????//向DS18B20写1字节子程序
void?delayms(uchar?count);????????????//延时count毫秒子程序
void?disp_temp(tempint,tempdf);?????//显示温度子程序
//***********************初始化DS18B20子程序**********************************
//****************************************************************************
void?set_ds18b20()
{
????while(1)
????{?
????????uchar?delay,flag;
????????flag=0;
????????TMDAT=1;
????????delay=1;
??while(--delay);
????????TMDAT=0;??????????????????//数据线置低电平
????????delay=250;
????????while(--delay);??????????//低电平保持500us
????????TMDAT=1;??????????????????//数据线置高电平
????????delay=30;
????????while(--delay);??????????//高电平保持60us
????????while(TMDAT==0)??????????//判断DS18B20是否发出低电平信号
????????{
????????????delay=210;????????????//DS18B20响应,延时420us
????????????while(--delay);
????????????if(TMDAT)?????????????//DS18B20发出高电平初始化成功,返回
????????????{
????????????????flag=1;?????????????//DS18B20初始化成功标志
???????????????
???????????????//初始化成功LED标志
????
????????????????break;
????????????}
????????}
????????if(flag)??????????????????//初始化成功,再延时480us,时序要求
????????{
????????????delay=240;
????????????while(--delay);
????????????break;
????????}
????}
}
//***********************获得温度子程序***************************************
//****************************************************************************
void?get_temperature()????????????//温度转换、获得温度子程序
{
????set_ds18b20();????????????????//初始化DS18B20
????write_ds18b20(0xcc);??????????//发跳过ROM匹配命令
????write_ds18b20(0x44);??????????//发温度转换命令
????disp_temp(tempint,tempdf);??????????????????//显示温度,等待AD转换
????set_ds18b20();
????write_ds18b20(0xcc);??????????//发跳过ROM匹配命令
????write_ds18b20(0xbe);??????????//发出读温度命令
????read_ds18b20();???????????????//将读出的温度数据保存到tempint和tempdf处
}
//***********************读DS18B20子程序***************************************
//****************************************************************************
void?read_ds18b20()
{
????uchar?delay,i,j,k,temp,temph,templ;
????float?wendu;
????j=3;??????????????????????????//读2位字节数据
????do
????{
????for(i=8;i》0;i--)??????????????//一个字节分8位读取
????{
????????temp》》=1;?????????????????//读取1位右移1位
????????TMDAT=0;??????????????????//数据线置低电平
????????delay=1;
??while(--delay);
????????TMDAT=1;??????????????????//数据线置高电平
????????delay=4;
????????while(--delay);??????????//延时8us
????????if(TMDAT)?????????????????//读取1位数据
????????????temp|=0x80;??????
????????delay=25;?????????????????//读取1位数据后延时50us
????????while(--delay);
????}
????if(j==3)??????????????????????
????????templ=temp;//读取的第一字节存templ
?????????
?????if(j==2)?
????????temph=temp;??//读取的第二字节存temph
????if(j==1)??
????????tempth=temp;???//读取的第3字节存tempth???TH的值?????????
????}while(--j);
????f=0;
????if((temph?&?0xf8)!=0x00)??//若温度为负的处理,对二进制补码的处理
????{
????????f=1;????//为负温度f置1
?
????????temph=~temph;
????????templ=~templ;????????
??k=templ+1;
????????templ=k;
????????if(k》255)
????????{
???????????temph++;
????????}
????}
????tempdf=templ?&?0x0f;??????????//将读取的数据转换成温度值,整数部分存tempint,小数部分存tempdf
?????????c=(tempdf*625);
?????????tempdf=c;
????templ》》=4;??//
????temph《《=4;?//转化成字节温度
????tempint=temph|templ;//两字节合并为一个字节
???//wendu=((temph*256)+templ)*0.0625;?
???//?tempdf=templ?&?0x0f;??????????//将读取的数据转换成温度值,整数部分存tempint,小数部分存tempdf
?????//?if?(tempdf&0x08==1)?a=8;
?????????//if?(tempdf&0x04==1)?b=4;
????????//?if?(tempdf&0x02==1)?c=2;
????????//?if?(tempdf&0x01==1)?d=1;
??//?tempdf=a+b+c+d;
????????//?c=tempdf*625;
?????????//tempdf=c;
????//templ》》=4;??//
????//《《=4;?//转化成字节温度
???//?tempint=temph|templ;//两字节合并为一个字节
}
//***********************写DS18B20子程序***************************************
//****************************************************************************
void?write_ds18b20(uchar?command)
{
????uchar?delay,i;
????for(i=8;i》0;i--)??????????????//将一字节数据一位一位写入
????{
????????TMDAT=0;??????????????????//数据线置低电平
????????delay=6;??????????????????//延时12us
????????while(--delay);
????????TMDAT=command&0x01;???????//将数据放置在数据线上
????????delay=25;?????????????????//延时50us
????????while(--delay);
????????command=command》》1;???????//准备发送下一位数据
????????TMDAT=1;??????????????????//发送完一位数据,数据线置高电平
????}
}
//***********************显示子程序***************************************
//****************************************************************************
void?disp_temp(?tempint,tempdf)
{
?????uchar?tempinth,tempintl,tempinbai,shifen,baifen,gefen,qianfen;
???????????
????
???????????int?x;
??????
??for(x=0;x《10;x++)??????????
???????????{???
?????if?(bb!=0)
?????{??tempint=settemp;
????????tempdf=0;
?????}?
?????else
?????{?tempinbai=tempint/100;?
????????tempinth=(tempint%100)/10;?????????
????????tempintl=tempint%10;?????????//整数取模
???????????gefen=tempdf/1000;
???????????shifen=tempdf%1000/100;?
???????????baifen?=tempdf%100/10;?
???????????qianfen=tempdf%10;?//小数取模
?????}
????
???if?(f==0)
???{?
??
????????????P0=display1;?//符号位
??????????????P2=ledmap;
?????}
??else?
??{
????????????P0=display1;?//符号位
??????????????P2=ledmap;
??}
???????????delayms(2);
????????P0=display2;?
??????????????P2=ledmap;??//开百位???????????
???????????delayms(2);
???????????P0=display3;??
??????????????P2=ledmap;//开十位???????????????????
???????????delayms(2);
??????????P0=display4;
?????????????P2=ledmap1;?//开个位?
???????????delayms(2);
??????????P0=display5;
?????????????P2=ledmap;//开个分位??
??????????delayms(2);
????????P0=display6;?
?????????????P2=ledmap;?//开十分位
??????????delayms(2);
???????P0=display7;
????????????P2=ledmap;?//开百分位??
??????????delayms(2);
?????????P0=display8;??
????????????P2=ledmap;//开千分位????????????????
???????????
??????????}
???????
??????}
?
//***********************延时count?ms子程序***************************************
//****************************************************************************
void?delayms(uchar?count)??//延时count?ms子程序
{
????uchar?i,j;
????do
????{
????????for(i=5;i》0;i--)
????????for(j=98;j》0;j--);
????}while(--count);
}
//***********************键盘扫描子程序***************************************
//****************************************************************************
void?keyscan()??//键盘扫描???????????????
??{
????
????if(set==0)
????{?
???????delayms(1);
????}
?????????if(set==0)
????{??
?????
?????bb++;??????
?????????????????while(!set);?//循环在此?非0=1?
????}?
??????????if(bb==1)
????????{??
??????
???????
?????????if(up==0)
?????{
?????delayms(1);
??????}
??????if(up==0)?
??????{???
??????
??????????????????????disp_temp(settemp);
????????if(settemp《125)
?????????????{settemp++;}
???????while(!up)//非0=1???????
??????????????????{
???????disp_temp(settemp);
??????}
????????????????}
??????????if(down==0)
???????{
????????delayms(1);
???????}
???????if(down==0)?
???????{??
???????????????disp_temp();
??????if(settemp!=0)?//不等于0为真执行
?????????{
??????settemp--;
???????while(!down)?//?down为(非0=1)循环执行?????????
?????????{
?????????disp_temp(settemp);
???????}
??????}
????????}
????????????????}
????
????????????if(bb==2)
?????????????{bb=0;
???????set_ds18b20();????????????????//初始化DS18B20
???????write_ds18b20(0xcc);??????????//发跳过ROM匹配命令
???????write_ds18b20(0x4e);??????????//发温度转换命令
???????write_ds18b20(settemp);????????//写TH?3
????//write_ds18b20(settemp);???写到TL??4
???//?write_ds18b20(settemp);????写分辨率??5???
???????set_ds18b20();????????????????//初始化DS18B20
???????write_ds18b20(0xcc);??????????//发跳过ROM匹配命令
??????write_ds18b20(0x48);?
}}
void?main()
{?????set_ds18b20();
?????write_ds18b20(0xcc);??????????//发跳过ROM匹配命令
?????write_ds18b20(0xbe);??????????//发出读温度命令
?????read_ds18b20();???????????????//将读出的数据
?????settemp=tempth;????????????????//将TH读到单片机
?????SP=0x60;?????????????????????//设置堆栈指针
??bb=0;
??led=0;
?????while(1)
?????{??????
???if(bb==0)
?????{?????keyscan();
????????????get_temperature();???????//获得温度
?????}
???
?????????disp_temp(tempint,tempdf);?????????????//显示温度
?????}
}
好编写啊,1.DS18B20采样 2.提取数据 3.UART传输。
给你点代码,自己参考下。
#include《reg52.h》
#define uint unsigned int
#define uchar unsigned char
sbit dq=P1^5;
void sdelay(unsigned int i)
{
while(i--);
}
ds18b20on(void)//ds18b20初始化
{
uchar x=0;
dq=1;
sdelay(8);
dq=0;
sdelay(80);
dq=1;
sdelay(14);
sdelay(20);
}
//读一个字节
readds18b20(void)
{
uchar i=0,dat=0;
for(i=8;i》0;i--)
{
dq=0;
dat》》=1;
dq=1;
if(dq)
dat|=0x80;
sdelay(4);
}
return(dat);
}
//写一个字节
writeds18b20(uchar dat)
{
uchar i=0;
for(i=8;i》0;i--)
{
dq=0;
dq=dat&0x01;
sdelay(5);
dq=1;
dat》》=1;
}
}
//读取温度
readtemperature(void)
{
uchar a=0,b=0;
uint t=0;
float tt=0;
ds18b20on();
writeds18b20(0xCC);//跳过ROM
writeds18b20(0x44);//开启温度转换
ds18b20on();
writeds18b20(0xCC);
writeds18b20(0xBE);//读暂存器
a=readds18b20();
b=readds18b20();
t=b;
t《《=8;
t=t|a;
tt=t*0.0625;
t= tt*10+0.5;
return(t);
}
这部分是DS18B20的采样:
t=b;
t《《=8;
t=t|a;
tt=t*0.0625;
t= tt*10+0.5;
return(t);
这部分的处理是得到十进制的温度数据。
如果你想直接得到2个字节数据(a=readds18b20();b=readds18b20();
),那么刚才那段可以不处理,删掉!
然后是串口部分:
#include 《reg52.h》
#include 《string.h》
#define uchar unsigned char
#define uint unsigned int
uchar receive; //串口接收数据存放
uchar t=0;
void delay(uint z)//延时子程序
{
uint x,y;
for(x=10;x》0;x--)
for(y=z;y》0;y--); //z*10 us
}
void init()//串口初始化
{
SCON=0x50; //SCON:串行口工作方式1, 8-bit UART,允许串行接收位(REN=1)
TMOD=0x20; //TMOD:定时器1,方式2,8位自动重装方式
PCON=0x80; //SMOD=1;(将串口传送的波特率加倍)
TH1=0xfa; //Baud:9600 fosc=11.0592MHz
TL1=0xfa;
TR1=1; //启动定时器/计数器1运行
//IE=0x90; //EA=1,ES=1允许总中断,允许串口中断
EA=1;//开总中断
ES=1; //开串口中断
}
void send_char(uchar a)//向串口发送一个字符
{
SBUF=a; //发送数据给“串口调试助手”接收窗口
while(TI==0);//等待发送完,TI置1
TI=0; //清零TI为发送中断标志
}
void send_string(uchar *str) //向串口发送一个字符串,strlen为该字符串长度
{
uint k=0;
do
{
send_char(*(str + k));
k++;
} while(k《strlen(str));
t=0;//发送完毕,准备接收
}
//串口接收中断函数,并将数据放入预存放数组里,每收到一个字符中断一次
void serial() interrupt 4 using 3
{
if(RI==1)//RI为接受中断标志,可能是发送产生的中断
{
uchar a;
RI=0;//接受中断标志软件清零
P0=SBUF;//把收到的缓存数据赋给P0口
a=SBUF;//把缓存在单片机的数据给a
//send_char(a);
receive=a;//将接受数据放入预置数组
send_string(receive);//将收到的数据发送回去,给P0口&显示在“串口调试助手”接收框
}
}
/*******************************主函数*******************************************/
void main()
{
init(); //串口初始化
delay(1);
// send_string();//利用串口发送字符串
while(1);
}
这个是串口收发程序,收什么发什么,那么我们修改一下,把我们的数据传出去。
void main()
{
uchar aa;//用于发数据
uint bb=0;//用于保存温度数据
init(); //串口初始化
ds18b20on(); //ds18b20初始化
bb=readtemperature();//温度采样
aa=bb; //取温度数据低字节
aa=bb》》8; //取温度数据高字节
send_string(aa);//利用串口发送字符串
while(1);//这里只循环了一次,你可以做修改
}
基本思路就这样,程序要你自己修改一部分,有问题Hi我!
你好!
蓝牙通讯,是在串口通讯基础之上完成的,
先完成单片机驱动温度传感器,实现DS18B20的读取,
再进行串口通讯,实现和电脑串口收发数据,
加上蓝牙模块,实现无线传输
相关tag:ds18b20代码
本站部分资源来源于网络,如果侵犯了您的权益,请联系我们删除1354090129@qq.com