STM32F103C8T6 DHT11模块 HAL cubeMX(学习记录)

一、实验现象:

        本实验即可用串口显示输出数据,同时也可使用OLED进行显示,实验现象如下:

        其中,XCOM中显示的四个数据的含义分别为:湿度整数,湿度小数,温度整数,温度小数。湿度小数部分固定显示为0,温度小数部分有显示。(查了一下,湿度的小数部分就是没有的^-^)

二、硬件准备:

        实现本次实验需要以下五个硬件,分别是:

        STM32F103C8T6最小系统板,DHT11温湿度传感器模块,OLED,USB-TTL模块,STLINK。

三、接线:

        cube部分配置不做展示(因为只是开了一个I2C1和USART1),不过多赘述。

四、DHT11模块:

        总结一下:看着很复杂,但其实很简单,DHT11是单总线也就是一根线进行通信,单片机IO口设置为推挽输出后发送起始信号(想要接收一次数据),而后IO改变配置方式为上拉输入,读取应答信号,之后连续接收40bit的数据,每8位为一组,分别是:湿度整数,湿度小数,温度整数,温度小数,校验和,最后IO配置为推挽输出,将总线电平拉高等待下一次读取。其中值得注意的是,DHT11表示0和1的方式有点特殊,是通过高电平的持续时间不同来进行数据的表示,0为23-27us,1为68-74us,如图6所示。DHT11说明书地址如下:

DHT11_PDF_数据手册_Datasheet_规格书 - 半导小芯 (semiee.com)(点击打开不下载也能看)

        OLED的驱动程序不做过多解释,但是本实验的工程中的OLED的驱动是可以正常使用的,但是唯独一点就是他不好用@_@,非紧急情况不推荐使用...如果真的想用的话,中文显示部分能正常使用,但是是有一点问题的,谁用谁知道,我不说,给你们挖个坑嘻嘻^_^,还有要注意中文的取模格式,在oled.c中有做注释

五、程序部分:

        本实验是采用cubeMX+Keil来进行的,对于本篇博客,只展示其中的DHT11.c的程序,具体程序请参考整个工程,工程地址在最后。

DHT11.c

#include "DHT11.h"
#include "main.h"
//粗延时函数,微秒
void HAL_Delay_us(uint16_t time)
{    
   uint16_t i=0;  
   while(time--)
   {
      i=10;  
      while(i--) ;    
   }
}

//起始信号
void DHT11_Start()
{
	MX_GPIO_Init_OUT();                                             //GPIOB GPIO_PIN_12 配置为推挽输出
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);            //先拉高
	HAL_Delay(1);                                                   //延时(随便,只是拉高)
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);          //拉低,起始信号
	HAL_Delay(20);                                                  //至少18ms
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);            //然后拉高
	HAL_Delay_us(30);                                               //等待20-40us
	MX_GPIO_Init();                                                 //GPIOB GPIO_PIN_12 配置为浮空输入 
}

char DHT11_Rec_Byte(void)
{
	unsigned char i = 0;
	unsigned char data;
	
	for(i=0;i<8;i++)                                                //1个数据就是1个字节byte,1个字节byte有8位bit
	{
		while( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == RESET );     //从1bit开始,低电平变高电平,等待低电平结束
		HAL_Delay_us(30);                                           //延迟30us是为了区别数据0和数据1,0只有26~28us
		
		data <<= 1;                                                 //左移一位
		
		if( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == 1 )             //如果过了30us还是高电平的话就是数据1
		{
			data |= 1;                                              //数据+1
		}
		
		while( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == 1 );         //高电平变低电平,等待高电平结束
	}
	
	return data;
}

