【GD32F427开发板试用】+DHT11温湿度监测
本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动,更多开发板试用活动请关注极术社区网站。作者:四季的温度
在完成所有项目后会开源,本次依旧是想做一个通过DHT11采集信息,OLED显示,ESP8266上传,可通过小程序查看的简易智能家居事例。
MDK环境准备
这里遇到了不少坑,到时候专门开一篇来讲
DHT11工作原理
具体可看csdn这篇文章https://blog.csdn.net/m0_5678…
简单来说就是
/*
数据格式:
湿度整数 湿度小数 温度整数 温度小数 校验位
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个字节,求和,把和值的末八位和校验位对比 相同数据正确、否则数据异常
*/
接下来就开始写代码了
由于官方库的systick是ms级别的,需要改写成us级别或者另外实现,我这里都做了,各位可以按需使用~~
第一种基于官方库systick修改为us级别
systick.cvoid systick_config(void){ /* setup systick timer for 1000Hz interrupts */ /*1000u是ms,1000000是us*/ if(SysTick_Config(SystemCoreClock / 1000000U)) { /* capture error */ while(1) { } } /* configure the systick handler priority */ NVIC_SetPriority(SysTick_IRQn, 0x00U);}
第二种,自己重新写
下边写的是delay_us,如果需要ms则*1000就可以了
delay.c void delay_us(uint32_t nus){ int i; uint32_t temp; for(i=0;iLOAD= nus *25;//时间加载 SysTick->VAL=0x00;//清空计数器 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数 do { temp=SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick->VAL =0X00; //清空计数器 }}
接下来开始写DHT11的代码了,主要是调用库,开发难度很低
dht11.c#include "dht11.h"void dht11_gpio_input(void){ rcu_periph_clock_enable(RCU_GPIOB); /*配置输入*/ gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_12); gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12); }void dht11_gpio_output(void){ rcu_periph_clock_enable(RCU_GPIOB); /*配置下拉输出*/ gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_12); gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12); }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 "gd32f4xx.h"#include "gd32f427v_start.h"#include "systick.h"#define DHT11_GPIO_TYPE GPIOB#define DHT11_GPIO_PIN GPIO_PIN_12#define DHT11_RCC RCC_APB2Periph_GPIOB#define DHT11_OUT_H gpio_bit_set(DHT11_GPIO_TYPE, DHT11_GPIO_PIN)#define DHT11_OUT_L gpio_bit_reset(DHT11_GPIO_TYPE, DHT11_GPIO_PIN)#define DHT11_IN gpio_input_bit_get(DHT11_GPIO_TYPE, DHT11_GPIO_PIN)/*如果使用的是重新写delay_us,不需要下面的宏,如果是改官方的就需要*/#define delay_us delay_1ms#define RESET 0#define SET 1void 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_1ms(1000000);/*因为改了systick,没在delay_1ms所以要把它单us用*/ }
看下结果
总结
GD32F427使用库开发体验还行,不过像systick这个库少了delay_us得自己写或者改,要是更完善点会更好,现在已经完成了DHT11,下一步是OLED,加油
下篇预告
下一篇我会整理下从安装pack到跑起LED工程到写DHT11遇到的问题,给各位参考参考