常用51单片机实现DHT11和ESP8266实现温湿度数据无线传输
第一篇文章
这个是我在尝试写的第一篇文章,这个项目来源是大学的大创项目,在制作的过程中,因为自己也是受到了很多来自平台的大神的支持,同时也总结了类似文章中没有提到的问题,写的有不好的和不专业的地方还希望大家多多指正,废话不多说开始吧。
DHT11模块
这个模块基本就是买上手就能知道怎么接线(就直接把三个端口对应接在单片机开发板上即可,后面需要扩展多个时候只需要重新定义数据口,要是电源线不够可以使用面包板,定义时注意别用单片机上的有特定功能的端口)。
DHT11程序部分
这个传感器的程序是我在制作整个阶段耗费时间最长的部分,因为刚接触这个东西的时候很多东西没有学,代码写的也很少,完全掌握这个模块的代码还是在完成了单片机与微机两门课后。实际上现在看起来这是这个系统最简单的一份代码了。
DHT11采集数据
先要看懂时序图,关于这个时序图网上包括说明书上都有介绍这里就不啰嗦了,掌握数电和单片机之后,完全有能力掌握。
这个是开始信号,和大部分的DHT11的代码是一样的,主要还是delay-1ms要写好后面的4个1us延时可用可不用。
void start()//开始信号
{
i0=1;
delay_1us();
i0=0;
delay_1ms(20); //拉低至少 18ms 保证能检测到起始信号
i0=1; //检测到开始信号后,将电平拉高20-40us
delay_1us(); //可替换成20-40us程序
delay_1us();
delay_1us();
delay_1us();
}
这个是开始信号结束之后的代码,主要看懂recive这个函数其实说白了就是照着时序写,后面吧得到的40位输出按温湿度和校验位分开,我们主要还是用到温湿度的高八位,温湿度的低八位我也尝试显示出来过结果都是0,所以如果是自己编写可以舍弃掉低八位数据。这里值得注意的是校验位是不能舍弃的,舍弃掉校验位后是对最后的数据有影响的。
uchar receive_byte()//接收一个字节
{
uchar i,temp;
for(i=0;i<8;i++)
{
while(!i0);//等待50us的低电平开始信号结束
delay_1us(); //开始信号结束后,延时26us-28us
delay_1us();
delay_1us();
temp=0; //如果时间为26us-28us 则表示接收的数据为‘0’
if(i0==1)
temp=1;//如果时间超过26us-28us 则表示收到的数据为‘1’
while(i0);//等待数据信号高电平, ‘0’为26us-28us;‘1’为70us
data_byte<<=1;//将接收到的数据向高位左移
data_byte|=temp;
}
return data_byte;
}
void receive() //接收数据
{
uchar T_H,T_L,R_H,R_L,check,num_check;
start();//开始信号
i0=1; //主机设为输入 判断从机DHT11的响应信号
if(!i0) //判断是否有响应信号
{
while(!i0);//判断从机发出80us低电平信号是否结束
while(i0);
R_H= receive_byte();//湿度高位
R_L= receive_byte();//湿度低位
T_H= receive_byte();//温度高位
T_L= receive_byte();//温度低位
check= receive_byte();//检验位
i0=0;//当所有的数据接收完成后,将从机电平拉低50us
delay_1us(); //拉低50us
delay_1us();
delay_1us();
delay_1us();
delay_1us();
i0=1;//将从机电平拉低,进入空闲状态
num_check=R_H+R_L+T_H+T_L;
if(num_check=check)//判断读取的数据与校验位是否相同
{
RH=R_H;
RL=R_L;
TH=T_H;
TL=T_L;
check=num_check;
}
}
}
ESP8266模块
关于这个模块有很多东西需要注意,我在使用这个模块时走过不少弯路,现在给大家说说关于这个模块的经验,给大家排雷。具体的基础教学可以给大家推荐几篇文章
关于波特率
这个是我在这个模块上踩的最大的一颗雷,不过也让我学了不少东西。
关于esp8266模块的波特率,它出厂的波特率是115200,我们常见使用的51单片机开发板上的晶振是11.0592hz的,它的最大波特率是57600的所以当时认为我们需要更换晶振,我们就设计了一个最小系统,准备所有元件都集成起来,这里配上原理图可能大家需要。但是这里我想告诉大家的是其实ESP8266的波特率是可以改变的,我们说明书上改变波特率的代码可能不行,这里给大家提供一段代码AT+UART_CUR=9600,8,1,0,0
如果还是不行可以在网上找一找其他的,但是要确信这个模块的波特率可以改变!!!!!
接线问题
我们是直接在开发板上面做的,所以接线上最要注意的是单片机要和ESP8266共地,我也是在这上面吃过亏了,检查代码没有一点问题但是传输过来的数据就是显示乱码,浪费了大量时间,吃了硬件基础不好的亏。
其余的接线就是3v3和EN端接3.3v电源,RX与TX与单片机的RI和TI反接即可,只需要接这5根线我们的ESP8266就可以正常工作了。
初始化ESP8266
整个ESP8266最大的问题就是初始化问题,可能检查了代码很多遍都没有问题,但是就是配置不成功,这里介绍一下我在写代码时遇到的问题。
while(1)
{
sendstr(esp_cipmux);
if(data_compare("OK"))
break;
delay(3000);
}
这一段是配置多连接的,因为ESP8266的模式和名称密码设置好之后掉电是不会擦除的,所以我们就可以简单的配置一下多连接和服务器即可。这里要注意的是不要直接把我们的指令放在数组里面然后发送给ESP8266
类似于这样
for(a=0;a<50000;a++);
sendstring("AT+CWMODE=2\n");
for(a=0;a<20000;a++);
sendstring("AT+RST");
for(a=0;a<20000;a++);;
这种字符串发送后ESP8266可能是来不及识别的原因,你就会在串口调试助手里面一直看到这些东西在无限循环但是你也找不到这个wifi热点,虽然延时了但是还是不能起到作用,可能有时候也能偶尔配置上但是是很不稳定的。正确的还是要写一段比较函数看是否ESP8266有返回“ok”
返回函数也很简单
uchar data_compare(uchar *p)
{
if(strstr(esp8266_return,p)!=NULL)
return 1;
else
{
return 0;
}
}
还有就是在初始化的时候记得要把串口中断关上!!!,不然在执行sendstr时就会陷入死循环,这里要特别说明的是,在编写整段代码的时候一定要记得自己串口中断的状态,一旦错位的进入串口中断就陷入死循环导致逻辑错位,自己还很难检查出来。**
数据传输
这部分其实很简单就直接上代码了
ES=0;
for(i=0;i<10;i++)
{
sendbyte(com[i]);
}
sendstr("\r\n");
sendstr(esp_cipsend);
值得注意的点就是先把要发送数据的数组发送给串口,然后在输入at+cipsend指令不然发送的结果就是这样的了
实物展示