STM32第一篇 ------ DS18B20测温模块

目录

一、DS18B20模块简介

1、DS1820数字温度计

2、DS18B20模块特性  

3、工作原理

4、数据格式

5、功能命令集         

二、单总线通信的工作原理与使用方法      

1、单总线通信简介

2、硬件结构

3、命令序列

4、信号方式

三、程序设计

1、Ds1820s.c

2、Ds1820s.h

3、main.c

四、效果图


一、DS18B20模块简介

1、DS1820数字温度计

2、DS18B20模块特性  

        (1)单线接口仅需要一个端口引脚进行通讯(即单总线接口方式);    

        (2)无需外部器件;

        (3)测温范围:-55 ~ +125 ℃ ,以0.5℃递增;-67 ~ +257 ℉ ,以0.9 ℉ 递增;

        (4)温度以9为数字量读出;

        (5)温度数字量转换时间200ms (典型值);

        (6)零待机功耗 ;

        (7)分辨率调整范围:9 ~ 12 位;

        (8)用户可定义的非易失性温度报警设置 ;

        (9)报警搜索命令识别并标志超过程序限定温度(温度报警条件)的器件;

        (10)应用包括温度控制、工业系统、消费品、温度计或任何热感测系统。

3、工作原理

        (1)信号类型:复位脉冲、应答脉冲、写0、写1、读0和读1;(所有这些信号,除了应答脉冲以外,都由主机发出同步信号,并且发送所有的命令和数据都是字节的低位在前);

        (2)工作时序

                a、初始化时序

                主机发送复位脉冲后检测从机给主机返回的存在脉冲,检测到正确脉冲表明器件初始化 成功。

                主机输出产生复位脉冲(输出低电平保持时间至少480us),主机进入接收模式  (释放总线,4.7k上拉电阻将总线拉高,延时15 ~ 60 us ),低电平应答脉冲(等待拉低总线约240us内),然后由于上拉电阻作用(释放总线240us内)。

                b、写时序

                写时序“ 0 ” :输出低电平延时60us ,然后释放总线延时2us;

                写时序“ 1 ” :输出低电平延时2us,然后释放总线延时60us。

                c、读时序

               主机输出低电平延时2us,再转入输入模式延时12us。读取总线电平,再延时50us。

                单总线器件仅在主机发出读时序时,才向主机传输数据,所以,在主机发出读数据命令  后,必须马上产生读时序,以便从机能够传输数据。

                所有读时序至少需要60us。且在2次独立的读时序之间至少需要1us的恢复时间,每个读  时序都由主机发起,至少拉低总线1us。主机在读时序期间必须释放总线,并且在时序起始后的15us之内采样总线状态。

4、数据格式

        MSB最高位S为符号位,负温度S = 1 ,正温度S = 0;

        从而得到以下的表格

5、功能命令集         

二、单总线通信的工作原理与使用方法      

1、单总线通信简介

        单总线是一种半双工通信方式,采用单根信号线,既传输时钟,又传输数据,且数据传  输是双向的,具有节省I/O口线资源、结构简单、成本低廉、便于总线扩展和维护等优点。

        适用于单个主机系统,能够控制一个或多个从机设备。当只有一个从机位于总线上时,  系统可按照单节点系统操作;而当多个从机位于总线上时,则系统按照多节点系统操作。

2、硬件结构

        设备(主机或从机)通过一个漏极开路或三态端口,连接至该数据线,这样允许设备在不发送数据时释放数据总线,以便总线被其他设备所使用,单总线端口为漏极开路。

        总线要求外接一个约 5k 的上拉电阻。这样,单总线的闲置状态为高电平,不管什么原因,如果传输过程需要暂时挂起,且要求传输过程还能够继续的话,则总线必须处于空闲状态。位传输之间的恢复时间没有限制,只要总线在恢复期间处于空闲状态(高电平)。

3、命令序列

        典型的单总线命令序列如下:

                第一步:初始化;

                第二步:ROM命令(跟随需要交换的数据);

                第三步:功能命令(跟随需要交换的数据)。

        每次访问单总线器件,必须严格遵守这个命令序列,如果出现序列混乱,则单总线器件不会响应主机。但是,这个准则对于搜索ROM命令和报警搜索命令例外,在执行两者中任何一条命令之后,主机不能执行其后的功能命令,必须返回至第一步。

4、信号方式

        所有的单总线器件要求采用严格的通信协议 ,以保证数据的完整性。该协议定义了几种信号类型:复位脉冲、应答脉冲、写0、写1、读0和读1。所有这些信号,除了应答脉冲以外,都由主机发出同步信号。并且发送所有的命令和数据都是字节的低位在前,这一点与多数串行通信格式不同(多数为字节的高位在前)。

        具体分析见本文1-3-2 。

