蓝桥杯模块学习13——DS18B20(深夜学习——单片机)

一、硬件电路:

  1. DS18B20内部电路:

(客观题可能会考,但是编程时由于我们直接输入命令让模块自己工作,所以我们并不需要了解该电路)

我们需要了解的是三部分:64位ROM、暂存器、EEPROM存储器

(1)64位ROM:存放地址码,其中包括了8位CRC校验码(由CRC发生器产生)+48位序列号(每个产品不同)+8位系列码(DS18B20都为0x28)

(2)暂存器:

(3)EEPROM存储器:包括TH、TL寄存器和配置寄存器CR

TH,TL:规定最高温度和最低温度

CR:规定了分辨率与最大转换时间

  1. 蓝桥杯板子上的电路

该电路可以分为两部分,一部分为1,3脚的供电部分;一部分为2接上拉电阻以满足漏极开路门输入输出

二、命令:

  1. ROM命令:

(由于板子上只有一个DS18B20,所以只需要记住0xCC跳过ROM操作就行)

2.功能命令:(重要)

三、具体操作步骤:(每发一个命令都要按照这个步骤,而不能连续发功能命令)

复位——》ROM命令——》功能命令

  1. 复位:

(1)首先将总线拉低480us,产生复位脉冲,然后释放总线(拉高电平)。

(2)这时DS8B20检测到请求之后,会将总线拉低60~240us,来表示应答,最后释放总线。

(3)单片机可以选择在第一次释放总线后60~240us去读取总线的电平,如果是低电平,那么表示初始化成功(基本不用这个操作)

  1. 写操作:(低位先行)

(1)写“0”操作:将总线拉低60到120us,再释放总线

(2)写“1”操作:将总线拉低小于15us,再释放总线

(3)一个写操作总时间必须大于60us,每两个写操作之间必须间隔1us

  1. 读操作:(低位先行)

(1)首先将总线拉低然后释放,让DS18B20知道我们要开始读数据了,然后DS18B20就会开始传数据

(2)然后我们就要在15us内将总线传输的数据读走

(3)一个读操作总时间大于60us,每两个读操作之间间隔1us

四、DS18B20实验:

  1. 我根据上面手册中的时序写了一份代码,但是实际的时序可能并不相同,我还是建议可以自己写一下收获会更多,但是比赛的时候建议直接用官方给的代码(写的不好仅供参考)

(1)公共函数:

#ifndef _PUBLIC_H
#define _PUBLIC_H#include "STC15F2K60S2.H" #define u8 unsigned char
#define u16 unsigned intvoid Delay_1ms(u16 num);
void Close_All(void);
void Delay_10us(u16 num);
#endif
#include "Public.h"
// 延时函数(最小约1ms@12MHz)
void Delay_1ms(u16 num)
{unsigned int i;while(num--)for(i=0; i<628; i++);
}/*输入变量:无输出变量:无功能:关闭蜂鸣器和继电器
*/
void Close_All(void)
{//关闭蜂鸣器和继电器P0 = 0x00;P2 = (P2 & 0x1f) | 0xA0;P2 &= 0x1f;//关闭LED灯P0 = 0xff;P2 = (P2 & 0x1F) | 0x80;P2 &= 0x1f;    
}void Delay_10us(u16 num)
{u16 i;while(num--)for(i=0; i<5; i++);
}

(2)主函数:

// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "Public.h"
#include "stdio.h"u8 SEG_COT[9];
u8 SEG_Code[8];
u8 SEF_POS = 0;
u16 SEG_delay;
void SEG_TSL(u8 *input,u8 *output);
void SEG_Show(u8 num,u16 PIS);
void Timer_0_Init(u16 time);
void SEG_Proc();sbit DQ = P1^4;  
void DS18B20_Init();
void DS18B20_Write(u8 w_dat);
u8 DS18B20_Read();
// 主函数
void main(void)
{Close_All();    Timer_0_Init(1000);while(1){ SEG_Proc();}
}void SEG_Proc()
{u8 LSB,MSB;u16 t_temp;if(SEG_delay)return;SEG_delay = 1;DS18B20_Init();DS18B20_Write(0xCC);//转换温度DS18B20_Write(0x44);DS18B20_Init();DS18B20_Write(0xCC);//读取暂存器DS18B20_Write(0xBE);//温度数据低八位LSB = DS18B20_Read();//温度数据高八位MSB = DS18B20_Read();t_temp = LSB | (MSB<<8);if((t_temp & 0xf800) == 0)//符号位为0sprintf(SEG_COT, "    %2.2f", t_temp*0.0625);else if((t_temp | 0x07ff) == 1)//符号位为1sprintf(SEG_COT, "-%04.2f", ((~t_temp)+1)*0.0625);//负数的补码要进行取反加一操作SEG_TSL(SEG_COT,SEG_Code);
}void DS18B20_Init()
{u8 b_temp=1,time_out=10;while(b_temp && ((time_out--) != 0)){DQ = 0;Delay_us(48);DQ = 1;Delay_us(5);b_temp = DQ;}Delay_us(20);
}void DS18B20_Write(u8 w_dat)
{u8 i=0;for(i=0;i<8;i++){DQ = 0;Delay_us(1);DQ = w_dat&0x01;Delay_us(5);DQ = 1;w_dat >>= 1;}
}
u8 DS18B20_Read()
{u8 r_dat=0;u8 i=0;for(i=0;i<8;i++){DQ = 0;r_dat >>= 1;DQ = 1;Delay_us(1);if(DQ){r_dat |= 0x80;}       Delay_us(5);}return r_dat;
}/***************************数码管*****************************/
/*输入变量:input,输入字符数组;output:输出16进制数数组输出变量:无功能:将字符串转化为对应数码管显示的16进制数注意:记得定义数组——u8 SEG_COT[9];u8 SEG_Code[8];
*/
void SEG_TSL(u8 *input,u8 *output)
{u8 i=0,temp=0,j=0;for(i=0;i<8;i++,j++){switch(input[j]){case '0': temp = 0xc0; break;case '1': temp = 0xf9; break;case '2': temp = 0xa4; break;case '3': temp = 0xb0; break;case '4': temp = 0x99; break;case '5': temp = 0x92; break;case '6': temp = 0x82; break;case '7': temp = 0xf8; break;case '8': temp = 0x80; break;case '9': temp = 0x90; break;case 'A': temp = 0x88; break;case 'B': temp = 0x83; break;case 'C': temp = 0xc6; break;case 'D': temp = 0xA1; break;case 'E': temp = 0x86; break;case 'F': temp = 0x8E; break;case 'H': temp = 0x89; break;case 'L': temp = 0xC7; break;case 'N': temp = 0xC8; break;case 'P': temp = 0x8c; break;case 'U': temp = 0xC1; break;case '-': temp = 0xbf; break;case ' ': temp = 0xff; break;default: temp = 0xff;}if(input[j+1] == '.'){temp &= 0x7f;j++;}output[i] = temp;}
}/*输入变量:num,要显示数据;PIS,显示位置,从左到右分别为0-7输出变量:无功能:操作138译码器,4-7分别对应Y4-Y7,其余都会使译码器不起作用注意:需要把存放从1-f对应的16进制数数组也移植
*/
void SEG_Show(u8 num,u16 PIS)
{//消影P0 = 0xff;P2 = (P2 & 0x1f) | 0xE0;P2 &= 0x1f;//改变显示位置P0 = 0x01<
  1. 根据官方写的时序:

(1)官方给的库函数

#ifndef __ONEWIRE_H
#define __ONEWIRE_H#include "Public.h"sbit DQ = P1^4;  
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
#endif
#include "onewire.h"//单总线内部延时函数
void Delay_OneWire(unsigned int t) 
{unsigned char i;while(t--){for(i=0;i<8;i++);}
}//单总线写操作
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);
}//单总线读操作
unsigned char Read_DS18B20(void)
{unsigned char i;unsigned char dat;for(i=0;i<8;i++){DQ = 0;dat >>= 1;DQ = 1;if(DQ){dat |= 0x80;}        Delay_OneWire(5);}return dat;
}//DS18B20初始化
bit init_ds18b20(void)
{bit initflag = 0;DQ = 1;Delay_OneWire(12);DQ = 0;Delay_OneWire(80);DQ = 1;Delay_OneWire(10); initflag = DQ;     Delay_OneWire(5);return initflag;
}

