打印
[STM8]

STM8S208驱动DHT11

[复制链接]
2920|24
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 冰封小肥牛 于 2017-10-3 12:37 编辑
<div>自己做了一块板子,目的是使用STM8S208驱动DHT11温湿度传感器,但是现在的问题是DHT11复位之后,无法在MCU端口读取到DHT11的低电平响应,检查了很长一段时间也没发现啥问题,所有特来论坛请教</div><div><b>
</b></div><div>
</div><div>#include "DHT11.h"
#include "delay.h"
#include "iostm8s208c8.h"

/*
PB7设置位推挽输出模式
*/
void DQ_out()
{
  PB_DDR_bit.DDR7 = 1;
  PB_CR1_bit.C17 = 1;
  PB_CR2_bit.C27 = 0;
}


/*
PB7设置为浮空输入模式
*/
void DQ_in()
{
  PB_DDR_bit.DDR7 = 0;
  PB_CR1_bit.C17 = 0;
  PB_CR2_bit.C27 = 0;
}


/*
DHT11起始信号
*/
void DHT11_start(void)
{
  DQ_out();                          //PB7设置为输出模式
  PB_ODR_bit.ODR7 = 0;              //拉低PB7
  delay_ms(18);                    //延时18ms
  PB_ODR_bit.ODR7 = 1;            //拉高延时30us
  delay_us(30);
  
}


/*DHT11响应函数
返回1:接受失败
返回0:成功
*/
u8 DHT11_check()
{
  u8 retry = 0;
  DQ_in();                              //PB7设置为浮空输入模式
  while(PB_IDR_bit.IDR7 && retry<100)   //在此等待DHT11拉低总线电平
  {
    retry++;
    delay_us(1);
  }
  if(retry>=100) return 1;
  else retry = 0;
  while(!PB_IDR_bit.IDR7 && retry<100)  //等待DHT11拉高总线电平
  {
    retry++;
    delay_us(1);
  }
  if(retry>=100) return 1;
  return 0;
}

/*DHT11读取一个位*/
u8 DHT11_read_bit()
{
  u8 retry = 0;
  while(PB_IDR_bit.IDR7 && retry<100)
  {
    retry++;
    delay_us(1);
  }
  retry = 0;
  while(!PB_IDR_bit.IDR7 && retry<100)
  {
    retry++;
    delay_us(1);
  }
  delay_us(40);
  if(PB_IDR_bit.IDR7)return 1;
  else return 0;
}

/*DHT11读取一个字节*/
u8 DHT11_read_byte()
{
  u8 dat = 0;
  u8 i;
  for(i=0;i<8;i++)
  {
    dat<<=1;
    dat |= DHT11_read_bit();
  }
  return dat;
}</div>

CAN.rar

338.23 KB

程序代码,编译环境IAR

沙发
一路向北lm| | 2017-10-3 14:45 | 只看该作者
这代码是楼主自己编写的还是参考人家的修改的?

使用特权

评论回复
板凳
冰封小肥牛|  楼主 | 2017-10-3 15:42 | 只看该作者
一路向北lm 发表于 2017-10-3 14:45
这代码是楼主自己编写的还是参考人家的修改的?

前面的起始函数都是我自己编写的,读取的是参照的

使用特权

评论回复
地板
捉虫天师| | 2017-10-3 20:24 | 只看该作者
//复位DHT11 void DHT11_RST() {      TIM4_CR1 = 0x00;                      //关闭定时器    TIM4_CNTR = 0;                        //保证下次的第一个数据位的准确    DATA_SET;                              //ODR设置为1    DATA_OUT();                            //推挽输出模式,此时输出高电平    DATA_CLR;                                //此时处于主机输出模式,总线拉低    TIM2_Delayus(20000);                     //拉低20毫秒     DATA_SET;                                //释放总线     TIM2_Delayus(40);                     //释放总线以后等待40微秒DHT会发出响应信号 }