三、程序设计

1、Ds1820s.c

#include "ds18b20.h"
#include "stm32f10x.h"

 /**************************************************************************************
 * 描  述 : 配置DS18B20用到的I/O口
 * 入  参 : 无
 * 返回值 : 无
 **************************************************************************************/
static void DS18B20_GPIO_Config(void)
{		
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(DS18B20_CLK, ENABLE); 
															   
  GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;	
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出  
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
  GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
	
  GPIO_SetBits(DS18B20_PORT, DS18B20_PIN);	 //DS18B20数据引脚初始化配置为高电平输出
}

 /**************************************************************************************
 * 描  述 : 配置使DS18B20-DATA引脚变为输入模式
 * 入  参 : 无
 * 返回值 : 无
 **************************************************************************************/
static void DS18B20_Mode_IPU(void)
{
 	  GPIO_InitTypeDef GPIO_InitStructure;
	
	  GPIO_InitStructure.GPIO_Pin = DS18B20_PIN; 
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	  //上拉输入
	  GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
}

 /**************************************************************************************
 * 描  述 : 配置使DS18B20-DATA引脚变为输出模式
 * 入  参 : 无
 * 返回值 : 无
 **************************************************************************************/
static void DS18B20_Mode_Out_PP(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
															   
  GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;	

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   //推挽输出   
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
}

 /**************************************************************************************
 * 描  述 : 主机给从机发送复位脉冲
 * 入  参 : 无
 * 返回值 : 无
 **************************************************************************************/
static void DS18B20_Rst(void)
{
	DS18B20_Mode_Out_PP();     //主机设置为推挽输出 
	
	DS18B20_DATA_OUT(LOW);     //主机至少产生480us的低电平复位信号
	Delay_us(750);
	DS18B20_DATA_OUT(HIGH);   //主机在产生复位信号后,需将总线拉高
	Delay_us(15);   //从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
}

 /**************************************************************************************
 * 描  述 : 检测从机给主机返回的存在脉冲
 * 入  参 : 无
 * 返回值 : 0:成功   1:失败  
 **************************************************************************************/
static u8 DS18B20_Presence(void)
{
	u8 pulse_time = 0;
	
	DS18B20_Mode_IPU();    //主机设置为上拉输入
	
	/* 等待存在脉冲的到来,存在脉冲为一个60~240us的低电平信号 
	 * 如果存在脉冲没有来则做超时处理,从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
	 */
	while( DS18B20_DATA_IN() && pulse_time<100 )
	{
		pulse_time++;
		Delay_us(1);
	}	

	if( pulse_time >=100 )  //经过100us后,存在脉冲都还没有到来
		return 1;             //读取失败
	else                 //经过100us后,存在脉冲到来
		pulse_time = 0;    //清零计时变量
	
	while( !DS18B20_DATA_IN() && pulse_time<240 )  // 存在脉冲到来,且存在的时间不能超过240us
	{
		pulse_time++;
		Delay_us(1);
	}	
	if( pulse_time >=240 ) // 存在脉冲到来,且存在的时间超过了240us
		return 1;        //读取失败
	else
		return 0;
}

 /**************************************************************************************
 * 描  述 : 从DS18B20读取一个bit
 * 入  参 : 无
 * 返回值 : u8 
 **************************************************************************************/
static u8 DS18B20_Read_Bit(void)
{
	u8 dat;
	
	/* 读0和读1的时间至少要大于60us */	
	DS18B20_Mode_Out_PP();
	/* 读时间的起始:必须由主机产生 >1us <15us 的低电平信号 */
	DS18B20_DATA_OUT(LOW);
	Delay_us(10);
	
	/* 设置成输入,释放总线,由外部上拉电阻将总线拉高 */
	DS18B20_Mode_IPU();
	
	if( DS18B20_DATA_IN() == SET )
		dat = 1;
	else
		dat = 0;
	
	/* 这个延时参数请参考时序图 */
	Delay_us(45);
	
	return dat;
}

 /**************************************************************************************
 * 描  述 : 从DS18B20读一个字节,低位先行
 * 入  参 : 无
 * 返回值 : u8  
 **************************************************************************************/
u8 DS18B20_Read_Byte(void)
{
	u8 i, j, dat = 0;	
	
	for(i=0; i<8; i++) 
	{
		j = DS18B20_Read_Bit();		//从DS18B20读取一个bit
		dat = (dat) | (j<<i);
	}
	
	return dat;																																																																																
}

 /**************************************************************************************
 * 描  述 : 写一个字节到DS18B20,低位先行
 * 入  参 : u8
 * 返回值 : 无  
 **************************************************************************************/