(2)根据官方给的库函数写的主函数

// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "Public.h"
#include "stdio.h"
#include "onewire.h"
u8 SEG_COT[9];
u8 SEG_Code[8];
u8 SEF_POS = 0;
u16 SEG_delay;
void SEG_TSL(u8 *input,u8 *output);
void SEG_Show(u8 num,u16 PIS);
void Timer_0_Init(u16 time);
void SEG_Proc();// 主函数
void main(void)
{Close_All();    Timer_0_Init(1000);while(1){ SEG_Proc();}
}
u16 TEMP_Proc();
void SEG_Proc()
{float temper;u16 t_temp;if(SEG_delay)return;SEG_delay = 1;t_temp = TEMP_Proc();if(!(t_temp & 0xf800))//符号位为0{temper = t_temp*0.0625;sprintf(SEG_COT, "    %2.2f", temper);}else if(t_temp | 0x07ff)//符号位为1{temper = ((~t_temp)+1)*0.0625;sprintf(SEG_COT, "-%04.2f", temper);}SEG_TSL(SEG_COT,SEG_Code);
}
u16 TEMP_Proc()
{u8 LSB,MSB;init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0x44);init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0xbe);LSB = Read_DS18B20();MSB = Read_DS18B20();init_ds18b20();    return LSB | (MSB<<8);
}
/***************************数码管*****************************/
/*输入变量:input,输入字符数组;output:输出16进制数数组输出变量:无功能:将字符串转化为对应数码管显示的16进制数注意:记得定义数组——u8 SEG_COT[9];u8 SEG_Code[8];
*/
void SEG_TSL(u8 *input,u8 *output)
{u8 i=0,temp=0,j=0;for(i=0;i<8;i++,j++){switch(input[j]){case '0': temp = 0xc0; break;case '1': temp = 0xf9; break;case '2': temp = 0xa4; break;case '3': temp = 0xb0; break;case '4': temp = 0x99; break;case '5': temp = 0x92; break;case '6': temp = 0x82; break;case '7': temp = 0xf8; break;case '8': temp = 0x80; break;case '9': temp = 0x90; break;case 'A': temp = 0x88; break;case 'B': temp = 0x83; break;case 'C': temp = 0xc6; break;case 'D': temp = 0xA1; break;case 'E': temp = 0x86; break;case 'F': temp = 0x8E; break;case 'H': temp = 0x89; break;case 'L': temp = 0xC7; break;case 'N': temp = 0xC8; break;case 'P': temp = 0x8c; break;case 'U': temp = 0xC1; break;case '-': temp = 0xbf; break;case ' ': temp = 0xff; break;default: temp = 0xff;}if(input[j+1] == '.'){temp &= 0x7f;j++;}output[i] = temp;}
}/*输入变量:num,要显示数据;PIS,显示位置,从左到右分别为0-7输出变量:无功能:操作138译码器,4-7分别对应Y4-Y7,其余都会使译码器不起作用注意:需要把存放从1-f对应的16进制数数组也移植
*/
void SEG_Show(u8 num,u16 PIS)
{//消影P0 = 0xff;P2 = (P2 & 0x1f) | 0xE0;P2 &= 0x1f;//改变显示位置P0 = 0x01<


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章