DHT12 驱动程序,STM32,Arduino



用于驱动奥松电子生产的的DHT12传感器





单线方式传输数据,SCL接10k欧姆电阻到GND拉低




Keil 5


DHT12.h

#ifndef _DHT12_H_
#define _DHT12_H_
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "stdio.h"

//IO方向设置
#define SDA_IN()  {GPIOB->CRH&=0XF0FFFFFF;GPIOB->CRH|=0x08000000;}//上下拉输入
#define SDA_OUT() {GPIOB->CRH&=0XF0FFFFFF;GPIOB->CRH|=0x03000000;}//通用推挽输出


//IO操作函数
#define IIC_SCL    PBout(13) //SCL输出	
#define SEND_SDA   PBout(14) //SDA输出	 
#define READ_SDA   PBin(14)  //SDA输入 



void DHT12_Init(void);//初始化SDA(PB14),CLK(PB13)
u8 DHT12_Rdata(void);
u8 DHT12_READ(void);




#endif	//_DHT12_H_




DHT12.c

#include "DHT12.h"


float Temprature,Humi;//定义温湿度变量 ,此变量为全局变量
u8 Sensor_AnswerFlag=0;//定义传感器响应标志
u8 Sensor_ErrorFlag;  //定义读取传感器错误标志


/********************************************\
|* 功能: 初始化SDA(PB14),CLK(PB13)	        *|
\********************************************/
void DHT12_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );//使能GPIOB	
	   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14;//PB13,PB14
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ;   //开漏输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_ResetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14); 	//PB13,PB14 输出低(SCL上电立即拉低)
}


/********************************************\
|* 功能: 读传感器发送的单个字节	        *|
\********************************************/
u8 DHT12_Rdata(void)
{
	u8 i;
	u16 j;
	u8 data=0,bit=0;
	
	for(i=0;i<8;i++)
	{
		while(!READ_SDA)//检测上次低电平是否结束
		{
			if(++j>=50000) //防止进入死循环
			{
				break;
			}
		}
		//延时Min=26us Max70us 跳过数据"0" 的高电平		 
		delay_us(30);

		//判断传感器发送数据位
		bit=0;
		if(READ_SDA)
		{
			bit=1;
		}
		j=0;
		while(READ_SDA)	//等待高电平结束
		{
			if(++j>=50000) //防止进入死循环
			{
				break;
			}		
		}
		data<<=1;
		data|=bit;
	}
	return data;
}


