stm32解析dht11传感器1-wire协议

STM32 电子创客营 5256次浏览 已收录 0个评论 扫描二维码

    要做个模块stm32dht11温湿度传感器的。这个传感器使用的是1-wire协议,也就是数据传输只需要一根线就可以了。这个和ds18b20比较相似,但是比18b20要简单一些。因为他的单线数据都是从dht11发送到主机这边来的,主机不需要给它发数据。

    百度了一下,在网上大部分例程都是用的io加延时拉模拟他的时序实现的通信。我看到延时这样的函数就很不喜欢,因为我单片机加了还要做其他事情。加了延时就注定要牺牲掉做事儿的时间,导致效率低下。于是乎想到1-wire协议也是高低电平变化,通过判断高电平的时间长短来确定是0还是1,这和红外解码也类似。大部分红外解码用的就是pwm捕获功能来解的,那么这个1-wire协议应该也可以。于是就按这个思路做了下实验,果然可以。

   思路呢我是用了两个单片机io口接到dht11的数据线(一个也可以,但是就是程序上麻烦一点,需要变化io口的输入输出状态)。我用了两个io口那就是一个作为输入一个作为输出。这个输出就一个功能,就是给到dht11一个复位信号。这个信号拉低大于18ms再拉高dht11就会温湿度数据输出来,这时候用到的就是单片机的另一个输入口。当然这个输入口一定是要有pwm捕获功能的,我选择的是pa2,是tim15的通道1.

stm32解析dht11传感器1-wire协议stm32解析dht11传感器1-wire协议stm32解析dht11传感器1-wire协议

    如上图所示就是stm32cubeMx的配置。这里需要重点关注的就是tim15的配置。这里的psc的值是控制计时器的频率的,我这里设置的48-1是因为我的单片机主频设置的是48mhz,这样定时器就是1us记一次数。counter priod这个值则是控制定时器溢出值,也就是计数器记到这个值以后就会重新从0开始记。这个值一定要大于dht11一个数据周期的最大值。比如dht11的0是低50us+高(26-28us),1是低50us+高80us。所以配置的最小值肯定也不能低于130。我们只要把这个数据周期给检测出来,那么我们就知道接收到的是0还是1了。

   检测思路是这样的:

   我先用单片机的输出口拉低一个20ms的低电平,然后再把输出口输出为高。这时候定时器的计数器清0并打开pwm捕获,这个捕获功能是只能检测上升沿或者下降沿的,我选择检测下降沿。两次下降沿之间的值就是dht11的一个数据周期。判断这个数据周期长短就可以判断出来就收到的是0还是1.看下我串口打印出来的结果:

stm32解析dht11传感器1-wire协议

    一共受到41个数据,第一个数据10us是因为是复位信号,所以不算数据,后面的1-41才是真正的dht11数据。可以看到74-76就可以判断为数据0 ,121就是代表数字1了。然后用在中断里面把这些0和1进行解析就可以的到完整的数据。

这是我的中断处理代码:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
		if(htim==&htim15)
		{
			valueBuf[valueCount] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
			valueCount++;
			if(valueCount>=42)  //接收到的编码数量够了41个,关闭定时器
			{
						HAL_TIM_IC_Stop_IT(htim,TIM_CHANNEL_1);
			}
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);
	    __HAL_TIM_SET_COUNTER(&htim15,0);
		}
}

还有我的main函数:

int main(void)
{

  /* USER CODE BEGIN 1 */
	uint8_t i=0;
  /* 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_TIM15_Init();
  MX_USART1_UART_Init();

  /* USER CODE BEGIN 2 */
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
	HAL_Delay(1);
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);
	HAL_Delay(20);
	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
	
	__HAL_TIM_SET_COUNTER(&htim15,0);
	HAL_TIM_IC_Start_IT(&htim15,TIM_CHANNEL_1);
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	
  while (1) 
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
		for(i=0;i<valueCount;i++)
		{
			printf("-----%d:%d-------\r\n",i,valueBuf[i]);
		}
		HAL_Delay(1000);

  }
  /* USER CODE END 3 */

}

  

    


转载请注明转自电子创客营:stm32解析dht11传感器1-wire协议! 了解我们点击这里

微信扫一扫关注我们的公众号:eemaker

stm32解析dht11传感器1-wire协议


喜欢 (4)or分享 (0)
电子创客营
关于作者:

您必须 登录 才能发表评论!