蓝桥杯模块DS18B20温度传感器Part_2
发布日期:2021-07-01 03:12:41 浏览次数:2 分类:技术文章

本文共 5219 字,大约阅读时间需要 17 分钟。

   九层妖塔 起于垒土

在这里插入图片描述

蓝桥杯模块DS18B20温度传感器Part_2

一、初始化

1、初始化时序图:

在这里插入图片描述

2、相关延时时间的计算:

AB:主机下拉500us发送存在脉冲。

B:主机释放总线并进入接收模式(RX)。释放总线即DQ=1
BC:DS18B20等待时间。15us<BC<60us
CD:DS18B20发送存在脉冲。60us<CD<240us
T:主机读取DQ数据线电平状态时刻。
BT B C m a x BC_{max} BCmax< B T BT BT< B C m i n BC_{min} BCmin+ C D m i n CD_{min} CDmin ,即60us< B T BT BT<75us, B T BT BT取65us
TE:取500us

3、官方底层驱动代码:

//DS18B20初始化bit init_ds18b20(void){
bit initflag = 0; DQ = 1; Delay_OneWire(12); DQ = 0; Delay_OneWire(80); // 延时大于480us DQ = 1; Delay_OneWire(10); // 14 initflag = DQ; // initflag等于1初始化失败 Delay_OneWire(5); return initflag;}

4、Template:

bit DS18B20_Init(void){
bit presence = 0; //返回值,DS18B20返回存在脉冲为1 DQ = 1; //为主机拉低总线做准备 Delay5us(); //稍加延时使总线电平稳定 DQ = 0; //主机下拉500us,发送存在脉冲 Delay500us(); DQ = 1; //主机释放单总线 Delay65us(); //等待DS18B20 presence = !DQ; Delay500us(); //保持时序完整 return presence;}

5、Notes:

 ●按照官方底层驱动所要求的12MHz,Debug了多次,例程延时所测偏离正常。

 ●presence = !DQ;存在presence为1即真。
 ●函数名DS18B20_Init便于在Functions栏中快速查找。

二、写时序/读时序

1、读/写时序图:

在这里插入图片描述

3、官方底层驱动代码:

//通过单总线向DS18B20写一个字节void Write_DS18B20(unsigned char dat){
unsigned char i; for(i=0;i<8;i++) {
DQ = 0; DQ = dat&0x01; Delay_OneWire(5); DQ = 1; dat >>= 1; } Delay_OneWire(5);}//从DS18B20读取一个字节unsigned char Read_DS18B20(void){
unsigned char i; unsigned char dat;// unsigned char index = 0; for(i=0;i<8;i++) {
DQ = 0; dat >>= 1; DQ = 1; Delay_us(); if(DQ) {
dat |= 0x80; } Delay_OneWire(5); } return dat;}

4、Template:

