基于51单片机的无线测温系统

demi的头像
demi 发布于:周三, 10/24/2018 - 15:58 ,关键词:

本51项目基于STC89C52MCU,温度传感器为DS18B20,显示模块用的是LCD1602,无线模块用的是Nodemcu。

项目用到的编程语言:C,C++,Lua。

实现思路是这样,DS18B20测温,然后数据串行传送给51单片机,然后51通过串口将数据传送给Nodemcu,Nodemcu通过其WIFI模块将数据发送给上位机,上位机上的程序是用Qt编写的GUI。(这里无线传输采用的是无连接的UDP协议)

1. DS18B20温度测量模块

DS18B20是单总线器件,所以时序要求非常严格,程序编写时注意时序,否则读不出温度。DS18B20有寄生供电和单独供电,这里采用单独供电方式。

它的驱动程序如下:

#include"Temp.h"
void delay1ms(unsigned int y)
{
unsigned int x;
for( ; y>0; y--)
{
for(x=110; x>0; x--);
}
}

void Init18b20(){
int i;
DQ=0;
i=60;
while(i--);   //10us左右,一共延时60*10=600us左右。
DQ=1;

while(DQ)
{
i=1;
while(i--); 
}
}

void Writeonebyte(unsigned char ins){
int i=0;
int j=0;
for(i=0;i<8;i++){
DQ=0;
j++;                   //延时1us
DQ=0x01&ins;   //写0或者1,写完以后保持,15us内DS18B20会来采集数据。
j++;
j=6;
while(j--);           //一个写周期至少60us。
DQ=1;                //释放数据线
  ins=ins>>1;      //写下一位数据
}
}

unsigned char Readonebyte(){
int i=0;
int j=0;
unsigned char bi, byte;
for(i=0;i<8;i++){
DQ=0; 
j++;
DQ=1;              //拉低1us后释放,给一个准备读的信号
j++;
j++;
bi=DQ;             
byte=(byte>>1)|(bi<<7);    //读取8位数据
j=5;
while(j--);
}
return byte;
}

void Tempconvert(){
Init18b20();
delay1ms(1); 
Writeonebyte(0xcc);
Writeonebyte(0x44);
}

void Readrom(){
Init18b20();
delay1ms(1);
Writeonebyte(0xcc);
Writeonebyte(0xbe);
}

int Readtemp(){
int temp;
unsigned char tml,tmh;
Tempconvert();
Readrom();
tml=Readonebyte();
tmh=Readonebyte();
temp=tmh;
temp=temp<<8;
temp=temp|tml;
return temp;
}

头文件

#include"reg52.h"
sbit DQ=P1^0;
void Init18b20();
void Writeonebyte(char ins);
unsigned char Readonebyte();
void Tempconvert();
void Readrom();
int Readtemp();
void delay1ms();

2.LCD1602显示模块

这个模块比较简单,注意时序,然后初始化函数里面不要写清屏指令,以免显示的数据一直闪烁。

#include"lcd1602.h"
char init[]="Temp ";
void delay1ms()   //误差 -0.651041666667us
{
    unsigned char a,b;
    for(b=102;b>0;b--)
        for(a=3;a>0;a--);
}

void delay5ms()   //误差 -0.000000000001us
{
    unsigned char a,b;
    for(b=15;b>0;b--)
        for(a=152;a>0;a--);
}
void writecom(int com){
E=0;
RS=0;
RW=0;
P0=com;     //并行送数据
delay1ms(); //送完后保持一下 使其稳定
E=1;           //拉高,让数据发送
delay5ms();
E=0;
}
void writedat(char dat){
E=0;
RS=1;
RW=0;
P0=dat;
delay1ms();
E=1;
delay5ms();
E=0;
}
void lcdinit(){
int i=0;
delay1ms();
writecom(0x06);
writecom(0x0c);
delay1ms();
writecom(0x38);
writecom(0xc3);
for(i=0;i<5;i++)
writedat(init[i]);
}

头文件

#include<reg52.h>
sbit RS=P2^0;
sbit RW=P2^1;
sbit E=P2^2;
void delay1ms();
void delay5ms();
void lcdinit();
void writecom(int com);
void writedat(char dat);

