首页 > 编程知识 正文

dht11和ds18b20区别,多个dht11同时使用

时间:2023-05-05 13:35:48 阅读:140987 作者:1195

DHT11是具有校正后的数字信号输出的温湿度传感器。 其精度湿度5%RH、温度2、量程湿度20-90%RH、温度0~50。

由于DHT11利用单总线协议,所以有严格的时机。

首先,主机必须发送至少18ms的低电平。 在此过程中,在DHT11内部完成AD转换等操作并提升主机后,将有20-40us的时间。 该时间用于主机切换输入输出,在主机释放总线控制权时(此时主机处于输入状态,总线由上拉电阻拉起),DHT11将总线下拉,正常下拉后,开始准备发送数据

具体的传输步骤如下。 这里,数据0和数据1根据高电平的持续时间来判断。

一个bit数据被发送后,下拉总线。 反过来说,应该是先下调一段时间再开始采样。

数据0的显示方式:

数据1的显示方法:

知道时机后开始写代码:

这里使用stm32f4系列的核心板,将3.3V电源连接到DHT11,将DHT11连接到PE9。

头文件定义要使用的函数和输入/输出模式切换操作,并直接写入寄存器更改。

# ifndef _ DHT 11 _ h # define _ DHT 11 _ h # include ' sys.h '/io方向设置# defined ht11 _ io _ in ({ gpioe-mod din ) } GPP }//PE9输入模式#define DHT11_IO_OUT () gpioe-moder=~(3)9*2) ); GPIOE-MODER|=19*2; } //PE9输出模式IO操作函数#definedht11_dq_outPEout(/数据端口PE9 #defineDHT11_DQ_IN PEin(9) /数据端口pe9 _ 8d ht11 _ ou d //读取温湿度U8DHT11_read_byte(void ); 读出//1字节u8DHT11_read_bit(void )//1比特u8DHT11_check(void ); //DHT 11检测有无void DHT 11 _ rst (void ); 重置与DHT11 #endif对应的c文件:

# include ' DHT 11.h ' # include ' delay.h ' /复位DHT11voidDHT11_rst(void ) { DHT11_IO_OUT ) }; //SET OUTPUT DHT11_DQ_OUT=0; 降低//dqdelay_ms(20 )//最低18ms DHT11_DQ_OUT=1; //dq=1delay_us(30; //主机等待20~40us}//DHT11的响应//未检测到返回1:DHT11的存在//返回03360u8DHT11_check(void ) ) { u8 retry=0; DHT11_IO_IN (; //setinputwhile (DHT 11 _ dq _ in retry 100 )//DHT11为40至80us { retry; dlay_us(1); (; 返回=100 (if )返回1; else retry=0; while (! 降低DHT11_dq_inretry100//DHT11再次降低40~80us{retry; dlay_us(1); (; 返回=100 (if )返回1; 返回0; 从DHT11读取1位//返回值:1/0u8DHT11_read_bit(void ) { u8 retry=0; while(DHT11_dq_in{retry100 ) /等待变为低电平) retry; dlay_us(1); (}retry=0; while (! 等待DHT11_DQ_INretry100成为高电平{retry; dlay_us(1); }Delay_us(40; //40usif(DHT11_dq_in ) return 1; else return 0; 从DHT11读取1字节//返回值:读取的数据u8DHT11_read_byte(void ) u8I、dat; dat=0; for(I=0; i8; I ) { dat=1; dat|=DHT11_Read_Bit (; } return dat; 从DHT11返回原始数据//temp:温度值(范围:0~50)//humi:湿度值)范围:20%~90%返回值: 0,正常; 1、读取失败的U8DHT11_read_data(U8*temp,u8 *humi ) U8buf(5); u8 i; DHT11_Rst (; if(DHT11_check(==0) ) for ) I=0

;i<5;i++)//读取40位数据{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; }//初始化DHT11的IO口 DQ 同时检测DHT11的存在//返回1:不存在//返回0:存在 u8 DHT11_Init(void){GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOG时钟 //GPIOF9,F10初始化设置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化DHT11_Rst(); return DHT11_Check();}

注意手册给出的电气特性:
DHT11采样间隔要大于1s!!!

为了测试DHT11运行时间,这里使用定时器做测试,定时器部分代码如下:

void mhdhj7_Int_Init(u16 arr,u16 psc){ NVIC_InitTypeDef NVIC_InitStructure; mhdhj_TimeBaseInitTypeDef mhdhj_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_mhdhj7, ENABLE);//mhdhj7时钟使能 //定时器mhdhj7初始化 mhdhj_TimeBaseStructure.mhdhj_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 mhdhj_TimeBaseStructure.mhdhj_Prescaler =psc; //设置用来作为mhdhjx时钟频率除数的预分频值 mhdhj_TimeBaseStructure.mhdhj_ClockDivision = mhdhj_CKD_DIV1; //设置时钟分割:TDTS = Tck_rxdhb mhdhj_TimeBaseStructure.mhdhj_CounterMode = mhdhj_CounterMode_Up; //mhdhj向上计数模式 mhdhj_TimeBaseInit(mhdhj7, &mhdhj_TimeBaseStructure); //根据指定的参数初始化mhdhjx的时间基数单位 mhdhj_ITConfig(mhdhj7,mhdhj_IT_Update,ENABLE ); //使能指定的mhdhj7中断,允许更新中断 mhdhj_Cmd(mhdhj7,ENABLE);//使能定时器7 NVIC_InitStructure.NVIC_IRQChannel = mhdhj7_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//子优先级1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能 NVIC_Init(&NVIC_InitStructure);//根据指定的参数初始化VIC寄存器}int rxdhbeFlow=0;void mhdhj7_IRQHandler(void){ if (mhdhj_GetITStatus(mhdhj7, mhdhj_IT_Update) != RESET)//是更新中断 { rxdhbeFlow++; mhdhj_ClearITPendingBit(mhdhj7, mhdhj_IT_Update ); //清除mhdhj7更新中断标志 }}

上面的代码用于简单的定时。

main函数内容如下:

int main(void){ u8 temperature=0; u8 humidity=0; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2 delay_init(168); //初始化延时函数 uart_init(115200);//初始化串口波特率为115200DHT11_Init();//初始化DHT11 mhdhj7_Int_Init(10000-1,84-1);//10ms中断一次 while(1) { rxdhbeFlow=0; mhdhj7->CNT=0; mhdhj_Cmd(mhdhj7, ENABLE); //使能定时器7 DHT11_Read_Data(&temperature,&humidity);//读取温湿度值 mhdhj_Cmd(mhdhj7, DISABLE); //使能定时器7 printf("using rxdhbe:%8d us ",rxdhbeFlow*10000+mhdhj7->CNT); printf("temperature:%2d humidity:%2drn",temperature,humidity); delay_ms(500); delay_ms(500); delay_ms(500); }}

其中的3个delay_ms(500)用于超过1s的延时。
实际输出结果如下:

using rxdhbe: 23765 us temperature:24 humidity:57using rxdhbe: 23767 us temperature:24 humidity:57using rxdhbe: 23766 us temperature:24 humidity:57using rxdhbe: 23720 us temperature:24 humidity:56using rxdhbe: 23767 us temperature:24 humidity:57using rxdhbe: 23766 us temperature:24 humidity:57using rxdhbe: 23722 us temperature:24 humidity:56using rxdhbe: 23766 us temperature:24 humidity:57using rxdhbe: 23767 us temperature:24 humidity:57using rxdhbe: 23766 us temperature:24 humidity:57using rxdhbe: 23767 us temperature:24 humidity:57using rxdhbe: 23765 us temperature:24 humidity:57using rxdhbe: 23766 us temperature:24 humidity:57using rxdhbe: 23767 us temperature:24 humidity:57using rxdhbe: 23766 us temperature:24 humidity:57using rxdhbe: 23767 us temperature:24 humidity:57using rxdhbe: 23766 us temperature:24 humidity:57using rxdhbe: 23767 us temperature:24 humidity:57using rxdhbe: 23766 us temperature:24 humidity:57using rxdhbe: 23767 us temperature:24 humidity:57using rxdhbe: 23766 us temperature:24 humidity:57using rxdhbe: 23767 us temperature:24 humidity:57using rxdhbe: 23766 us temperature:24 humidity:57using rxdhbe: 23767 us temperature:24 humidity:57

可以看出即使除去20ms的开始信号,整个读写过程也要接近4ms,而且整个单总线过程非常严格,不允许被打断,所以在使用的时候一定要小心,慎用中断!

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。