在完成所有项目后会开源,目前初步是想做一个通过DHT11采集信息,OLED显示,ESP8266上传,可通过小程序查看的简易智能家居事例。
MindSDK环境准备
使用sdk里的hello_work作为模板
DHT11工作原理
简单来说就是
/*
数据格式:
湿度整数 湿度小数 温度整数 温度小数 校验位
00000000 00000000 00000000 00000000 00000000
1 看原理图确认GPIO引脚
2、 输出模式, 输出起始信号 :输出低电平18~30ms, 20ms
3、 IO口配置浮空输入模式,准检测响应信号
传感器把数据总线( SDA)拉低 83μs,
再接高 87μs 以响应主机的起始信号。
4、 40 个位的数据,高位先发;
一位一位的收,数据0: 54us低电平 + 23~27高电平
数据1: 54us低电平 + 68~74高电平
注意高位先发的(每个字节)
5、校验数据
前4个字节,求和,把和值的末八位和校验位对比
相同数据正确、否则数据异常
*/
接下来就开始写代码了
由于我在MindSDK里找不到延时函数就只能手动操作一波寄存器写个延时函数了
delay.c
void delay_us(uint32_t nus)
{
uint32_t temp;
SysTick->LOAD= nus *15; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
void delay_ms(uint16_t nms)
{
uint32_t temp;
SysTick->LOAD= nms *15* 1000; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
接下来开始写DHT11的代码了,主要是调用SDK代码,开发难度很低
dht11.c
#include "dht11.h"
void dht11_gpio_input(void)
{
GPIO_Init_Type g;
//RCC_APB2PeriphClockCmd(DHT11_RCC, ENABLE);
g.Pins = DHT11_GPIO_PIN;
g.Speed = GPIO_Speed_50MHz;
g.PinMode = GPIO_PinMode_In_Floating; //输入
GPIO_Init(DHT11_GPIO_TYPE, &g);
}
void dht11_gpio_output(void)
{
GPIO_Init_Type g;
//RCC_APB2PeriphClockCmd(DHT11_RCC, ENABLE);
g.Pins = DHT11_GPIO_PIN;
g.Speed = GPIO_Speed_50MHz;
g.PinMode = GPIO_PinMode_Out_PushPull; //输出
GPIO_Init(DHT11_GPIO_TYPE, &g);
}
void dht11_reset(void)//复位
{
dht11_gpio_output();
DHT11_OUT_L;
delay_us(19000);
DHT11_OUT_H;
delay_us(30);
dht11_gpio_input();
}
uint16_t dht11_scan(void)//判断总线状态
{
return DHT11_IN;
}
uint16_t dht11_read_bit(void)//读取一个bit
{
while (DHT11_IN == RESET);
delay_us(40);
if (DHT11_IN == SET)
{
while (DHT11_IN == SET);
return 1;
}
else
{
return 0;
}
}
uint16_t dht11_read_byte(void)//读取一个字节
{
uint16_t i;
uint16_t data = 0;
for (i = 0; i < 8; i++)
{
data <<= 1;
data |= dht11_read_bit();
}
return data;
}
uint8_t checksum;
uint16_t dht11_read_data(uint8_t buffer[5])//读取数据
{
uint16_t i = 0;
dht11_reset();
if (dht11_scan() == RESET)
{
while (dht11_scan() == RESET);
while (dht11_scan() == SET);
for (i = 0; i < 5; i++)
{
buffer[i] = dht11_read_byte();
}
while (dht11_scan() == RESET);
dht11_gpio_output();
DHT11_OUT_H;
checksum = buffer[0] + buffer[1] + buffer[2] + buffer[3];
if (checksum != buffer[4])
{
// checksum error
return 1;
}
}
return 0;
}
dht11.h
#ifndef __DHT11_H__
#define __DHT11_H__
//#include "timer.h"
#include "board_init.h"
#include "delay.h"
#include "hal_gpio.h"
#include "hal_rcc.h"
#include "pin_init.h"
#define DHT11_GPIO_TYPE GPIOB
#define DHT11_GPIO_PIN GPIO_PIN_11
#define DHT11_RCC RCC_APB2Periph_GPIOB
#define DHT11_OUT_H GPIO_SetBits(DHT11_GPIO_TYPE, DHT11_GPIO_PIN)
#define DHT11_OUT_L GPIO_ClearBits(DHT11_GPIO_TYPE, DHT11_GPIO_PIN)
#define DHT11_IN GPIO_ReadInDataBit(DHT11_GPIO_TYPE, DHT11_GPIO_PIN)
#define RESET 0
#define SET 1
void dht11_gpio_input(void);
void dht11_gpio_output(void);
uint16_t dht11_scan(void);
uint16_t dht11_read_bit(void);
uint16_t dht11_read_byte(void);
uint16_t dht11_read_data(uint8_t buffer[4]);
#endif
写完了DHT11的代码,接下来验证下
在main里调用下
while (1)
{
if (dht11_read_data(buffer) == 0)
{
hum = buffer[0] + buffer[1] / 10.0;
temp1 = buffer[2] + buffer[3] / 10.0;
printf("hum:%f,temp:%f\r\n",hum,temp1);
}
delay_ms(100);
}
看下结果
总结
MindSDK使用体验还行,有些还是得自己写,要是api更完善点会更好。
原作者:四季的温度
更多回帖