3.Nodemcu模块

手里只有这个MCU,没有ESP8266。其实差不多,Nodemcu就是一个ESP8266的小系统板,然后将一些资源进行二次封装,然后用Lua语言开发。如果是单独的ESP8266模块,就用串口 AT指令调试。 相同的是一开始都要烧固件进去,固件可以自己选,模块都在github上。这个Nodemcu三种工作方式 STA ,AP,STA+AP。 STA模式就是可以像手机一样接到你的路由器上,然后你可以用你的手机电脑通过网络来操纵。AP就是这个模块成为一个热点,你手机电脑可以连接上这个热点,这种方式适用于局域网。STA+AP是都可以的。

本次项目使用STA模式。

代码如下

print('Setting up WIFI...')
wifi.setmode(wifi.STATION)
wifi.sta.config('AP', 'SSID')
wifi.sta.connect()

tmr.alarm(1, 1000, tmr.ALARM_AUTO, function()
    if wifi.sta.getip() == nil then
        print('Waiting for IP ...')
    else
        print('IP is ' .. wifi.sta.getip())
    tmr.stop(1)
    end
end)

cu=net.createConnection(net.UDP, 0)
cu:connect(9999,"ip")
cu:on("receive",function(cuk,c) print(c) end )

uart.setup(0,9600,8,0,1,0)
uart.on("data",
function(data)
print("receive from uart:", data) 
cu:send(data)
end, 0)

这里要注意的是你烧进去的第一个程序,名字必须是init.lua 它上电是从这个文件开始执行的。

最后一点

各个模块的组合,即C语言主函数如下

#include"Temp.h"
#include"lcd1602.h"
#include<reg52.h>
void dlay1ms(int y)
{
int x;
for( ; y>0; y--)
{
for(x=110; x>0; x--);
}
}
void Serialinit(){
TMOD=0x20;
TH1=0XFD;
TL1=0XFD;
TR1=1;
SCON=0x50;    //配置好串口,这里波特率为9600. 只用定时器和串口,不用中断。
}

char list[11]={'0','1','2','3','4','5','6','7','8','9','.'};
char value[4];
int i=0;

void Datapros(int temp){
float fp;
fp=temp;
temp=fp*0.0625*100;     //注意 0.0625*temp是温度,但是乘出来的可能是带小数部分的,你要先把temp变成带小数的,再乘0.0625,否则乘出来的小数部分就被类型转换截掉了。
value[0]=list[temp/1000];
value[1]=list[temp%1000/100];
value[2]=list[10];
value[3]=list[temp%100/10];      //显示一位小数,这种显示算法对数码管也通用。
}

void Lcddisplay(){
lcdinit();
writedat(value[0]);
dlay1ms(20);
writedat(value[1]);
dlay1ms(20);
writedat(value[2]);
dlay1ms(20);
writedat(value[3]);
dlay1ms(20);
}

int main(){
Serialinit();
while(1){
Datapros(Readtemp());
Lcddisplay();
for(i=0;i<4;i++)
{
SBUF=value[i];    //启动串口传输,51单片机的TXD RXD接到Nodemcu上的TX RX上。
while(!TI);
TI=0;
}
}
}

上位机界面用Qt编写。

代码就不贴出来了。效果图已经上传。

整个项目做完以后的总结与不足。

总结:DS18B20时序一定要特别注意。Lcd如果添加了清屏指令,显示温度会闪烁。Nodemcu第一个程序名一定是init.lua。烧写工作有好几种,自己选择。Lua语言需要了解一下,Nodemcu的API需要了解一下。然后就是Qt写的GUI,里面用到的UDP协议,端口和IP要对应好,不然接收不到数据。

不足: DS18B20可以用寄生方式供电,这个我不是很了解,下次可以尝试寄生供电方式工作,这个适合远距离测温。无线数据传说部分可以用更可靠的TCP协议来传输,这个必须要会,下次会尝试使用这个协议来编写上位机程序。采集到的温度没有进行处理,只用来显示了,希望在学习数据库以后加入数据的存储筛选功能。

来源:博客园 - Crenx ,转载此文目的在于传递更多信息,版权归原作者所有。

围观 388