/********************************************\
|* 功能:DHT12读取温湿度函数       *|
\********************************************/
//变量:Humi_H:湿度高位;Humi_L:湿度低位;Temp_H:温度高位;Temp_L:温度低位;Temp_CAL:校验位
//数据格式为:湿度高位(湿度整数)+湿度低位(湿度小数)+温度高位(温度整数)+温度低位(温度小数)+ 校验位
//校验:校验位=湿度高位+湿度低位+温度高位+温度低位
u8 DHT12_READ(void)
{
	u32 j;
	u8 Humi_H,Humi_L,Temp_H,Temp_L,Temp_CAL,temp;

	//主机发送起始信号
	SDA_OUT() //设为输出模式
	SEND_SDA=0;	//主机把数据总线(SDA)拉低
	delay_ms(20);//拉低一段时间(至少18ms), 通知传感器准备数据
	SEND_SDA=1;	 //释放总线
	SDA_IN();	//设为输入模式,判断传感器响应信号
	delay_us(30);//延时30us

	Sensor_AnswerFlag=0;	//传感器响应标志
	//判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行	  
	if(READ_SDA==0)
	{
		Sensor_AnswerFlag=1;	//收到起始信号

		j=0;
		while((!READ_SDA)) //判断从机发出 80us 的低电平响应信号是否结束	
		{
			if(++j>=500) //防止进入死循环
			{
				Sensor_ErrorFlag=1;
				break;
			}
		}

		j=0;
		while(READ_SDA)//判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
		{
			if(++j>=800) //防止进入死循环
			{
				Sensor_ErrorFlag=1;
				break;
			}		
		}
		//接收数据
		Humi_H=DHT12_Rdata();
		Humi_L=DHT12_Rdata();
		Temp_H=DHT12_Rdata();	
		Temp_L=DHT12_Rdata();
		Temp_CAL=DHT12_Rdata();

		temp=(u8)(Humi_H+Humi_L+Temp_H+Temp_L);//只取低8位

		if(Temp_CAL==temp)//如果校验成功,往下运行
		{
			Humi=Humi_H*10+Humi_L; //湿度
	
			if(Temp_L&0X80)	//为负温度
			{
				Temprature =0-(Temp_H*10+((Temp_L&0x7F)));
			}
			else   //为正温度
			{
				Temprature=Temp_H*10+Temp_L;//为正温度
			}
			//判断数据是否超过量程(温度:-20℃~60℃,湿度20%RH~95%RH)
			if(Humi>950) 
			{
			  Humi=950;
			}
			if(Humi<200)
			{
				Humi =200;
			}
			if(Temprature>600)
			{
			  Temprature=600;
			}
			if(Temprature<-200)
			{
				Temprature = -200;
			}
			Temprature=Temprature/10;//计算为温度值
			Humi=Humi/10; //计算为湿度值
			printf("\r\n温度为:  %.1f  ℃\r\n",Temprature); //显示温度
			printf("湿度为:  %.1f  %%RH\r\n",Humi);//显示湿度	
		}
		
		else
		{
		 	printf("CAL Error!!\r\n");
			printf("%d \r%d \r%d \r%d \r%d \r%d \r\n",Humi_H,Humi_L,Temp_H,Temp_L,Temp_CAL,temp);
		}
	}
	else
	{
		Sensor_ErrorFlag=0;  //未收到传感器响应
		printf("Sensor Error!!\r\n");
	}

	return 1;
}






Arduino IDE 1.8.0

#define u8 unsigned short
#define u16 unsigned int
#define u32 unsigned long
const int DHT12Pin = 5;


int DHT12_flag = 0;
int DHT12_error = 0;
void DHT12_Init()
{
  pinMode(DHT12Pin, OUTPUT);
  digitalWrite(DHT12Pin, LOW);
  delay(50);
}


u8 DHT12_Rdata(void)
{
  u8 i;
  u16 j;
  u8 data = 0;
  u8 dbit = 0;
  pinMode(DHT12Pin, INPUT);
  for (i = 0; i < 8; i++)
  {
    while (digitalRead(DHT12Pin) == LOW) //check the last low state is over
    {
      if (++j >= 50000)
      {

      }
    }
    delayMicroseconds(50);//delay 26-70us,to overed data0 high level

    dbit = 0;
    if (digitalRead(DHT12Pin) == HIGH)
    {
      dbit = 1;
    }
    while (digitalRead(DHT12Pin) == HIGH) //等待高电平结束
    {
      if (++j >= 50000) //防止进入死循环
      {
        break;
      }
    }
    data <<= 1;
    data |= dbit;

  }
  return data;
}

