
本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 ,转载此文目的在于传递更多信息,版权归原作者所有。