void DS18B20_Write_Byte(u8 dat)
{
	u8 i, testb;
	DS18B20_Mode_Out_PP();
	
	for( i=0; i<8; i++ )
	{
		testb = dat&0x01;
		dat = dat>>1;		
		/* 写0和写1的时间至少要大于60us */
		if (testb)
		{			
			DS18B20_DATA_OUT(LOW);
			Delay_us(8);   //1us < 这个延时 < 15us
			
			DS18B20_DATA_OUT(HIGH);
			Delay_us(58);    //58us+8us>60us
		}		
		else
		{			
			DS18B20_DATA_OUT(LOW);  
			/* 60us < Tx 0 < 120us */
			Delay_us(70);
			
			DS18B20_DATA_OUT(HIGH);			
			/* 1us < Trec(恢复时间) < 无穷大*/
			Delay_us(2);
		}
	}
}

 /**************************************************************************************
 * 描  述 : 起始DS18B20
 * 入  参 : 无
 * 返回值 : 无  
 **************************************************************************************/
void DS18B20_Start(void)
{
	DS18B20_Rst();	           //主机给从机发送复位脉冲
	DS18B20_Presence();	       //检测从机给主机返回的存在脉冲
	DS18B20_Write_Byte(0XCC);		 // 跳过 ROM 
	DS18B20_Write_Byte(0X44);		 // 开始转换 
}

 /**************************************************************************************
 * 描  述 : DS18B20初始化函数
 * 入  参 : 无
 * 返回值 : u8
 **************************************************************************************/
u8 DS18B20_Init(void)
{
	DS18B20_GPIO_Config();   
	DS18B20_Rst();
	
	return DS18B20_Presence();
}

 /**************************************************************************************
 * 描  述 : 从DS18B20读取温度值
 * 入  参 : 无  
 * 返回值 : float 
 **************************************************************************************/
float DS18B20_Get_Temp(void)
{
	u8 tpmsb, tplsb;
	short s_tem;
	float f_tem;
	
	DS18B20_Rst();	   
	DS18B20_Presence();	 
	DS18B20_Write_Byte(0XCC);				/* 跳过 ROM */
	DS18B20_Write_Byte(0X44);				/* 开始转换 */
	
	DS18B20_Rst();
    DS18B20_Presence();
	DS18B20_Write_Byte(0XCC);				/* 跳过 ROM */
    DS18B20_Write_Byte(0XBE);				/* 读温度值 */
	
	tplsb = DS18B20_Read_Byte();		 
	tpmsb = DS18B20_Read_Byte(); 
	
	s_tem = tpmsb<<8;
	s_tem = s_tem | tplsb;
	
	if( s_tem < 0 )		/* 负温度 */
		f_tem = (~s_tem+1) * 0.0625;	
	else
		f_tem = (s_tem * 0.625);
	  
    //这样做的目的将小数点后第一位也转换为可显示数字
    //同时进行一个四舍五入操作。
	  
	return f_tem/10.0; 	
}




2、Ds1820s.h

#ifndef __DS18B20_H
#define	__DS18B20_H

#include "stm32f10x.h"
#include "delay.h"

#define HIGH  1
#define LOW   0

#define DS18B20_CLK     RCC_APB2Periph_GPIOB
#define DS18B20_PIN     GPIO_Pin_12                  
#define DS18B20_PORT		GPIOB 

//带参宏,可以像内联函数一样使用,输出高电平或低电平
#define DS18B20_DATA_OUT(a)	if (a)	\
					GPIO_SetBits(GPIOB,GPIO_Pin_12);\
					else		\
					GPIO_ResetBits(GPIOB,GPIO_Pin_12)
 //读取引脚的电平
#define  DS18B20_DATA_IN()	   GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)

typedef struct
{
	u8  temp_int;	 	//温度的整数部分
	u8  temp_deci;	 	//温度的小数部分
	u8  check_sum;	 	//校验和
		                 
}DS18B20_Data_TypeDef;

u8 DS18B20_Init(void);
float DS18B20_Get_Temp(void);

#endif /* __DS18B20_H */

3、main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Ds18b20.h"

uint8_t temp[17];
float temp_data = 0.0 ; 



void TempGetNum ()
{
	temp_data=DS18B20_Get_Temp();

	sprintf((char*)temp,"%4.2f",temp_data);
	OLED_ShowString(1,6,temp);
}
		
	
int main(void)
{
	/*模块初始化*/
	OLED_Init();		//OLED初始化

	OLED_ShowString(1,1,"Temp:");
	
	while (DS18B20_Init())
    {
        OLED_ShowString(1,1,"DS18B20 Error");
    }


	while (1)
	{
		TempGetNum();
		Delay_ms(500);
	}
}

四、效果图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值