这两个传感器F4的开发板上都没有,如果要阅读此博客,请先买好传感器哟(^U^)ノYO
1.DS18B20 数字温度传感器实验
1.1 DS18B20简介
1.2 硬件与IO口配置
将 DS18B20 传感器插入到这个上面就可以通过 STM32 来读取 DS18B20 的温度了。
1.3 实物图与接线
1.4 工程配置
1.开启GPIOG_9
2.开启串口
3.开启TIMX,实现us级定时
在tim.c文件中加入:
/* USER CODE BEGIN 1 */
void delay_us(uint16_t us){
uint16_t differ = 0xffff-us-5;
__HAL_TIM_SET_COUNTER(&htim7,differ);
HAL_TIM_Base_Start(&htim7);
while(differ < 0xffff-5){
differ = __HAL_TIM_GET_COUNTER(&htim7);
}
HAL_TIM_Base_Stop(&htim7);
}
/* USER CODE END 1 */
1.5 驱动和检测代码编写
驱动代码移植原子哥。驱动代码有很多,可以自行修改。
1.5.1 ds18b20.c
#include "ds18b20.h"
void DS18B20_IO_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);
}
void DS18B20_IO_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);
}
//复位DS18B20
void DS18B20_Rst(void)
{
DS18B20_IO_OUT();
DS18B20_DQ_OUT_LOW;
delay_us(750);
DS18B20_DQ_OUT_HIGH;
delay_us(15);
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
uint8_t DS18B20_Check(void)
{
uint8_t retry = 0;
DS18B20_IO_IN();
while(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)
{
uint8_t data;
DS18B20_IO_OUT();
DS18B20_DQ_OUT_LOW;
delay_us(2);
DS18B20_DQ_OUT_HIGH;
DS18B20_IO_IN();
delay_us(12);
if(DS18B20_DQ_IN)
data = 1;
else
data = 0;
delay_us(50);
return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
uint8_t DS18B20_Read_Byte(void)
{
uint8_t i,j,data;
data = 0;
for(i=1;i<=8;i++)
{
j = DS18B20_Read_Bit();
data = (j<<7)|(data>>1);
}
return data;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(uint8_t data)
{
uint8_t j;
uint8_t testb;
DS18B20_IO_OUT();
for(j=1;j<=8;j++)
{
testb=data&0x01;
data=data>>1;
if(testb)
{
DS18B20_DQ_OUT_LOW;
delay_us(2);
DS18B20_DQ_OUT_HIGH;
delay_us(60);
}
else
{
DS18B20_DQ_OUT_LOW;
delay_us(60);
DS18B20_DQ_OUT_HIGH;
delay_us(2);
}
}
}
//开始温度转换
void DS18B20_Start(void)
{
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc);
DS18B20_Write_Byte(0x44);
}
uint8_t DS18B20_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);
DS18B20_Rst();
return DS18B20_Check();
}
//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在
short DS18B20_Get_Temperature(void)
{
uint8_t t;
uint8_t TL,TH;
short temperature;
DS18B20_Start();
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc);
DS18B20_Write_Byte(0xbe);
TL = DS18B20_Read_Byte();
TH = DS18B20_Read_Byte();
if(TH>7)
{
TH = ~TH;
TL = ~TL;
t = 0;
}
else
t = 1;
temperature = TH;
temperature <<= 8;
temperature += TL;
temperature = (short)temperature*0.625;
if(temperature)
return temperature;
else
return -temperature;
}
DS18B20读取温度需要发送一些命令,
温度转换指令:0x44(启动Ds18b20启动转换温度)。
读暂存器指令:0xBE(读取暂存器中的九字节数据)。
1.5.2 ds18b20.h
#ifndef __DS18B20_H
#define __DS18B20_H
#include "main.h"
#include "tim.h"
#define DS18B20_DQ_OUT_HIGH HAL_GPIO_WritePin(GPIOG,GPIO_PIN_9,GPIO_PIN_SET)
#define DS18B20_DQ_OUT_LOW HAL_GPIO_WritePin(GPIOG,GPIO_PIN_9,GPIO_PIN_RESET)
#define DS18B20_DQ_IN HAL_GPIO_ReadPin(GPIOG,GPIO_PIN_11)
void DS18B20_IO_IN(void);
void DS18B20_IO_OUT(void);
uint8_t DS18B20_Init(void); //初始化DS18B20
void DS18B20_Rst(void); //复位DS18B20
uint8_t DS18B20_Check(void);//检测是否存在DS18B20
uint8_t DS18B20_Read_Bit(void);//读出一个位
uint8_t DS18B20_Read_Byte(void);//读出一个字节
void DS18B20_Write_Byte(uint8_t data);//写入一个字节
void DS18B20_Start(void);//开始温度转换
short DS18B20_Get_Temperature(void); //获取温度
#endif
1.5.3 main测试
/* USER CODE BEGIN 2 */
printf("DS18B20 Test!\r\n");
while(DS18B20_Init())
{
printf("DS18B20 checked failed!!!\r\n");
HAL_Delay(500);
}
//DS18B20_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
temperature=DS18B20_Get_Temperature();
if(temperature < 0)
printf("temperature = -%.2f degree\r\n",temperature/10);
else
printf("temperature = %.2f degree\r\n",temperature/10);
HAL_Delay(200);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
1.6 测试结果
2.DHT11 数字温湿度传感器实验
在此将介绍数字温湿度传感器DHT11 的使用,该传感器不但能测温度,还能测湿度。
2.1 DHT11简介和接线
DHT11 和 DS18B20 的接口是共用一个的,不过 DHT11 有 4 条腿,需要把 U12 的 4 个接口都用上, 将 DHT11 传感器插入到这个上面就可以通过 STM32F4来读取温湿度值了。
2.2 通信时序简述
以下内容来自客服给的DHT11说明书。
2.2.1 数据格式
微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零.操作流程如下:
一次完整的数据传输为40bit,高位先出。
数据格式: 8bit湿度整数数据+8bit湿度小数数据
+8bi温度整数数据+8bit温度小数数据
+8bit校验和
据传送正确时校验和数据等于 “8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据” 所得结果的末8位。
2.2.2 通讯时序
通讯过程如图:
总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。 DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号。主机发送开始信号结束后,延时等待20-40us后,读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可,总线由上拉电阻拉高。
开始传输信号:
总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定了数据位是0还是1。
2.3.2 数字信号0/1表示方式
2.3工程配置
2.2.1 输出GPIO_PG_11
2.2.2 打开串口USART1
2.2.3 开启TIM7,与1.4相同
2.4 编写代码
依据时序图,编写程序。
2.4.1 初始化、封装IO的输入输出
由于是一个IO口,要满足输出和检测电平,所以用两个函数来切换引脚的模式,可以使引脚在输出和输入之间切换
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在
uint8_t DHT11_Init(void)
{
DHT11_Rst();
return DHT11_Check();
}
#define DHT11_DQ_OUT_HIGH HAL_GPIO_WritePin(GPIOG,GPIO_PIN_11,GPIO_PIN_SET)
#define DHT11_DQ_OUT_LOW HAL_GPIO_WritePin(GPIOG,GPIO_PIN_11,GPIO_PIN_RESET)
#define DHT11_DQ_IN HAL_GPIO_ReadPin(GPIOG,GPIO_PIN_11)
void DHT11_IO_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_11;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);
}
void DHT11_IO_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_11;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOG,&GPIO_Ini
2.4.2 复位和响应模块
//复位DHT11
void DHT11_Rst(void)
{
DHT11_IO_OUT(); //设置为输出
DHT11_DQ_OUT_LOW; //拉低DQ
HAL_Delay(20); //拉低至少18ms
DHT11_DQ_OUT_HIGH; //DQ=1
delay_us(30); //主机拉高20~40us
}
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
uint8_t DHT11_Check(void)
{
uint8_t retry=0;
DHT11_IO_IN(); //设置为输出
while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
{
retry++;
delay_us(1);
};
if(retry>=100)return 1;
else retry=0;
while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
{
retry++;
delay_us(1);
};
if(retry>=100)return 1;
return 0;
}
//从DHT11读取一个位
//返回值:1/0
uint8_t DHT11_Read_Bit(void)
{
uint8_t retry=0;
while(DHT11_DQ_IN&&retry<100)//等待变为低电平
{
retry++;
delay_us(1);
}
retry=0;
while(!DHT11_DQ_IN&&retry<100)//等待变高电平
{
retry++;
delay_us(1);
}
delay_us(40);//等待40us
if(DHT11_DQ_IN)return 1;
else return 0;
}
//从DHT11读取一个字节
//返回值:读到的数据
uint8_t DHT11_Read_Byte(void)
{
uint8_t i,dat;
dat=0;
for (i=0;i<8;i++)
{
dat<<=1;
dat|=DHT11_Read_Bit();
}
return dat;
}
2.4.3 数据的解算
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
uint8_t DHT11_Read_Data(uint16_t *temp,uint16_t *humi)
{
uint8_t buf[5];
uint8_t i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0;i<5;i++)//读取40位数据
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humi=(buf[0]<<8) + buf[1];
*temp=(buf[2]<<8) + buf[3];
}
}else return 1;
return 0;
}
2.4.4 测试代码
uint16_t temperature;
uint16_t humidity;
while(DHT11_Init())
{
printf("DHT11 Checked failed!!!\r\n");
HAL_Delay(200);
}
printf("DHT11 Checked Sucess!!!\r\n");
while (1)
{
DHT11_Read_Data(&temperature,&humidity);
printf("DHT11 Temperature = %d.%d degree\r\n",temperature>>8,temperature&0xff);
printf("DHT11 Humidity = %d.%d%%\r\n",humidity>>8,humidity&0xff);
HAL_Delay(200);
}