使用特权

评论回复
5
捉虫天师| | 2017-10-3 20:24 | 只看该作者
//检测DHT11是否响应 uchar DHT11_CHECK() {      if(!DATA_GET)                       //如果顺利拉低,就说明有了响应   {   while((!DATA_GET)&&(outline<100))                    //先是低电平   {   TIM2_Delayus(1);   }   if(outline>90)                                       //起始信号超时退出   return 0;   outline = 0;   while((DATA_GET)&&(outline<100))                    //接着是高电平   {   TIM2_Delayus(1);   }   if(outline<90)   TIM4_CR1 = 0x81;                                    //立刻打开定时器开始计时第一个数据位   else   return 0;   DATA_IN();                                          //引脚设置为外部中断模式   outline = 0;            return 1;                                          //一切成功返回1      }   else   return 0;    }

使用特权

评论回复
6
捉虫天师| | 2017-10-3 20:25 | 只看该作者
#pragma vector = 0x05                               //PA的中断向量位 __interrupt void GPIOA_IRQHandler() {    datatime = TIM4_CNTR;         //获取两次下降沿之间的数据宽度    TIM4_CNTR = 0;                //清零,再次获取下一位    datareg <<= 1;                //高位先出,左移操作    if((datatime>75)&&(datatime<85))           //数据0  我就默认高位开始获取了    datareg &= 0xfe;                            if((datatime>120)&&(datatime<130))         //数据1    datareg |= 0x01;                           if(datanum == 7)    dataall[0] = datareg;                        //获取第一个字节也就是湿度整数位    if(datanum == 23)                            //获取第三个字节也就是温度整数位    dataall[1] = datareg;    if(datanum == 39)                            //获取第五个字节也就是校验(温度+湿度)位    dataall[2] = datareg;    datanum++;                                 //每次读取一位进1    if(datanum >= 40)                          //数据接收完了结束    datanum = 0;     }

使用特权

评论回复
7
捉虫天师| | 2017-10-3 20:26 | 只看该作者
网上找的不知道对不对

使用特权

评论回复
8
yiy| | 2017-10-3 22:38 | 只看该作者
看看几种IO的模式是不是有错,如果时序没错的情况下。

使用特权

评论回复
9
冰封小肥牛|  楼主 | 2017-10-3 22:41 | 只看该作者
yiy 发表于 2017-10-3 22:38
看看几种IO的模式是不是有错,如果时序没错的情况下。

都正确的啊

使用特权

评论回复
10
huangcunxiake| | 2017-10-4 11:32 | 只看该作者

使用特权

评论回复
11
huangcunxiake| | 2017-10-4 11:34 | 只看该作者

使用特权

评论回复
12
huangcunxiake| | 2017-10-4 11:35 | 只看该作者
STM8S [url=home.php?mod=space&uid=72445]@[/url] 16M 定时器定时5ms中断一次

#define _G_DHT11

#include "dht11.h"

unsigned char uc_DHT11Value[SIZE];

//全局变量 得到的温湿度值

unsigned int ui_TempValue = 0;

unsigned int ui_HumiValue = 0;

extern unsigned char uc_20mstimeflag;

/************************************************************* 函数名称:

函数功能:

入口参数:

入口参数的类型和含义:

出口参数:

备 注:

*************************************************************/ unsigned char s_ComDHT11(void)

{

unsigned char i,temp,comdata;

for(i = 8;i>0;i--)

{

while(!DHT11_DATA_VALUE);

DHT11_Delay_10us();

DHT11_Delay_10us();

DHT11_Delay_10us();

DHT11_Delay_10us();

temp = 0;

if(DHT11_DATA_VALUE)

{

temp =1;

}

comdata = comdata << 1;

comdata = comdata|temp;

while(DHT11_DATA_VALUE);

}

return comdata;

}

函数名称:

函数功能:

入口参数:

