请给出用stm32f103c8t6,标准库的方式初始化DHT11,并采集温湿度打印到串口
时间: 2024-03-23 15:43:15 浏览: 61
好的,以下是用STM32F103C8T6标准库初始化DHT11,并采集温湿度并打印到串口的代码:
首先,需要定义DHT11的引脚,例如我们将它连接到了PA1引脚上:
```c
#define DHT11_PIN GPIO_PIN_1
#define DHT11_PORT GPIOA
```
然后,需要初始化GPIO和定时器。其中,DHT11的数据引脚需要设置为输出模式,并且初始化为高电平。定时器用于精确控制DHT11的数据采集和处理时间,这里我们使用TIM2定时器。
```c
void DHT11_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
TIM_TimeBaseInitTypeDef TIM_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_SET);
/*Configure GPIO pin : DHT11_PIN */
GPIO_InitStruct.Pin = DHT11_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(DHT11_PORT, &GPIO_InitStruct);
/* TIM2 init */
__HAL_RCC_TIM2_CLK_ENABLE();
TIM_InitStruct.Period = 0xffff;
TIM_InitStruct.Prescaler = SystemCoreClock / 1000000 - 1;
TIM_TimeBaseInit(TIM2, &TIM_InitStruct);
}
```
接下来,实现DHT11的数据采集和处理函数。通过定时器产生的精确延时,发送开始信号和读取DHT11传输的40位数据。然后,通过计算得到温度和湿度值,并将结果打印到串口。
```c
void DHT11_ReadData(float* temperature, float* humidity)
{
uint8_t data[5] = {0};
uint8_t i, j;
HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_RESET);
DELAY_US(18000); // 发送开始信号
HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_SET);
DELAY_US(30);
HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_RESET);
DELAY_US(80);
HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_SET);
DELAY_US(10);
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DHT11_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(DHT11_PORT, &GPIO_InitStruct);
// 等待DHT11的响应信号
while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_SET);
// 等待DHT11的数据传输
while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_RESET);
// 读取40位数据
for (i = 0; i < 5; i++)
{
for (j = 0; j < 8; j++)
{
while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_RESET);
DELAY_US(40);
if (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_SET)
{
data[i] |= (1 << (7 - j));
}
while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_SET);
}
}
// 计算温度和湿度值
uint8_t sum = data[0] + data[1] + data[2] + data[3];
if (data[4] != sum) return; // 数据校验失败
*humidity = (float)(data[0] * 256 + data[1]) / 10.0f;
*temperature = (float)(data[2] * 256 + data[3]) / 10.0f;
// 打印温湿度值
char buf[32];
sprintf(buf, "Temperature: %.1fC Humidity: %.1f%%\r\n", *temperature, *humidity);
HAL_UART_Transmit(&huart1, (uint8_t*)buf, strlen(buf), 1000);
// 恢复DHT11数据引脚状态
GPIO_InitStruct.Pin = DHT11_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(DHT11_PORT, &GPIO_InitStruct);
HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_SET);
}
```
最后,在main函数中调用初始化函数和数据读取函数即可。
```c
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
DHT11_Init();
float temperature, humidity;
while (1)
{
DHT11_ReadData(&temperature, &humidity);
HAL_Delay(2000);
}
}
```
需要注意的是,代码中的`DELAY_US`宏需要自行定义,方法如下:
```c
#define DELAY_US(us) TIM2_DelayUs(us)
void TIM2_DelayUs(uint16_t us)
{
TIM2->CNT = 0;
TIM2->ARR = us;
TIM2->CR1 |= TIM_CR1_CEN;
while (TIM2->CNT < us);
TIM2->CR1 &= ~TIM_CR1_CEN;
}
```
这样,就可以通过串口监视器查看到DHT11采集到的温湿度值了。
阅读全文