stm32+DS18B20编程教学

stm32+DS18B20编程教学

一、前言

继上次发布的光照传感器讲解,这次继续讲一些简单的适合大学生学习使用的传感器。这次要讲的是一款温度传感器,想要完整代码工程的,可以在文章末尾的链接下载。

二、芯片介绍

1、简介
DS18B20是一款数字型温度传感器,这款传感器已经有长的历史了,驱动方式简单,很适合初学者使用,具体的我就不多说了,很多人应该都是知道这个传感器的。
2、引脚定义

引脚 名称 说明
1 GND 供电电源负极
2 DQ 数据输入输出引脚(和单片机IO口相连的时候一定要接上拉电阻)
3 VCC 供电电源正极

3、通讯方式
DS18B20用的是单总线方式,单片机给DQ引脚输出一定规则的时序信号即可配置和驱动DS18B20,同样的,单片机按照时序接收DS18B20发送的数据即可得到温度数据。
4、工作原理
DS18B20通过传感电路把温度转换成对应的电压信息,然后转换成数字信号,再把温度相关的数据存到自身的寄存器里面,单片机去读取这些数据,就可以知道当前的温度了。简单的说就是把模拟信号转换成数字信号,然后把这些数据存起来交给单片机,大概的原理是这样,如果你想继续深入了解,可以去找一下相关的文章,关于这方面的介绍有很多。

三、编程讲解

1、DS18B20驱动程序

//单片机只需要用一个普通的IO口和DS18B20的DQ引脚相连,然后控制这个IO口输出高低电平即可

//复位DS18B20
//作用:复位
void DS18B20_Rst(void)	   
{                 
	DS18B20_IO_OUT(); //把单片机的IO口配置为输出
    DS18B20_DQ_OUT=0; //拉低DQ
    delay_us(750);    //拉低750us,这个时间是根据DS18B20本身的规则定的,可以在数据手册找到相关介绍
    DS18B20_DQ_OUT=1; //拉高DQ
	delay_us(15);     //15US
}

//等待DS18B20的回应
//作用:检查单片机和DS18B20的通讯是否正常
//返回1:未检测到DS18B20的存在(可能是DQ引脚没有上拉电阻,通讯的时序不对,芯片损坏等原因)
//返回0:存在
u8 DS18B20_Check(void) 	   
{   
	u8 retry=0;
	DS18B20_IO_IN();//把IO口配置为输入,目的是为了接收DS18B20发过来的数据	 
    while (DS18B20_DQ_IN&&retry<200)//如果IO口是低电平,则是正常的,否则一直进while循环
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=200)
	{//通讯有误,返回1
		return 1;
	}
	else 
	{//正常
		retry=0;
	}
    while (!DS18B20_DQ_IN&&retry<240)//继续读取电平,如果IO口是高电平,则是正常的
	{
		retry++;
		delay_us(1);
	};
	if(retry>=240)
	{//通讯有误,返回1
		return 1;
	}	    
	return 0;//通讯正常,返回0
}

//从DS18B20读取一个位
//作用:读取一个位数据,重复调用该函数可以把温湿度数据读出来
//返回值:1/0
u8 DS18B20_Read_Bit(void) 			 // read one bit
{
  	u8 data;
	DS18B20_IO_OUT();//单片机输出一个由低到高的上升沿脉冲给DS18B20
 	DS18B20_DQ_OUT=0; 
	delay_us(2);
 	DS18B20_DQ_OUT=1; 
	DS18B20_IO_IN();//把IO口配置为输入,读取电平
	delay_us(12);
	if(DS18B20_DQ_IN)//如果是高电平,则DS18B20输出的数据是'1',否则为'0'
		data=1;
  	else 
  		data=0;	 
 	delay_us(50);           
  	return data;
}

//从DS18B20读取一个字节
//作用:连续读8个位,并合成一个字节数据
//返回值:读到的数据
u8 DS18B20_Read_Byte(void)    // read one byte
{        
    u8 i,j,dat;
    dat=0;
	for (i=1;i<=8;i++) 
	{
        j=DS18B20_Read_Bit();//连续调用8次
        dat=(j<<7)|(dat>>1);//每次读取到1个位的数据后左移1位,读取完8个位的数据之后就可以合成1个字节了
    }						    
    return dat;//返回合成的1字节数据
}