入口参数的类型和含义:

出口参数:

备 注:

*************************************************************/ void g_ReadTempAndHumi(void)

{

DHT11_DATA_OUT;

DHT11_DATA_LOW;

//layTime(40);// 至少18MS的延时,在中断计时里实现

uc_20mstimeflag = 1;

while(uc_20mstimeflag);

DHT11_DATA_HIGH;

DHT11_DATA_IN;

DHT11_Delay_10us();

DHT11_Delay_10us();

DHT11_Delay_10us();

while(!DHT11_DATA_VALUE); //80us的应答信号 DHT11 TO MCU while(DHT11_DATA_VALUE); //80us的通知信号 DHT11 TO MCU uc_DHT11Value[0] = s_ComDHT11();

uc_DHT11Value[1] = s_ComDHT11();

uc_DHT11Value[2] = s_ComDHT11();

uc_DHT11Value[3] = s_ComDHT11();

uc_DHT11Value[4] = s_ComDHT11();

if((uc_DHT11Value[0] + uc_DHT11Value[1] + uc_DHT11Value[2] + uc_DHT11Value[3]) == uc_DHT11Value[4])

{

ui_HumiValue = uc_DHT11Value[0];

ui_TempValue = uc_DHT11Value[2];

}

}

函数名称:

函数功能:

入口参数:

入口参数的类型和含义:

出口参数:

备 注:

*************************************************************/ void DHT11_Delay_10us(void)

{

for(unsigned char uc_10us = 0;uc_10us < 34;uc_10us ++); }

头文件部分

#ifndef __DHT11_H

#define __DHT11_H

#include "iostm8s105c6.h"

#ifdef __cplusplus

extern "C" {

#endif

#ifndef _G_DHT11

#define DHT11_extern extern

#else

#define DHT11_extern

#endif

/**************宏定义****************/

//#define DATA_DR PA_ODR_ODR6 //OUTPUT

//#define DATA_SR PA_IDR_IDR6 //IN STATE

#define DHT11_DATA_OUT PE_DDR_DDR3 = 1 //输出

使用特权

评论回复
13
冰封小肥牛|  楼主 | 2017-10-4 16:05 | 只看该作者

问题已经搞定了,是一个小错误,还是谢谢各位

使用特权

评论回复
14
山东电子小菜鸟| | 2017-10-5 09:52 | 只看该作者
冰封小肥牛 发表于 2017-10-4 16:05
问题已经搞定了,是一个小错误,还是谢谢各位

使用特权

评论回复
15
冰封小肥牛|  楼主 | 2017-10-5 11:28 | 只看该作者

使用特权

评论回复
16
gejigeji521| | 2017-10-5 11:49 | 只看该作者
就是断点问题?莫非你一直在调试模式搞的?没有全速跑一个看看?

使用特权

评论回复
17
menfiss| | 2017-10-5 17:16 | 只看该作者
dht11需要一秒以上的稳定时间,不知设置没有?

使用特权

评论回复
18
一路向北lm| | 2017-10-5 17:27 | 只看该作者
冰封小肥牛 发表于 2017-10-3 15:42
前面的起始函数都是我自己编写的,读取的是参照的

原子的,野火都有代码直接用就行了。

使用特权

评论回复
19
冰封小肥牛|  楼主 | 2017-10-9 15:16 | 只看该作者
gejigeji521 发表于 2017-10-5 11:49
就是断点问题?莫非你一直在调试模式搞的?没有全速跑一个看看?

是在调试模式,断点位置改了就没问题了,板子是自己设计的,当时没考虑周全没有显示设备

使用特权

评论回复
20
冰封小肥牛|  楼主 | 2017-10-9 15:16 | 只看该作者
一路向北lm 发表于 2017-10-5 17:27
原子的,野火都有代码直接用就行了。

我现在是在STM8上,目前DHT11的读写没问题

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

201

帖子

1

粉丝