一、硬件搭建
先根据模块上面的丝印对应接好杜邦线,模块上VDD接3.3V。模块上的GND接开发板上面的GND,DATA引脚接单片机的GPIO脚,我这接了PC9。
二、模块熟悉
由于本人很懒,买回来的模块几年了没用过,一直吃灰,感谢极术给的这次测评的机会。让我吃灰的模块不在吃灰。由于买回来没用过。先去嘉立创查一下规格书。先熟悉一下这个器件的一些特性和时序。
![图片.png 图片.png](//file.elecfans.com/web2/M00/84/AD/poYBAGOhDnaAB4WkAAB2i44HZNs142.jpg)
数据格式
![图片.png 图片.png](//file.elecfans.com/web2/M00/85/35/pYYBAGOhDnaAAvmLAACENa0mtP8214.jpg)
![图片.png 图片.png](//file.elecfans.com/web2/M00/85/35/pYYBAGOhDnaASBm5AACGRD3D5qE496.jpg)
![图片.png 图片.png](//file.elecfans.com/web2/M00/84/AD/poYBAGOhDnaAPrPVAADt-TkBY6o258.jpg)
时序图
![图片.png 图片.png](//file.elecfans.com/web2/M00/85/35/pYYBAGOhDnaADXBLAAEcohZF8pY030.jpg)
1、从时序图来看,我们只需要先把PC9拉高然后拉低大于18ms然后再拉高,激活模块,就可以等待模块相应低电平,在等待响应高电平,就可以接收40bit数据。然后再拉高PC9引脚就可以读取到湿度和温度数据。
学习一个新的东西的最快方式是看他的使用示例,并且驱动起来
![图片.png 图片.png](//file.elecfans.com/web2/M00/85/35/pYYBAGOhDnaAclhkAAHGaHPPdmI932.jpg)
三、软件部分
从单总线格式定义的延时来看,我们需妖在GD32F427里面准备ms延时和us延时。
毫秒延时我们直接使用系统已经搭建好的滴答时钟就可以了
systick_config();
us时钟需要我们自己搭建,
在这里我使用通用定时器1来搭建us。
搭建us函数需要用到延时和中断和时钟的分配。
1、熟悉时钟
从GD32F427xx的数据手册,看到最高时钟为200MHz
![图片.png 图片.png](//file.elecfans.com/web2/M00/85/35/pYYBAGOhDnaAAN2nAAItw49LVkE075.jpg)
查看一下时钟树,找到time1的时钟路线,从下图看time1的时钟CK_TIMERx
挂在APB1总线上。
我们只需要吧CK_TIMERx配置成1MHz就可以了计数器为1.或者1us产生一次中断。
![图片.png 图片.png](//file.elecfans.com/web2/M00/84/AD/poYBAGOhDneAFXHAAALG14NkHbE470.jpg)
我们先看一下整个系统软件配置的时钟是多少。进入startup_gd32f407_427.s汇编启动文件查看一下系统时钟的配置,下面我复制了一部分代码。
下面SystemInit就是配置系统时钟的函数。
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
时钟的配置,由SystemInit函数调用system_clock_config,system_clock_config执行在调用system_clock_200m_25m_hxtal,最后完成200M时钟的配置,具体的时钟配置函数和内部代码逻辑如下:
下面是SystemInit函数
void SystemInit (void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));
#endif
RCU_CTL |= RCU_CTL_IRC16MEN;
while(0U == (RCU_CTL & RCU_CTL_IRC16MSTB)){
}
RCU_MODIFY(0x50);
RCU_CFG0 &= ~RCU_CFG0_SCS;
RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN);
RCU_CTL &= ~(RCU_CTL_HXTALBPS);
RCU_CFG0 = 0x00000000U;
while(0 != (RCU_CFG0 & RCU_SCSS_IRC16M)){
}
RCU_PLL = 0x24003010U;
RCU_INT = 0x00000000U;
system_clock_config();
}
system_clock_config函数:
static void system_clock_config(void)
{
#ifdef __SYSTEM_CLOCK_IRC16M
system_clock_16m_irc16m();
#elif defined (__SYSTEM_CLOCK_HXTAL)
system_clock_hxtal();
#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC16M)
system_clock_120m_irc16m();
#elif defined (__SYSTEM_CLOCK_120M_PLL_8M_HXTAL)
system_clock_120m_8m_hxtal();
#elif defined (__SYSTEM_CLOCK_120M_PLL_25M_HXTAL)
system_clock_120m_25m_hxtal();
#elif defined (__SYSTEM_CLOCK_168M_PLL_IRC16M)
system_clock_168m_irc16m();
#elif defined (__SYSTEM_CLOCK_168M_PLL_8M_HXTAL)
system_clock_168m_8m_hxtal();
#elif defined (__SYSTEM_CLOCK_168M_PLL_25M_HXTAL)
system_clock_168m_25m_hxtal();
#elif defined (__SYSTEM_CLOCK_200M_PLL_IRC16M)
system_clock_200m_irc16m();
#elif defined (__SYSTEM_CLOCK_200M_PLL_8M_HXTAL)
system_clock_200m_8m_hxtal();
#elif defined (__SYSTEM_CLOCK_200M_PLL_25M_HXTAL)
system_clock_200m_25m_hxtal();
#elif defined (__SYSTEM_CLOCK_240M_PLL_IRC16M)
system_clock_240m_irc16m();
#elif defined (__SYSTEM_CLOCK_240M_PLL_8M_HXTAL)
system_clock_240m_8m_hxtal();
#elif defined (__SYSTEM_CLOCK_240M_PLL_25M_HXTAL)
system_clock_240m_25m_hxtal();
#endif
}
知道了最大时钟,我们可以配置定时器了
void bsp_timer_init(void)
{
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(RCU_TIMER1);
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
timer_struct_para_init(&timer_initpara);
timer_deinit(TIMER1);
timer_initpara.prescaler = 5-1;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 40-1;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER1,&timer_initpara);
timer_auto_reload_shadow_enable(TIMER1);
timer_interrupt_enable(TIMER1,TIMER_INT_UP);
nvic_irq_enable(TIMER1_IRQn, 0, 1);
timer_enable(TIMER1);
}
#ifndef __DHT11_H__
#define __DHT11_H__
#include "gd32f4xx.h"
#include "systick.h"
#include "stdbool.h"
#include "time.h"
#define DHT11_HIGH 1
#define DHT11_LOW 0
#define DHT_PORT_RCU RCU_GPIOC
#define DHT_PORT GPIOC
#define DHT_PORT_PIN GPIO_PIN_9
typedef struct
{
uint8_t humi_int;
uint8_t humi_deci;
uint8_t temp_int;
uint8_t temp_deci;
uint8_t check_sum;
}DHT11_Data_TypeDef;
#define DHT11_DATA_OUT(a) if (a) \
gpio_bit_write(DHT_PORT, DHT_PORT_PIN, true);\
else \
gpio_bit_write(DHT_PORT, DHT_PORT_PIN, false)
#define DHT11_DATA_IN() gpio_input_bit_get(DHT_PORT,DHT_PORT_PIN)
#define DHT_VOLTAGE(VOLTAGE) (VOLTAGE == true ? gpio_bit_write(DHT_PORT, DHT_PORT_PIN, true) : gpio_bit_write(DHT_PORT, DHT_PORT_PIN, false))
void DHT11_Mode_Out_PP(void);
uint8_t Read_DHT11(DHT11_Data_TypeDef *DHT11_Data);
#endif
#include "dht11.h"
void DHT11_Mode_Out_PP(void)
{
rcu_periph_clock_enable(DHT_PORT_RCU);
gpio_mode_set(DHT_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, DHT_PORT_PIN);
gpio_output_options_set(DHT_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, DHT_PORT_PIN);
}
void DHT11_Mode_IPU(void)
{
rcu_periph_clock_enable(DHT_PORT_RCU);
gpio_mode_set(DHT_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, DHT_PORT_PIN);
}
static uint8_t Read_Byte(void)
{
uint8_t i, temp=0;
for(i=0;i<8;i++)
{
while(DHT11_DATA_IN()==RESET);
delay_1us(40);
if(DHT11_DATA_IN()==SET)
{
while(DHT11_DATA_IN()==SET);
temp|=(uint8_t)(0x01<<(7-i));
}
else
{
temp&=(uint8_t)~(0x01<<(7-i));
}
}
return temp;
}
uint8_t Read_DHT11(DHT11_Data_TypeDef *DHT11_Data)
{
uint16_t count;
DHT11_Mode_Out_PP();
DHT11_DATA_OUT(DHT11_LOW);
delay_1ms(20);
DHT11_DATA_OUT(DHT11_HIGH);
delay_1us(30);
DHT11_Mode_IPU();
if(DHT11_DATA_IN()==RESET)
{
count=0;
while(DHT11_DATA_IN()==RESET)
{
count++;
if(count>1000) return 0;
delay_1us(10);
}
count=0;
while(DHT11_DATA_IN()==SET)
{
count++;
if(count>1000) return 0;
delay_1us(10);
}
DHT11_Data->humi_int= Read_Byte();
DHT11_Data->humi_deci= Read_Byte();
DHT11_Data->temp_int= Read_Byte();
DHT11_Data->temp_deci= Read_Byte();
DHT11_Data->check_sum= Read_Byte();
DHT11_Mode_Out_PP();
DHT11_DATA_OUT(DHT11_HIGH);
if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
return 1;
else
return 0;
}
else
{
return 0;
}
}
执行函数
#include "gd32f4xx.h"
#include "gd32f427r_start.h"
#include "systick.h"
#include <stdio.h>
#include "dht11.h"
#include "time.h"
#include "drv_usb_hw.h"
#include "usbd_msc_core.h"
DHT11_Data_TypeDef DHT11_Data;
usb_core_driver msc_udisk;
unsigned char SRAM[40 * 1024];
int main(void)
{
systick_config();
rcu_periph_clock_enable(RCU_GPIOC);
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
gpio_bit_reset(GPIOC, GPIO_PIN_6);
bsp_timer_init();
DHT11_Mode_Out_PP();
usb_gpio_config();
usb_rcu_config();
usb_timer_init();
usbd_init(&msc_udisk,
#ifdef USE_USB_FS
USB_CORE_ENUM_FS,
#elif defined(USE_USB_HS)
USB_CORE_ENUM_HS,
#endif
&msc_desc,
&msc_class);
usb_intr_config();
while(1) {
gpio_bit_set(GPIOC, GPIO_PIN_6);
delay_1ms(1000);
gpio_bit_reset(GPIOC, GPIO_PIN_6);
delay_1ms(1000);
if( Read_DHT11 ( & DHT11_Data ) == SUCCESS)
{
printf("\r\n读取DHT11成功!\r\n\r\n湿度为%d.%d %RH ,温度为 %d.%d℃ \r\n",\
DHT11_Data.humi_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci);
}
else{
delay_1ms(1);
}
}
}
原作者:兆易创新GD32 MCU 惜今