//写一个字节到DS18B20
//作用:写数据到DS18B20,调用这个函数可以发送指令控制DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(u8 dat)     
 {             
    u8 j;
    u8 testb;
	DS18B20_IO_OUT();//SET PA0 OUTPUT;
    for (j=1;j<=8;j++) 
	{
        testb=dat&0x01;//把传进来的这个数据的最高位提取出来
        dat=dat>>1;//dat的数据左移1位,作用是把次高位移到最高位
        if (testb) //如果最高位数据为'1'
        {
            DS18B20_DQ_OUT=0;// Write 1
            delay_us(2);                            
            DS18B20_DQ_OUT=1;//输出60us高电平,相当于告诉DS18B20要传的数据是'1'
            delay_us(60);             
        }
        else //如果最高位数据为'0'
        {
            DS18B20_DQ_OUT=0;//输出60us低电平,相当于告诉DS18B20要传的数据是'0'
            delay_us(60);             
            DS18B20_DQ_OUT=1;
            delay_us(2);                          
        }
    }
}

//开始温度转换
//作用:从DS18B20中读取温度数据
void DS18B20_Start(void)// ds1820 start convert
{   						               
  DS18B20_Rst();//复位   
  DS18B20_Check();//检查单片机和DS18B20的通讯是否正常	 
  DS18B20_Write_Byte(0xcc);//寻址总线上的所有从设备,详细说明可以参考数据手册ROM COMMANDS
  DS18B20_Write_Byte(0x44);//0x44命令为启动温度转换命令,详细说明可以参考数据手册ROM COMMANDS
} 
//初始化DS18B20的IO口DQ 同时检测DS18B20的存在
//返回1:不存在
//返回0:存在    	 
u8 DS18B20_Init(void)
{
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能PORTA口时钟 
 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;				//PORTA0 推挽输出
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		  
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);

 	GPIO_SetBits(GPIOA,GPIO_Pin_0);    //输出1

	DS18B20_Rst();//复位

	return DS18B20_Check();
}  
//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250) 
short DS18B20_Get_Temp(void)
{
    u8 temp;
    u8 TL,TH;
	short tem;
    //DS18B20_Start (); //开始采集温度
    DS18B20_Rst();//复位
    DS18B20_Check();//检查单片机和DS18B20通讯是否正常	 
    DS18B20_Write_Byte(0xcc);//寻址总线上的所有从设备,详细说明可以参考数据手册ROM COMMANDS
    DS18B20_Write_Byte(0xbe);//0x44命令为启动温度转换命令,详细说明可以参考数据手册ROM COMMANDS    
    TL=DS18B20_Read_Byte(); //读取数据低字节  
    TH=DS18B20_Read_Byte(); //读取数据高字节 
	    	  
    if(TH>7)
    {
        TH=~TH;
        TL=~TL; 
        temp=0;//温度为负  
    }
    else 
    {
    	temp=1;//温度为正	
    }  	  
    tem=TH;//获得高字节数据
    tem<<=8;//高字节位左移8位    
    tem+=TL;//左移的高8位加上低8位合成一个16位数据
    tem=(float)tem*0.625;//从DS18B20读取到的2个字节的数据还不是温度值,需要转换,转换公式参考数据手册     
	if(temp)
	{
		return tem; //返回温度值
	}
	else 
	{
		return -tem;   
	} 
} 

2、main函数

int main()
{  
	short temperature;    
	uart_init(115200);	 	//串口初始化为115200
	LED_Init();		  		//初始化与LED连接的硬件接口
	OLED_Init();            //OLED初始化
	OLED_Clear();           //OLED清屏
	while(DS18B20_Init())	//DS18B20初始化	
	{
    	OLED_ShowString(50,2,"error",12);//DS18B20通讯有问题
	}
	while(1)
	{	
	    //读取温度		
		temperature=DS18B20_Get_Temp();	
		if(temperature<0)//温度低于0
		{		
			OLED_ShowString(50,4,"-",16);   //显示负号
			temperature=-temperature;	    //转为正数
		}
		else //温度大于0
		{
			OLED_ShowString(50,4," ",16);	//不显示负号,也不显示正号
		}	 
		OLED_ShowCHinese(0,4,0);//显示中文字体“温”
		OLED_ShowCHinese(16,4,1);//显示中文字体“度”
		OLED_ShowString(32,4,":",16);
		OLED_ShowNum(60,4,temperature/10,2,16); //显示整数部分
		OLED_ShowString(80,4,".",16);
   		OLED_ShowNum(88,4,temperature%10,1,16);	//显示小数部分 
		OLED_ShowCHinese(100,4,9);//显示“℃”
	}

好了,关于这个传感器的介绍就到这里吧。
链接:https://pan.baidu.com/s/1pIcwctU0q1EWM7975JWrnQ ,提取码:bbhc
创作不易,希望你们尊重别人的劳动,点赞+关注支持一下吧,谢谢大家了,博主也会继续写更多的大学生专栏,如果你们还有什么问题,可以评论留言或者私信给我

你可能感兴趣的:(芯片驱动,大学生专栏)