一、准备工作
有关CUBEMX的初始化配置,参见我的另一篇blog:【STM32+HAL】CUBEMX初始化配置
二、所用工具
1、芯片: STM32F407VET6
2、IDE: MDK-Keil软件
3、库文件:STM32F4xxHAL库
三、实现功能
串口打印当前温度值
四、HAL库配置
1、选择IO口连接输入输出端口DQ
2、打开串口
至此,HAL库配置完毕
五、Keil填写代码
1、us级延时函数
#define CPU_FREQUENCY_MHZ 168 /* CPU主频,根据实际进行修改 *//*** 此延时函数代码适用于HAL库*/
void delay_us(uint32_t delay)
{int last, curr, val;int temp;while (delay != 0){temp = delay > 900 ? 900 : delay;last = SysTick->VAL;curr = last - CPU_FREQUENCY_MHZ * temp;if (curr >= 0){do{val = SysTick->VAL;}while ((val < last) && (val >= curr));}else{curr += CPU_FREQUENCY_MHZ * 1000;do{val = SysTick->VAL;}while ((val <= last) || (val > curr));}delay -= temp;}
}
2、DS18B20.c
#include "ds18b20.h"
#include "tim.h"
#include "main.h"#define CPU_FREQUENCY_MHZ 168 /* CPU主频,根据实际进行修改 *//*** 此延时函数代码适用于HAL库*/
void delay_us(uint32_t delay)
{int last, curr, val;int temp;while (delay != 0){temp = delay > 900 ? 900 : delay;last = SysTick->VAL;curr = last - CPU_FREQUENCY_MHZ * temp;if (curr >= 0){do{val = SysTick->VAL;}while ((val < last) && (val >= curr));}else{curr += CPU_FREQUENCY_MHZ * 1000;do{val = SysTick->VAL;}while ((val <= last) || (val > curr));}delay -= temp;}
}static void DS18B20_IO_Init(void)
{/* 总线空闲为高电平 */HAL_GPIO_WritePin(DS18B20_GPIO_Port, DS18B20_Pin, GPIO_PIN_SET);
}static void DS18B20_IO_OUT(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = DS18B20_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(DS18B20_GPIO_Port, &GPIO_InitStruct);
}static void DS18B20_IO_IN(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = DS18B20_Pin;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(DS18B20_GPIO_Port, &GPIO_InitStruct);
}static void DS18B20_DQ_OUT(int state)
{HAL_GPIO_WritePin(DS18B20_GPIO_Port, DS18B20_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET);
}static int DS18B20_DQ_IN(void)
{return HAL_GPIO_ReadPin(DS18B20_GPIO_Port, DS18B20_Pin) == GPIO_PIN_SET ? 1 : 0;
}///
/// DS18B20驱动
///
/////复位DS18B20
void DS18B20_Rst(void)
{DS18B20_IO_OUT(); //SET PA0 OUTPUTDS18B20_DQ_OUT(0); //拉低DQdelay_us(750); //拉低750usDS18B20_DQ_OUT(1); //DQ=1delay_us(15); //15US
}//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
uint8_t DS18B20_Check(void)
{uint8_t retry=0;DS18B20_IO_IN();//SET PA0 INPUTwhile (DS18B20_DQ_IN()&&retry<200){retry++;delay_us(1);};if(retry>=200)return 1;else retry=0;while (!DS18B20_DQ_IN()&&retry<240){retry++;delay_us(1);};if(retry>=240)return 1;return 0;
}//从DS18B20读取一个位
//返回值:1/0
uint8_t DS18B20_Read_Bit(void) // read one bit
{uint8_t data;DS18B20_IO_OUT(); //SET PA0 OUTPUTDS18B20_DQ_OUT(0);delay_us(2);DS18B20_DQ_OUT(1);DS18B20_IO_IN(); //SET PA0 INPUTdelay_us(12);if(DS18B20_DQ_IN())data=1;else data=0;delay_us(50);return data;
}//从DS18B20读取一个字节
//返回值:读到的数据
uint8_t DS18B20_Read_Byte(void) // read one byte
{uint8_t i,j,dat;dat=0;for (i=1; i<=8; i++){j=DS18B20_Read_Bit();dat=(j<<7)|(dat>>1);}return dat;
}//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(uint8_t dat)
{uint8_t j;uint8_t testb;DS18B20_IO_OUT();//SET PA0 OUTPUT;for (j=1; j<=8; j++){testb=dat&0x01;dat=dat>>1;if (testb){DS18B20_DQ_OUT(0);// Write 1delay_us(2);DS18B20_DQ_OUT(1);delay_us(60);}else{DS18B20_DQ_OUT(0);// Write 0delay_us(60);DS18B20_DQ_OUT(1);delay_us(2);}}
}//开始温度转换
void DS18B20_Start(void) // ds1820 start convert
{DS18B20_Rst();DS18B20_Check();DS18B20_Write_Byte(0xcc); // skip romDS18B20_Write_Byte(0x44); // convert
}//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在
uint8_t DS18B20_Init(void)
{DS18B20_IO_Init();DS18B20_Rst();return DS18B20_Check();
}//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250)
short DS18B20_Get_Temp(void)
{uint8_t temp;uint8_t TL,TH;short tem;__disable_irq(); /* 中断可能会单总线的时序从而导致读出来的温度值不正确,所以读取之前屏蔽中断 */DS18B20_Start(); // ds1820 start convertDS18B20_Rst();DS18B20_Check();DS18B20_Write_Byte(0xcc); // skip romDS18B20_Write_Byte(0xbe); // convertTL=DS18B20_Read_Byte(); // LSBTH=DS18B20_Read_Byte(); // MSBif(TH>7){TH=~TH;TL=~TL;temp=0; //温度为负}else temp=1; //温度为正tem=TH; //获得高八位tem<<=8;tem+=TL; //获得底八位__enable_irq(); /* 再将全局中断打开 */tem=(float)tem*0.625; //转换if(temp) return tem; //返回温度值else return -tem;
}/*
代码使用示例:int main()
{short temp;while(DS18B20_Init()){printf(" ds18b20 init failed ! \r\n");HAL_Delay(1000);}while(1){temp = DS18B20_Get_Temp();printf("当前温度:%0.2f \r\n", (float)temp / 10);HAL_Delay(1000);}
}*/
3、DS18B20.h
#ifndef DS18B20_H__
#define DS18B20_H__#include <stdint.h>uint8_t DS18B20_Init(void); //初始化DS18B20
short DS18B20_Get_Temp(void); //获取温度
void DS18B20_Start(void); //开始温度转换
void DS18B20_Write_Byte(uint8_t dat);//写入一个字节
uint8_t DS18B20_Read_Byte(void); //读出一个字节
uint8_t DS18B20_Read_Bit(void); //读出一个位
uint8_t DS18B20_Check(void); //检测是否存在DS18B20
void DS18B20_Rst(void); //复位DS18B20void delay_us(uint32_t delay);#endif
六、巨人之肩
STM32 HAL库 DS18B20读取温度值
【常用传感器】DS18B20温度传感器原理详解及例程代码
七、源码提供
资源【STM32+HAL】DS18B20读取环境温度