STM32系列第29篇--DS18B20
扫描二维码
随时随地手机看文章
特点:
独特的单总线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯。大大提高了系统的抗干扰性。
测温范围 -55℃~+125℃,精度为±0.5℃。
支持多点组网功能,多个DS18B20可以并联在唯一的三线上,最多只能并联8个,实现多点测温,如果数量过多,会使供电电源电压过低,从而造成信号传输的不稳定。
工作电源: 3.0~5.5V/DC (可以数据线寄生电源)。
测量结果以9~12位数字量方式串行传送。
复位脉冲 & 应答信号单总线上的所有通信都是以初始化序列开始。主机输出低电平,保持低电平时间至少480us,以产生复位脉冲。接着主机释放总线,4.7K的上拉电阻将单总线拉高,延时15~60us,并进入接收模式(Rx)。接着DS18B20拉低总线60~240us,以产生低电平应答脉冲。
写时序写时序包括写0时序和写1时序。所有写时序至少需要60us,且在2次独立的写时序之间至少需要1us的恢复时间,两种写时序均起始于主机拉低总线。
写1:主机输出低电平,延时2us,然后释放总线,延时60us。
写0:主机输出低电平,延时60us,然后释放总线,延时2us。
单总线器件仅在主机发出读时序时,才向主机传输数据,所以,在主机发出读数据命令后,必须马上产生读时序,以便从机能够传输数据。
读取过程复位→发SKIP ROM命令(0XCC)→发开始转换命令(0X44)→延时→复位→发送SKIPROM命令(0XCC)→发读存储器命令(0XBE)→连续读出两个字节数据(即温度)→结束。
转化后得到的12位数据,存储在18B20的两个8比特的RAM中,二进制中的前面5位是符号位,如果测得的温度大于0, 这5位为0,只要将测到的数值乘于0.0625即可得到实际温度;如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际 温度。 例如+125℃的数字输出为07D0H,,-25.0625℃的数字输出为FE6FH。
CODE://ds18b20.c#include"ds18b20.h"#include"delay.h"//复位DS18B20voidDS18B20_Rst(void){DS18B20_IO_OUT();//SETPG11OUTPUTDS18B20_DQ_OUT=0;//拉低DQdelay_us(750);//拉低750usDS18B20_DQ_OUT=1;//DQ=1delay_us(15);//15US}//等待DS18B20的回应//返回1:未检测到DS18B20的存在//返回0:存在u8DS18B20_Check(void){u8retry=0;DS18B20_IO_IN();//SETPG11INPUTwhile(DS18B20_DQ_IN&&retry<200){retry++;delay_us(1);};if(retry>=200)return1;elseretry=0;while(!DS18B20_DQ_IN&&retry<240){retry++;delay_us(1);};if(retry>=240)return1;return0;}//从DS18B20读取一个位//返回值:1/0u8DS18B20_Read_Bit(void){u8data;DS18B20_IO_OUT();//SETPG11OUTPUTDS18B20_DQ_OUT=0;delay_us(2);DS18B20_DQ_OUT=1;DS18B20_IO_IN();//SETPG11INPUTdelay_us(12);if(DS18B20_DQ_IN)data=1;elsedata=0;delay_us(50);returndata;}//从DS18B20读取一个字节//返回值:读到的数据u8DS18B20_Read_Byte(void){u8i,j,dat;dat=0;for(i=1;i<=8;i++){j=DS18B20_Read_Bit();dat=(j<<7)|(dat>>1);}returndat;}//写一个字节到DS18B20//dat:要写入的字节voidDS18B20_Write_Byte(u8dat){u8j;u8testb;DS18B20_IO_OUT();//SETPG11OUTPUT;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb){DS18B20_DQ_OUT=0;//Write1delay_us(2);DS18B20_DQ_OUT=1;delay_us(60);}else{DS18B20_DQ_OUT=0;//Write0delay_us(60);DS18B20_DQ_OUT=1;delay_us(2);}}}//开始温度转换voidDS18B20_Start(void){DS18B20_Rst();DS18B20_Check();DS18B20_Write_Byte(0xcc);//skipromDS18B20_Write_Byte(0x44);//convert}//初始化DS18B20的IO口DQ同时检测DS的存在//返回1:不存在//返回0:存在u8DS18B20_Init(void){GPIO_InitTypeDefGPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);//使能PORTG口时钟GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;//PORTG.11推挽输出GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOG,&GPIO_InitStructure);GPIO_SetBits(GPIOG,GPIO_Pin_11);//输出1DS18B20_Rst();returnDS18B20_Check();}//从ds18b20得到温度值//精度:0.1C//返回值:温度值(-550~1250)shortDS18B20_Get_Temp(void){u8temp;u8TL,TH;shorttem;DS18B20_Start();//ds1820startconvertDS18B20_Rst();DS18B20_Check();DS18B20_Write_Byte(0xcc);//skipromDS18B20_Write_Byte(0xbe);//convertTL=DS18B20_Read_Byte();//LSBTH=DS18B20_Read_Byte();//MSBif(TH>7){TH=~TH;TL=~TL;temp=0;//温度为负}elsetemp=1;//温度为正tem=TH;//获得高八位tem<<=8;tem+=TL;//获得底八位tem=(float)tem*0.625;//转换if(temp)returntem;//返回温度值elsereturn-tem;}//main.c#include"led.h"#include"delay.h"#include"key.h"#include"sys.h"#include"lcd.h"#include"usart.h"#include"ds18b20.h"intmain(void){u8t=0;shorttemperature;delay_init();//延时函数初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级uart_init(115200);//串口初始化为115200LED_Init();//初始化与LED连接的硬件接口LCD_Init();//初始化LCDPOINT_COLOR=RED;//设置字体为红色LCD_ShowString(30,50,200,16,16,"WarShipSTM32");LCD_ShowString(30,70,200,16,16,"DS18B20TEST");LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(30,110,200,16,16,"2015/1/16");while(DS18B20_Init())//DS18B20初始化{LCD_ShowString(30,130,200,16,16,"DS18B20Error");delay_ms(200);LCD_Fill(30,130,239,130+16,WHITE);delay_ms(200);}LCD_ShowString(30,130,200,16,16,"DS18B20OK");POINT_COLOR=BLUE;//设置字体为蓝色LCD_ShowString(30,150,200,16,16,"Temp:.C");while(1){if(t%10==0)//每100ms读取一次{temperature=DS18B20_Get_Temp();if(temperature<0){LCD_ShowChar(30+40,150,'-',16,0);//显示负号temperature=-temperature;//转为正数}elseLCD_ShowChar(30+40,150,'',16,0);//去掉负号LCD_ShowNum(30+40+8,150,temperature/10,2,16);//显示正数部分LCD_ShowNum(30+40+32,150,temperature%10,1,16);//显示小数部分}delay_ms(10);t++;if(t==20){t=0;LED0=!LED0;}}}