//---------------------------------------向DS18B20写一个字节-------------------------//void DS18B20_Write(uchar dat){
uchar i; for(i=0;i<8;i++) {
DQ=0; //下拉 DQ=dat&0X01; //写入一位数据 Delay65us(); //保持时序完整 DQ=1; //释放总线 dat >>=1; } Delay65us(); //保持时序完整}//--------------------------------------从DS18B20读一个字节----------------------------//uchar DS18B20_Read(void){
uchar i; uchar dat=0; for(i=0;i<8;i++) {
DQ=0; //主机拉低总线 dat >>=1; //右移兼延时,第一次移位无效 DQ=1; //释放总线 Delay5us();//稍加延时使总线电平稳定 if(DQ==1) {
dat |=0X80; } Delay65us();//保持时序完整 } return dat;}

5、Notes:

 ●读时序中将返回值uchar dat=0;

○在函数调用时对自动变量赋初值,每调用一次函数重新给一次初值。

○若在定义时不赋初值,自动变量的初值不确定。每次函数调用结束后存储单元已释放,下次调用时又重新另分配存储单元,而所分配的单元中的内容是不可知的。

 ●读时序中Delay5us();//稍加延时使总线电平稳定。释放总线后,若读到的是1,则DQ线会被上拉电阻拉高,从0到1需要跨过阈值需要一段时间。按照芯片手册要求尽量在15us后端取检测。

三、DS18B20温度采集函数

1、Template:

//-------------------------------------DS18B20温度采集函数---------------------------//uint DS18B20_get_Temperature(void){
uint low,high; uint Temp=0; DS18B20_Init(); //初始化 DS18B20_Write(0XCC); //跳过ROM DS18B20_Write(0X44); //转换温度 DS18B20_Init(); //初始化 DS18B20_Write(0XCC); //跳过ROM DS18B20_Write(0XBE); //读暂存器 low = DS18B20_Read(); //低字节,16位温度低8位,Byte 0 high = DS18B20_Read();//高字节,16位温度高8位, Byte 1 Temp = (high<<8)+(low&0X00FF); return Temp;}

2、Notes:

 ●uint low,high;官方例程中将其定义为uchar,并且也进行了high<<8操作,若使用uchar在调用子函数之初就开辟了8位的内存地址,再进行左移,感觉会数据溢出。但是调试时并没有发生错误。

 ●uint Temp=0;low&0X00FF
 ●返回值Temp为16位无符号整型。
 ●12位分辨率的精度位0.0625,最大转换时间为750ms。写入DS18B20_Write(0X44); //转换温度开始温度转换后,就由DS18B20的相关硬件部分去执行温度转换,转换完成后存放在暂存器的低两位字节中;若不进行初始化直接读取时序,如果DS18B20正在温度转换过程中则返回0来响应,若转换完成则返回1。主机可以对DS18B20进行其他操作,由DS18B20的其他硬件部分响应;主机若对DS18B20进行其他操作,必须由初始化开始。
 在执行第二个初始化时,转换温度的命令已经写入DS18B20,虽然温度还未转换完成,但是单总线已经空闲,可以继续执行下边几乎不耗时的读暂存器命令。所以在上电之初,会出现短暂的85初始值。

四、DS18B20温度数码管段码转换函数

1、Template:

//-------------------------------------DS18B20温度数码管段码转换函数------------------------//void DS18B20_SEG(uint Temp){
yi=20; //符号位 er=(Temp>>4)/100; //百位 san=((Temp>>4)%100)/10; //十位 si=((Temp>>4)%10)+10; //个位 wu=((Temp&=0X000F)*625)/1000; //小数点后一位 liu=((Temp&=0X000F)*625)/100%10;//小数点后两位 qi=((Temp&=0X000F)*625)/10%10; //小数点后三位 ba=((Temp&=0X000F)*625)%10; //小数点后四位}

2、Notes:

 ●第一位为符号位,现写入全灭,可以通过判断Temp高四位确认正负。

 ●整数部分,加符号位共八位,可测温范围:-128~+127 。整数部分以(Temp>>4)为整体进行操作。虽然从暂存器读到的Tenp为16位二进制无符号整数,进行取余、除法运算时,右端的数为十进制,对于单片机(计算机)统一转换为二进制进行运算,同样在用户端为了便于理解可以理解为都是十进制
 ●小数部分以((Temp&=0X000F)*625)为整体进行操作。(Temp&=0X000F)的四位有效数值为的权值依次为 2 3 2^3 23, 2 2 2^2 22, 2 1 2^1 21, 2 0 2^0 20,若为二进制小数,小数点后四位小数权值依次为 2 − 1 2^{-1} 21, 2 − 2 2^{-2} 22, 2 − 3 2^{-3} 23, 2 − 4 2^{-4} 24,所以将(Temp&=0X000F)乘以 2 − 4 2^{-4} 24即0.0625,((Temp&=0X000F)*0.0625)即为小数点后四位(最多表示4位小数)。为了避免浮点数运算,可将十进制小数((Temp&=0X000F)*0.0625)扩大一万倍,即将十进制小数点左移四位,即为((Temp&=0X000F)*625)
 ●对小数部分,尝试了右移4位来代替除法运算,可是在这儿,数值却移出去了。最后一位出现了0,5以外的值。
 ●12位分辨率的精度位0.0625,所以数码管最后一位一定为0或5。
 ●若要求不显示四位小数,通过除法和求余的方法是将不显示的部分直接抹掉;若采用prinftsprinft指定小数位数输出,可以实现四舍五入。

五、主函数

uint Temp;  //DS18B20温度值,16位uchar SEG_Array[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, //数字0~9无点,索引值0~9 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10, //数字0~9有点,索引值(0~9)+10 0XFF, //灭灯,索引值20 0X86, //字母大写E,索引值21 0XC8, //字母小写n,索引值22 0XBF //中间一横,索引值23};void main(void){
All_Init(); //开发板初始化 while(1) {
Temp=DS18B20_get_Temperature(); //温度采集 DS18B20_SEG(Temp); //将16位Temp转换为段码 SEG_1_2(yi,er); SEG_3_4(san,si); SEG_5_6(wu,liu); SEG_7_8(qi,ba); SEG_Init(); }}

补:

  • 不同类型间数值的运算。
  • prinftsprinft的具体使用。
  • 将相对独立的模块化程序使用头文件和从c文件的形式在主c文件中调用。
  • Debug的具体使用规则。

转载地址:https://methadone-no1.blog.csdn.net/article/details/107971305 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:蓝桥杯MCU:IAP15F2K61S2中断
下一篇:蓝桥杯杂记C51

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年05月02日 13时37分38秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章