赞
踩
目录
3、DHT11检测起始信号(这里的DHT11_LOW,DHT11_HIGH 在下面的的第8点)
4、DHT11检测响应信号(这里的DHT11_IO_IN在下面的第8点)
8、IO口输出高、低电平以及读取IO口电平定义和需要添加的头文件
1、芯片:STM32F103C8T6
2、软件:STM32CubeMX软件
3、IDE : MDK_Keil软件
DHT11基本知识和原理
DHT11通讯方式
STM32CubeTIM和USART的配置
DHT11数据采集实现
建议连接线短语20m时用5K的上拉电阻,大于20m时根据实际情况使用合适的上拉电阻
DHT11的供电电压为 3.3~5v。传感器上电后,要等待1s,以越过不稳定状态在此期间无需发送任何指令。电源引脚(VDD,GND)之间可增加一个100uf电容,用以去耦滤波。
总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉 高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定 了数据位是0还是1.格式见下面图示.如果读取响应信号为高电平,则DHT11没有 响应,请检查线路是否连接正常.当最后一bit数据传送完毕后,DHT11拉低总线 50us,随后总线由上拉电阻拉高进入空闲状态。
1、 复制所用文件的.C和.H
2、每个功能生成独立的.C和.H文件
第二步的Moed设置GPIO_OUTPUT和GPIO_INPUT都可以,因为DHT11是单线双向的 ,所以在编写程序时我们需要改写的它IO模式。
5、USART配置
第二步 Mode设置为异步通信
首先来编写函数部分:
- /**
- * @brief us级延时函数
- * @param delay 控制延时的时长
- * @retval 无
- */
- void Delay_us(uint32_t udelay)
- {
- uint32_t startval,tickn,delays,wait;
-
- startval = SysTick->VAL;
- tickn = HAL_GetTick();
- delays =udelay * 72;
- if(delays > startval)
- {
- while(HAL_GetTick() == tickn)
- {
-
- }
- wait = 72000 + startval - delays;
- while(wait < SysTick->VAL)
- {
-
- }
- }
- else
- {
- wait = startval - delays;
- while(wait < SysTick->VAL && HAL_GetTick() == tickn)
- {
-
- }
- }
- }
100us:
10us:
1us:
- /**
- * @brief DATA引脚(PA7)设置为输出模式
- * @param 无
- * @retval 无
- */
- void DHT11_OUT(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
-
- GPIO_InitStruct.Pin = GPIO_PIN_7;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- }
- /**
- * @brief DATA引脚(PA7)设置为输入模式
- * @param 无
- * @retval 无
- */
- void DHT11_IN(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
-
- GPIO_InitStruct.Pin = GPIO_PIN_7;
- GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- }
- /**
- * @brief DHT11检测起始信号
- * @param 无
- * @retval 无
- */
- void DHT11_Strat(void)
- {
- DHT11_OUT(); //PA7设置为输出模式
- DHT11_LOW; //主机拉低总线
- HAL_Delay(20); //延迟必须大于18ms ;
- DHT11_HIGH; //主机拉高总线等待DHT11响应
- Delay_us(30);
- }
- /**
- * @brief DHT11发送响应信号
- * @param 无
- * @retval 返回值0/1 0:响应成功 1:响应失败
- */
- uint8_t DHT11_Check(void)
- {
- uint8_t retry = 0 ;
- DHT11_IN();
- //采用while循环的方式检测响应信号
- while(DHT11_IO_IN && retry <100) // DHT11会拉低 40us ~80us
- {
- retry++;
- Delay_us(1);//1us
- }
- if(retry>=100) //判断当DHT11延迟超过80us时return 1 , 说明响应失败
- {return 1;}
- else retry = 0 ;
-
- while(!DHT11_IO_IN && retry<100)// // DHT11拉低之后会拉高 40us ~80us
- {
- retry++;
- Delay_us(1);//1us
- }
-
- if(retry>=100)
- {return 1;}
- return 0 ;
- }
- /**
- * @brief DHT11读取一位数据
- * @param 无
- * @retval 返回值0/1 1:读取成功 0:读取失败
- */
- uint8_t DHT11_Read_Bit(void)
- {
- uint8_t retry = 0 ;
- while(DHT11_IO_IN && retry <100)//同上采用while循环的方式去采集数据
- {
- retry++;
- Delay_us(1);
- }
- retry = 0 ;
- while(!DHT11_IO_IN && retry<100)
- {
- retry++;
- Delay_us(1);
- }
-
- Delay_us(40); //结束信号,延时40us
- if(DHT11_IO_IN) return 1; //结束信号后,总线会被拉高 则返回1表示读取成功
- else
- return 0 ;
- }
- /**
- * @brief DHT11读取一个字节数据
- * @param 无
- * @retval 返回值:dat 将采集到的一个字节的数据返回
- */
- uint8_t DHT11_Read_Byte(void)
- {
- uint8_t i , dat ;
- dat = 0 ;
- for(i=0; i<8; i++)
- {
- dat <<= 1; //通过左移存储数据
- dat |= DHT11_Read_Bit();
- }
- return dat ;
- }
- /**
- * @brief DHT11读取数据
- * @param temp:温度值 humi :湿度值
- * @retval 返回值0/1 0:读取数据成功 1:读取数据失败
- */
- uint8_t DHT11_Read_Data(uint8_t* temp , uint8_t* humi)
- {
- uint8_t buf[5]; //储存五位数据
- uint8_t i;
- DHT11_Strat(); //起始信号
- if(DHT11_Check() == 0) //响应信号
- {
- for(i=0; i<5; i++)
- {
- buf[i] = DHT11_Read_Byte();
- }
- if(buf[0]+buf[1]+buf[2]+buf[3] == buf[4]) //校验数据
- {
- *humi = buf[0]; // 湿度
- *temp = buf[2]; // 温度
- }
- }else return 1;
-
- return 0 ;
- }
以上就是需要用到的函数部分的编写,接下来是一些声明和定义:
- /* Private define ------------------------------------------------------------*/
- /* USER CODE BEGIN PD */
- #define DHT11_HIGH HAL_GPIO_WritePin(GPIOA, DHT11_Pin, GPIO_PIN_SET) //输出高电平
- #define DHT11_LOW HAL_GPIO_WritePin(GPIOA, DHT11_Pin, GPIO_PIN_RESET)//输出低电平
-
- #define DHT11_IO_IN HAL_GPIO_ReadPin(GPIOA, DHT11_Pin)//读取IO口电平
-
- /* USER CODE END PD */
- /* Private includes ----------------------------------------------------------*/
- /* USER CODE BEGIN Includes */
- #include "stdio.h"
- #include "string.h"
-
- /* USER CODE END Includes */
-
- /* USER CODE BEGIN 1 */
- uint8_t temperature = 1; //温度
-
- uint8_t humidity = 1; //湿度
-
- uint8_t aTXbuf[32]; //串口发送缓存数组
-
- DHT11_Strat(void);
-
- /* USER CODE END 1 */
- /* Private function prototypes -----------------------------------------------*/
- void SystemClock_Config(void);
-
- void Delay_us(uint16_t delay); //us级延时函数
-
- //DHT11_DATA ,IO口设置为输出模式(这里的IO口指的是STM32CubeMX中配置的IO口)
- void DHT11_OUT(void);
-
- void DHT11_IN(void); //DHT11_Data IO设置为输入模式
- void DHT11_Strat(void); //主机发出起始信号
- uint8_t DHT11_Check(void); //DHT11发送响应信号
- uint8_t DHT11_Read_Bit(void); //读取DHT11一个BIT的数据
- uint8_t DHT11_Read_Byte(void); //读取DHT11一个Byte的数据
- uint8_t DHT11_Read_Data(uint8_t* temp , uint8_t* humi); //读取DHT11湿度和温度的数据
-
- /* USER CODE BEGIN PFP */
- while (1)
- {
- //接收DHT11的温度和湿度的值
- DHT11_Read_Data(&temperature , &humidity);
- //将数据存放到aTXbuf这个数组当中去。 不了解"sprintf"用法的可以去查一下...
- sprintf((char*)aTXbuf,"温度:%d℃,湿度: %d %%\r\n" ,temperature ,humidity);
- //将数据通过串口发送到主机上的串口助手
- HAL_UART_Transmit(&huart1, aTXbuf, strlen((const char*)aTXbuf), 200);
- //延时500ms
- HAL_Delay(500);
-
- /* USER CODE END WHILE */
-
- /* USER CODE BEGIN 3 */
- }
到这里DHT11的程序就编写完了 ,下面就来看看效果吧
通过本次DHT11温湿度传感器的学习,掌握了单线双向的数据通信方式,DHT11和主机之间数据通讯过程,而且在此过程中要注意延时函数的把控精度,在编写程序中DHT11数据读取方式,数据传输方式和数据存储方式,以及微秒级延迟函数的编写,本设计参考正点原子探索者开发板教程和STM32Cube高效开发指南(高级篇)。
- /* USER CODE END Header */
-
- /* Includes ------------------------------------------------------------------*/
- #include "main.h"
- #include "tim.h"
- #include "usart.h"
- #include "gpio.h"
-
- /* Private includes ----------------------------------------------------------*/
- /* USER CODE BEGIN Includes */
- #include "stdio.h"
- #include "string.h"
-
- /* USER CODE END Includes */
-
- /* Private typedef -----------------------------------------------------------*/
- /* USER CODE BEGIN PTD */
-
- /* USER CODE END PTD */
-
- /* Private define ------------------------------------------------------------*/
- /* USER CODE BEGIN PD */
-
- #define DHT11_HIGH HAL_GPIO_WritePin(GPIOA, DHT11_Pin, GPIO_PIN_SET)
- #define DHT11_LOW HAL_GPIO_WritePin(GPIOA, DHT11_Pin, GPIO_PIN_RESET)
-
- #define DHT11_IO_IN HAL_GPIO_ReadPin(GPIOA, DHT11_Pin)
-
- /* USER CODE END PD */
-
- /* Private macro -------------------------------------------------------------*/
- /* USER CODE BEGIN PM */
-
- /* USER CODE END PM */
-
- /* Private variables ---------------------------------------------------------*/
-
- /* USER CODE BEGIN PV */
-
- /* USER CODE END PV */
-
- /* Private function prototypes -----------------------------------------------*/
- void SystemClock_Config(void);
-
- void Delay_us(uint16_t delay);
- void DHT11_OUT(void);
- void DHT11_IN(void);
- void DHT11_Strat(void);
- uint8_t DHT11_Check(void);
- uint8_t DHT11_Read_Bit(void);
- uint8_t DHT11_Read_Byte(void);
- uint8_t DHT11_Read_Data(uint8_t* temp , uint8_t* humi);
-
- /* USER CODE BEGIN PFP */
-
- /* USER CODE END PFP */
-
- /* Private user code ---------------------------------------------------------*/
- /* USER CODE BEGIN 0 */
-
- /* USER CODE END 0 */
-
- /**
- * @brief The application entry point.
- * @retval int
- */
- int main(void)
- {
- /* USER CODE BEGIN 1 */
-
- uint8_t temperature = 1 ;
- uint8_t humidity = 1;
- uint8_t aTXbuf[32] ;
-
- /* 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_USART1_UART_Init();
- MX_TIM3_Init();
- /* USER CODE BEGIN 2 */
- DHT11_Strat();
- /* USER CODE END 2 */
-
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
-
- DHT11_Read_Data(&temperature , &humidity);
- sprintf((char*)aTXbuf,"温度:%d℃ , 湿度:%d %% \r\n" ,temperature ,humidity);
- HAL_UART_Transmit(&huart1, aTXbuf, strlen((const char*)aTXbuf), 200);
- HAL_Delay(500);
-
- /* USER CODE END WHILE */
-
- /* USER CODE BEGIN 3 */
- }
- /* USER CODE END 3 */
- }
-
- /**
- * @brief System Clock Configuration
- * @retval None
- */
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
-
- /** Initializes the CPU, AHB and APB busses clocks
- */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
- RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
- RCC_OscInitStruct.HSIState = RCC_HSI_ON;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
- RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
- /** Initializes the CPU, AHB and APB busses clocks
- */
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
- |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
-
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
- {
- Error_Handler();
- }
- }
-
- /* USER CODE BEGIN 4 */
-
- void Delay_us(uint16_t delay)
- {
- __HAL_TIM_DISABLE(&htim3);
- __HAL_TIM_SET_COUNTER(&htim3,0);
- __HAL_TIM_ENABLE(&htim3);
- uint16_t curCnt=0;
- while(1)
- {
- curCnt=__HAL_TIM_GET_COUNTER(&htim3);
- if(curCnt>=delay)
- break;
- }
- __HAL_TIM_DISABLE(&htim3);
- }
-
- void DHT11_OUT(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
-
- GPIO_InitStruct.Pin = GPIO_PIN_7;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- }
-
- void DHT11_IN(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
-
- GPIO_InitStruct.Pin = GPIO_PIN_7;
- GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- }
-
-
- void DHT11_Strat(void)
- {
- DHT11_OUT();
- DHT11_LOW;
- HAL_Delay(20);
- DHT11_HIGH;
- Delay_us(30);
- }
-
-
- uint8_t DHT11_Check(void)
- {
- uint8_t retry = 0 ;
- DHT11_IN();
-
- while(DHT11_IO_IN && retry <100)
- {
- retry++;
- Delay_us(1);//1us
- }
- if(retry>=100)
- {return 1;}
- else retry = 0 ;
-
- while(!DHT11_IO_IN && retry<100)
- {
- retry++;
- Delay_us(1);//1us
- }
-
- if(retry>=100)
- {return 1;}
- return 0 ;
- }
-
-
- uint8_t DHT11_Read_Bit(void)
- {
- uint8_t retry = 0 ;
- while(DHT11_IO_IN && retry <100)
- {
- retry++;
- Delay_us(1);
- }
- retry = 0 ;
- while(!DHT11_IO_IN && retry<100)
- {
- retry++;
- Delay_us(1);
- }
- Delay_us(40);
- if(DHT11_IO_IN) return 1;
- else
- return 0 ;
- }
-
-
- uint8_t DHT11_Read_Byte(void)
- {
- uint8_t i , dat ;
- dat = 0 ;
- for(i=0; i<8; i++)
- {
- dat <<= 1;
- dat |= DHT11_Read_Bit();
- }
- return dat ;
- }
-
-
- uint8_t DHT11_Read_Data(uint8_t* temp , uint8_t* humi)
- {
- uint8_t buf[5];
- uint8_t i;
- DHT11_Strat();
- if(DHT11_Check() == 0)
- {
- for(i=0; i<5; i++)
- {
- buf[i] = DHT11_Read_Byte();
- }
- if(buf[0]+buf[1]+buf[2]+buf[3] == buf[4])
- {
- *humi = buf[0];
- *temp = buf[2];
- }
- }else return 1;
-
- return 0 ;
- }
-
- /* USER CODE END 4 */
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。