stm32f103c8t6温湿度dht11教程
时间: 2023-07-10 19:34:34 浏览: 282
好的,下面是STM32F103C8T6与DHT11温湿度传感器的教程。
1. 硬件连接:
将DHT11的VCC引脚连接到STM32F103C8T6开发板的3.3V电源引脚,GND引脚连接到开发板的GND引脚,DATA引脚连接到开发板的任意一个GPIO引脚。
2. 软件编程:
首先需要在工程中调用STM32F1xx_HAL_Driver库,并在代码中定义相应的引脚号。
接下来,需要编写相应的程序代码读取DHT11传感器的数据。具体步骤如下:
(1) 通过GPIO口输出低电平信号,保持至少18ms以上(一般为20ms)。
(2) 将GPIO口输出高电平信号,并延时20us,再将GPIO口设置为输入模式。
(3) 等待DHT11的响应信号,即DHT11会将总线拉低80us,然后再拉高80us。
(4) 接下来,DHT11会输出40个数据位,每个数据位之间的低电平时间为50us,高电平时间为26-28us。0表示低电平时长为26-28us,高电平时长为50us;1表示低电平时长为50us,高电平时长为26-28us。
(5) 最后,DHT11会输出一个总线释放信号,即拉高总线80us。
3. 完整代码实现:
```c
#include "main.h"
TIM_HandleTypeDef htim2;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
void delay_us(uint32_t us);
void DHT11_start(void);
uint8_t DHT11_read_byte(void);
uint8_t DHT11_read_data(uint8_t *temp, uint8_t *humi);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM2_Init();
uint8_t temp = 0, humi = 0;
while (1)
{
if (DHT11_read_data(&temp, &humi) == HAL_OK)
{
printf("Temperature: %d, Humidity: %d\n", temp, humi);
}
else
{
printf("Error reading data from DHT11\n");
}
HAL_Delay(2000);
}
}
void DHT11_start(void)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
delay_us(20000); // hold the GPIO pin to reset the DHT11
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
delay_us(20);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
}
uint8_t DHT11_read_byte(void)
{
uint8_t i, j;
uint8_t byte = 0;
for (i = 0; i < 8; i++)
{
while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET)
; // wait for the start of low pulse
delay_us(30); // delay 30us to read the data bit
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_SET) // if the data bit is high
byte |= (1 << (7 - i)); // set the corresponding bit in byte
while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_SET) // wait for the end of data bit
;
}
return byte;
}
uint8_t DHT11_read_data(uint8_t *temp, uint8_t *humi)
{
DHT11_start();
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET) // if DHT11 responds
{
while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET)
; // wait for the end of low pulse
while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_SET)
; // wait for the end of high pulse
*humi = DHT11_read_byte(); // read humidity byte
uint8_t humi_verify = DHT11_read_byte(); // read humidity verify byte
*temp = DHT11_read_byte(); // read temperature byte
uint8_t temp_verify = DHT11_read_byte(); // read temperature verify byte
uint8_t sum = DHT11_read_byte(); // read the sum byte
if (sum == (*humi + humi_verify + *temp + temp_verify))
return HAL_OK;
else
return HAL_ERROR;
}
else
return HAL_ERROR;
}
void delay_us(uint32_t us)
{
__HAL_TIM_SET_COUNTER(&htim2, 0);
while (__HAL_TIM_GET_COUNTER(&htim2) < us)
;
}
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = (SystemCoreClock / 1000000) - 1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 0xFFFF;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
printf("GPIO initialized\n");
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK |
RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
```
在本示例代码中,我们将DHT11数据线连接到PA1引脚,将时钟源设置为HSI。在主循环中,我们每2秒钟读一次DHT11数据,并将温度和湿度打印到串口终端。
最后,使用ST-Link将生成的代码烧写到STM32F103C8T6开发板上即可。