【GD32L233C-START评测】三、GPIO应用之驱动单总线温湿度传感器DHT11
[复制链接]
GPIO是使用最广泛的外设之一,可以用来进行输入输出,驱动一些特殊时序的传感器。DHT11是一款有已校准数字信号输出的温湿度传感器。 其精度湿度±5%RH, 温度±2℃,量程湿度5~95%RH, 温度-20~+60℃。
手头有一块兼容arduino uno v3接口的机智云的gokit板卡,上面正好有DHT11温湿度传感器。原理图如下:
对比GD32L233C-START原理图可知,信号脚连接的是PB5.
GD32L233固件库和stm32标准固件库类似,个人认为GD32的api设计使用更加方便、简洁。一共有5组GPIO:
/* GPIOx(x=A,B,C,D,F) definitions */
#define GPIOA (GPIO_BASE + 0x00000000U) /*!< GPIOA base address */
#define GPIOB (GPIO_BASE + 0x00000400U) /*!< GPIOB base address */
#define GPIOC (GPIO_BASE + 0x00000800U) /*!< GPIOC base address */
#define GPIOD (GPIO_BASE + 0x00000C00U) /*!< GPIOD base address */
#define GPIOF (GPIO_BASE + 0x00001400U) /*!< GPIOF base address */
每组有16个管脚:
/* GPIO pin definitions */
#define GPIO_PIN_0 BIT(0) /*!< GPIO pin 0 */
#define GPIO_PIN_1 BIT(1) /*!< GPIO pin 1 */
#define GPIO_PIN_2 BIT(2) /*!< GPIO pin 2 */
#define GPIO_PIN_3 BIT(3) /*!< GPIO pin 3 */
#define GPIO_PIN_4 BIT(4) /*!< GPIO pin 4 */
#define GPIO_PIN_5 BIT(5) /*!< GPIO pin 5 */
#define GPIO_PIN_6 BIT(6) /*!< GPIO pin 6 */
#define GPIO_PIN_7 BIT(7) /*!< GPIO pin 7 */
#define GPIO_PIN_8 BIT(8) /*!< GPIO pin 8 */
#define GPIO_PIN_9 BIT(9) /*!< GPIO pin 9 */
#define GPIO_PIN_10 BIT(10) /*!< GPIO pin 10 */
#define GPIO_PIN_11 BIT(11) /*!< GPIO pin 11 */
#define GPIO_PIN_12 BIT(12) /*!< GPIO pin 12 */
#define GPIO_PIN_13 BIT(13) /*!< GPIO pin 13 */
#define GPIO_PIN_14 BIT(14) /*!< GPIO pin 14 */
#define GPIO_PIN_15 BIT(15) /*!< GPIO pin 15 */
#define GPIO_PIN_ALL BITS(0, 15) /*!< GPIO pin all */
关于gpio的所有API如下,通过函数命名和固件库里面的注释就很容易知晓其用法了:
/* function declarations */
/* reset GPIO port */
void gpio_deinit(uint32_t gpio_periph);
/* set GPIO mode */
void gpio_mode_set(uint32_t gpio_periph, uint32_t mode, uint32_t pull_up_down, uint32_t pin);
/* set GPIO output type and speed */
void gpio_output_options_set(uint32_t gpio_periph, uint8_t otype, uint32_t speed, uint32_t pin);
/* set GPIO pin bit */
void gpio_bit_set(uint32_t gpio_periph, uint32_t pin);
/* reset GPIO pin bit */
void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin);
/* write data to the specified GPIO pin */
void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value);
/* write data to the specified GPIO port */
void gpio_port_write(uint32_t gpio_periph, uint16_t data);
/* get GPIO pin input status */
FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin);
/* get GPIO port input status */
uint16_t gpio_input_port_get(uint32_t gpio_periph);
/* get GPIO pin output status */
FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin);
/* get GPIO port output status */
uint16_t gpio_output_port_get(uint32_t gpio_periph);
/* set GPIO alternate function */
void gpio_af_set(uint32_t gpio_periph, uint32_t alt_func_num, uint32_t pin);
/* lock GPIO pin bit */
void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin);
/* toggle GPIO pin status */
void gpio_bit_toggle(uint32_t gpio_periph, uint32_t pin);
/* toggle GPIO port status */
void gpio_port_toggle(uint32_t gpio_periph);
编写dht11驱动头文件DHT.h如下:
#ifndef DHT_H_
#define DHT_H_
#include "gd32l23x.h"
#define DHT_TIMEOUT 10000
typedef struct {
float hum;
float temp;
} DHT_data;
typedef enum {
DHT11,
DHT22
} DHT_type;
typedef struct {
uint32_t DHT_Port;
uint16_t DHT_Pin;
DHT_type type;
uint8_t pullUp;
} DHT_sensor;
DHT_data DHT_getData(DHT_sensor *sensor);
#endif
编写dht11驱动源文件DHT.c如下:
#include "DHT.h"
#define lineDown() gpio_bit_reset(sensor->DHT_Port, sensor->DHT_Pin)
#define lineUp() gpio_bit_set(sensor->DHT_Port, sensor->DHT_Pin)
#define getLine() (gpio_input_bit_get(sensor->DHT_Port, sensor->DHT_Pin) == SET)
#define Delay(d) delay_ms(d)
static void goToOutput(DHT_sensor *sensor)
{
lineUp();
if(sensor->pullUp == 1)
{
gpio_mode_set(sensor->DHT_Port, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, sensor->DHT_Pin);
}
else
{
gpio_mode_set(sensor->DHT_Port, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, sensor->DHT_Pin);
}
gpio_output_options_set(sensor->DHT_Port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, sensor->DHT_Pin);
}
static void goToInput(DHT_sensor *sensor)
{
if(sensor->pullUp == 1)
{
gpio_mode_set(sensor->DHT_Port, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, sensor->DHT_Pin);
}
else
{
gpio_mode_set(sensor->DHT_Port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, sensor->DHT_Pin);
}
}
DHT_data DHT_getData(DHT_sensor *sensor)
{
DHT_data data = {0.0f, 0.0f};
goToOutput(sensor);
lineDown();
Delay(15);
lineUp();
goToInput(sensor);
uint16_t timeout = 0;
while(getLine()) {
timeout++;
if (timeout > DHT_TIMEOUT) return data;
}
timeout = 0;
while(!getLine()) {
timeout++;
if (timeout > DHT_TIMEOUT) return data;
}
timeout = 0;
while(getLine()) {
timeout++;
if (timeout > DHT_TIMEOUT) return data;
}
uint8_t rawData[5] = {0,0,0,0,0};
for(uint8_t a = 0; a < 5; a++) {
for(uint8_t b = 7; b != 255; b--) {
uint32_t hT = 0, lT = 0;
while(!getLine()) lT++;
timeout = 0;
while(getLine()) hT++;
if(hT > lT) rawData[a] |= (1<<b);
}
}
if((uint8_t)(rawData[0] + rawData[1] + rawData[2] + rawData[3]) == rawData[4]) {
if (sensor->type == DHT22) {
data.hum = (float)(((uint16_t)rawData[0]<<8) | rawData[1])*0.1f;
if(!(rawData[2] & (1<<7))) {
data.temp = (float)(((uint16_t)rawData[2]<<8) | rawData[3])*0.1f;
} else {
rawData[2] &= ~(1<<7);
data.temp = (float)(((uint16_t)rawData[2]<<8) | rawData[3])*-0.1f;
}
}
if (sensor->type == DHT11) {
data.hum = (float)rawData[0];
data.temp = (float)rawData[2];;
}
}
return data;
}
main.c测试代码:
#include "gd32l23x.h"
#include "DHT.h"
#include "delay.h"
static DHT_sensor livingRoom = {GPIOB, GPIO_PIN_5, DHT11, 0};
DHT_data d;
int main(void)
{
delay_init();
rcu_periph_clock_enable(RCU_GPIOB);
while(1)
{
d = DHT_getData(&livingRoom);
delay_ms(500);
}
}
测试调试效果:
|