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

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值