//获取数据
void DHT11_REC_Data(void)
{
	unsigned char R_Z,R_X,T_Z,T_X;
	unsigned char RZ,RX,TZ,TX,CHECK;
	
	DHT11_Start();                                                  //主机发送信号
	
	if( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == RESET )             //判断DHT11是否响应
	{
		while( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == 0);          //低->高,等待低电平结束
		while( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == 1);          //高->低,等待高电平结束
		
		R_Z   =   DHT11_Rec_Byte();
		R_X   =   DHT11_Rec_Byte();
		T_Z   =   DHT11_Rec_Byte();
		T_X   =   DHT11_Rec_Byte();
		CHECK =   DHT11_Rec_Byte();                                 //接收5个数据
		 
		MX_GPIO_Init_OUT();
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);      //当最后一bit数据传送完毕后,DHT11拉低总线 50us
		HAL_Delay_us(55);                                           //这里延时55us
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);        //随后总线由上拉电阻拉高进入空闲状态。
		
		if(R_Z + R_X + T_Z + T_X == CHECK)                          //和检验位对比,判断校验接收到的数据是否正确
		{
			RZ = R_Z;
			RX = R_X;
			TZ = T_Z;
			TX = T_X;
		}
	}
	
	printf("RZ = %d, RX = %d, TZ = %d, TX = %d\n\r",RZ,RX,TZ,TX);
	oled_show_chinese(0, 1, 0);                                     //温
	oled_show_chinese(20, 1, 1);                                    //度
	oled_show_chinese(0, 4, 2);                                     //湿
	oled_show_chinese(20, 4, 1);                                    //度
	oled_show_string(40, 1, ":", 2);                                //:
	oled_show_string(40, 4, ":", 2);                                //:
	oled_show_string(76, 1, ".", 2);                                //.
	oled_show_string(76, 4, ".", 2);                                //.
	oled_show_char(60, 1, TZ/10+48, 16);                            //温度整数第十位
	oled_show_char(68, 1, TZ%10+48, 16);                            //温度整数第个位
	oled_show_char(84, 1, TX+48, 16);								//温度小数							
	oled_show_chinese(92, 1, 3);                                    //℃
	oled_show_char(60, 4, RZ/10+48, 16);                            //湿度整数第十位
	oled_show_char(68, 4, RZ%10+48, 16);                            //湿度整数第个位
	oled_show_char(84, 4, RX+48, 16);								//湿度小数								
	oled_show_string(96, 4, "%", 2);                                //%

}

main.c

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	oled_init();
	
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		DHT11_REC_Data();
		HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

本篇的程序是移植的下面的博客,对其中的部分进行了改动,同时将标准库移植为了HAL库。

链接为:DHT11详细介绍(内含51和STM32代码)-CSDN博客

七、总结

        DHT11确实很简单,真的(骗人是小狗!),但是说实话感觉这个传感器精度不高,温度误差正负两度说实话我觉得还是很大的,在我看来温度误差在0.5℃才是合适的好用的,但是毕竟人家价钱在那里摆着呢,价格抗打。对于本实验是有缺点存在的,最大的缺点就是HAL库的优点,可移植性很差,所以日后的文章我会尽量往可移植方面多靠拢靠拢 (*——*) ,OLED的驱动日后有时间在搞吧(有能用的我实在是懒得整hh..)。工程链接放在下面了,需要自取。   ^_^

工程链接:

链接:https://pan.baidu.com/s/1rTXTXtZNHvM4Kc-_ZnPhQw?pwd=hs2z 
提取码:hs2z

  • 39
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
好的,以下是stm32f103c8t6DHT11温湿度传感器的连接及程序实现教程。 1.连接 将DHT11的VCC连接到stm32f103c8t6的5V电源,GND连接到GND,数据线连接到PA1。 2.程序实现 首先需要在stm32f103c8t6中配置GPIO的输入输出模式和中断模式。具体配置方法可以参考资料进行学习。 下面是使用STM32CubeMX生成的代码,实现DHT11的温湿度读取。 ```c /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "dht11.h" /* Private variables ---------------------------------------------------------*/ TIM_HandleTypeDef htim2; UART_HandleTypeDef huart1; /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART1_UART_Init(void); static void MX_TIM2_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); MX_TIM2_Init(); HAL_TIM_Base_Start_IT(&htim2); while (1) { } } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) { DHT11_Start(); uint8_t check = DHT11_Check(); if (check == 1) { printf("Temperature = %d.%dC, Humidity = %d.%d%%\r\n", DHT11_Read_Temp() / 10, DHT11_Read_Temp() % 10, DHT11_Read_Humidity() / 10, DHT11_Read_Humidity() % 10); } else { printf("DHT11 check error!\r\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(); } } static void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 7199; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 2000; 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(); } } static void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); /*Configure GPIO pin : PA1 */ GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } ``` 在main函数中,启动了TIM2定时器,并在定时器中断中读取DHT11传感器的温湿度值。DHT11_Start()函数用于启动传感器,并且等待40us,然后通过DHT11_Check()函数检测传感器的响应信号是否正确,如果正确则通过DHT11_Read_Temp()和DHT11_Read_Humidity()函数读取温湿度值。 最后,通过串口打印函数printf()将温湿度值输出。 这就是stm32f103c8t6DHT11温湿度传感器的连接及程序实现教程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值