u8 DHT12_ReadTemp()
{
  u32 j;
  double Humi=0,Temprature =0;
  u8 Humi_H, Humi_L, Temp_H, Temp_L, Temp_CAL, temp;
  pinMode(DHT12Pin, OUTPUT);
  digitalWrite(DHT12Pin, LOW);
  delay(20);
  digitalWrite(DHT12Pin, HIGH);
  pinMode(DHT12Pin, INPUT);
  delayMicroseconds(30);
  DHT12_flag = 0;
  if (digitalRead(DHT12Pin) == LOW)
  {
    DHT12_flag = 1;

    j = 0;
    while (digitalRead(DHT12Pin) == LOW) //判断从机发出 80us 的低电平响应信号是否结束
  {
    if (++j >= 500) //防止进入死循环
      {
        DHT12_error = 1;
        break;
      }
    }
    j = 0;
        while (digitalRead(DHT12Pin) == HIGH) //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
  {
    if (++j >= 800) //防止进入死循环
      {
        DHT12_error = 1;
        break;
      }
    }
    Humi_H = DHT12_Rdata();
             Humi_L = DHT12_Rdata();
             Temp_H = DHT12_Rdata();
             Temp_L = DHT12_Rdata();
             Temp_CAL = DHT12_Rdata();
             temp = (u8)(Humi_H + Humi_L + Temp_H + Temp_L);

             //Verify
             //if success ,continue
             if (Temp_CAL == temp) //如果校验成功,往下运行
  {
    Humi = Humi_H * 10 + Humi_L; //湿度

    if (Temp_L & 0X80) //为负温度
      {
        Temprature = 0 - (Temp_H * 10 + ((Temp_L & 0x7F)));
      }
      else   //为正温度
      {
        Temprature = Temp_H * 10 + Temp_L; //为正温度
      }
      //判断数据是否超过量程(温度:-20℃~60℃,湿度20%RH~95%RH)
      if (Humi > 950)
      {
        Humi = 950;
      }
      if (Humi < 200)
      {
        Humi = 200;
      }
      if (Temprature > 600)
      {
        Temprature = 600;
      }
      if (Temprature < -200)
      {
        Temprature = -200;
      }
      Temprature = Temprature / 10; //计算为温度值
      Humi = Humi / 10; 
      Serial.print("\r\n温度为: ");
      Serial.print(Temprature);
      Serial.print("  ℃\r\n"); 
      Serial.print("湿度为: ");
      Serial.print(Humi);
      Serial.print(" RH\r\n"); 
    }
    else
    {
      Serial.print("CAL Error!!\r\n");
      //Serial.print("%d \r%d \r%d \r%d \r%d \r%d \r\n", Humi_H, Humi_L, Temp_H, Temp_L, Temp_CAL, temp);
    }
  }
  else
  {
    DHT12_error = 0;
    Serial.print("Sensor Error!!\r\n");
  }

  return 1;
}



void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200);
  DHT12_Init();

}

void loop()
{
  // put your main code here, to run repeatedly:
  delay(1000);
  DHT12_ReadTemp();
}





  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
驱动DHT11传感器,首先需要连接DHT11传感器到STM32的GPIO引脚上。然后,需要编写STM32的代码来读取DHT11传感器的数据。 以下是一个简单的代码示例,可以读取DHT11传感器的数据: ```c #include "stm32f10x.h" #define DHT11_DATA_PIN GPIO_Pin_0 #define DHT11_DATA_PORT GPIOA void delay_us(uint32_t us) { // 延时函数,us为微秒数 uint32_t i; for (i = 0; i < us * 8; i++); } void DHT11_start() { // 发送起始信号 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = DHT11_DATA_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11_DATA_PORT, &GPIO_InitStructure); GPIO_ResetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); delay_us(18000); GPIO_SetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); delay_us(20); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(DHT11_DATA_PORT, &GPIO_InitStructure); } uint8_t DHT11_read_bit() { // 读取一个位的数据 while(GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == RESET); delay_us(40); if(GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == SET) { while(GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == SET); return 1; } else { return 0; } } uint8_t DHT11_read_byte() { // 读取一个字节的数据 uint8_t i, byte = 0; for (i = 0; i < 8; i++) { byte <<= 1; byte |= DHT11_read_bit(); } return byte; } uint8_t DHT11_read(uint8_t *humidity, uint8_t *temperature) { // 读取温湿度数据 uint8_t data[5]; uint8_t i; DHT11_start(); if(GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == RESET) { while(GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == RESET); while(GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == SET); for (i = 0; i < 5; i++) { data[i] = DHT11_read_byte(); } if(data[0] + data[1] + data[2] + data[3] == data[4]) { *humidity = data[0]; *temperature = data[2]; return 1; } else { return 0; } } else { return 0; } } int main(void) { uint8_t humidity, temperature; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); while(1) { if(DHT11_read(&humidity, &temperature)) { // 读取成功 } else { // 读取失败 } } } ``` 在这个代码示例中,首先定义了DHT11传感器的引脚和端口。然后,定义了一些辅助函数,如延时函数、发送起始信号和读取一个位数据等。最后,在主函数中循环读取DHT11传感器的温湿度数据。 需要注意的是,DHT11传感器的数据读取需要严格按照一定的时间序列进行,否则可能会出现读取错误。因此,在编写代码时需要仔细调试和测试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值