热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

51单片机物联网开发

绪论硬件工具:STC89C52RC芯片、51单片机开发板、ESP8266通信模块、TTL转USB、各类传感器软件工具:Keil开发环境,

绪论

硬件工具:STC89C52RC芯片、51单片机开发板、ESP8266通信模块、TTL转USB、各类传感器

软件工具:Keil开发环境,STC-ISP烧录工具,IDEA专业版,Postman,WebStorm,vx小程序开发工具,sscom串口助手,Socket-Tools,Tomcat8,JDK1.8,Navicat,Android Studio

开发环境:Java8、SpringBoot+MyBatis、MySQL、C51、阿里云、Javascript、JQuery、Ajax、Windows操作系统、Chrome浏览器,Android操作系统

开发描述:基于ESP8266通信模块,通过51单片机采集环境传感数据并实现自动控制,通过AT指令将采集数据打包json格式发送目标服务器,云端部署jar包并建立数据库,将接收的数据解析并保存到设备数据表中,基于Ajax与Restful接口实现前后端分离,实现用户登录注册、设备管理、数据查询功能,并支持在Android和vx小程序上访问设备信息。

项目整体框架


一、硬件开发

        本案例通过检测MQ-5可燃气体传感器、DHT数字温湿度传感器、火焰传感器这三个传感器感知的环境数据,进而通过逻辑判断通过I/O口输出到继电器、蜂鸣器和LED报警灯。通过ESP8266-01s模块通过WIFI接入云服务器,将采集的数据实时发送到指定端口,且51单片机根据传感器采集的各种火灾安全参数进行判断,如果出现异常情况则单片机启动接入的控制元器件进行自动控制,控制报警灯、蜂鸣器和风扇进行工作,硬件整体框架如下


ESP8266调试

         我们使用sscom调试助手进行调试。首先需要一个TTL转USB工具插上ESP8266模块连接PCcom口,打开调试助手检测到设备,然后可以向8266发送指令,指令集如下:

AT+RST :初始化
AT+CWMODE=3 :设置兼容模式,可以访问其他WiFi
AT&#43;UART&#61;<波特率>,8,1,0,0 &#xff1a;设置波特率
AT&#43;CWJAP&#61;"","" &#xff1a;设置连接的WiFi名称和密码
AT&#43;CIPSTART&#61;"TCP","",<端口号>
AT&#43;CIPSEND&#61;5 : 用于测试字符长度
<下面输入要发送的字符串>

C51单片机程序开发


        使用Keil编写&#xff0c;打开工具&#xff0c;引入STC系列的MCU

//引入库与宏定义
#include
#include
#include
#include #define uchar unsigned char
#define uint unsigned inttypedef unsigned char u8;
typedef unsigned int u16;
unsigned char strlen(unsigned char *str);
unsigned char flag;sbit Data&#61;P0^6;
sbit Gas_DOUT &#61; P0^4;
sbit Fire_DOUT &#61; P0^3;
sbit beep&#61;P0^2;
sbit LED &#61; P0^1;
sbit relay &#61; P0^5;bit uart_busy &#61; 0;
uchar temp_dat[9];
uchar tempture[2];
uchar string_data1[80];
uchar string_data2[10];
char gas;
char fire;
//设置发送数据
uchar string_send[12];
uint i;
uint count;
void relay_fun();
uchar len_a;
uchar len_b;
uchar len_c;
uchar len_sum;void LED_Alarm()
{u8 i;for(i&#61;10;i>0;i--){LED&#61;0;beep&#61;0;delay_u16(10);LED&#61;1;beep&#61;1;delay_u16(10);}
}
//设置频率
void delay_u16(u16 i)
{while(i--);
}
//控制继电器风扇函数
void relay_fun(){relay &#61; ~relay;LED_Alarm();relay &#61; ~relay;
}void beep_led_alarm(){beep &#61; 0; for(i&#61;0;i<5000;i&#43;&#43;){beep&#61;~beep;delay_u16(100);}
}void DHT11_delay_us(uchar n)
{while(--n);
}void DHT11_delay_ms(uint z)
{uint i,j;for(i&#61;z;i>0;i--)for(j&#61;110;j>0;j--);
}void DHT11_start()
{Data&#61;1;DHT11_delay_us(2);Data&#61;0;DHT11_delay_ms(20); Data&#61;1;DHT11_delay_us(30);
}uchar DHT11_rec_byte()
{uchar i,dat&#61;0;for(i&#61;0;i<8;i&#43;&#43;) { while(!Data); DHT11_delay_us(8); dat<<&#61;1; if(Data&#61;&#61;1) dat&#43;&#61;1;while(Data); } return dat;
}
//DHT11AD转换函数
void DHT11_receive()
{uchar R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise; DHT11_start();if(Data&#61;&#61;0){while(Data&#61;&#61;0); DHT11_delay_us(40); R_H&#61;DHT11_rec_byte(); R_L&#61;DHT11_rec_byte(); T_H&#61;DHT11_rec_byte(); T_L&#61;DHT11_rec_byte(); revise&#61;DHT11_rec_byte(); DHT11_delay_us(25); if((R_H&#43;R_L&#43;T_H&#43;T_L)&#61;&#61;revise) {RH&#61;R_H;RL&#61;R_L;TH&#61;T_H;TL&#61;T_L;} if(TH > 24){LED_Alarm();LED &#61; 0;beep&#61;0;}temp_dat[0]&#61;&#39;0&#39;&#43;(TH/10);temp_dat[1]&#61;&#39;0&#39;&#43;(TH%10);}
}void delay5ms(){unsigned char a,b;for(b&#61;201;b>0;b--)for(a&#61;247;a>0;a--);
}void Init_uart(void) { TMOD &#61; TMOD | 0x20; SCON &#61; SCON | 0x50; TH1 &#61; 0xFd; TL1 &#61; TH1; TR1 &#61; 1; EA &#61;1; ES &#61;1;
}void Uart_SendByteData(unsigned char msg){while(uart_busy); SBUF&#61;msg; uart_busy &#61; 1;
}void Uart_SendStrData(unsigned char *msg){while(*msg){Uart_SendByteData(*msg&#43;&#43;);}
}//取字符串长度
unsigned char strlen(unsigned char *str)
{unsigned char len&#61;0;while(1){ if(*str&#61;&#61;&#39;\0&#39;)break;//拷贝完成了.len&#43;&#43;;str&#43;&#43;;}return len;
}void main(){count &#61; 0;beep&#61;1;LED&#61;1;Init_uart();len_a&#61;0;len_b&#61;0;len_sum&#61;0;while(1){count&#43;&#43;;DHT11_receive();delay5ms();delay5ms();for(i&#61;0;i<2;i&#43;&#43;){tempture[i]&#61;temp_dat[i];}if(Gas_DOUT &#61;&#61; 0){gas&#61;&#39;1&#39;;LED_Alarm();LED &#61; 0;beep&#61;0;}else{gas&#61;&#39;0&#39;;}if(Fire_DOUT &#61;&#61; 0){fire&#61;&#39;1&#39;;LED_Alarm();LED &#61; 0;beep&#61;0;}else{fire&#61;&#39;0&#39;;}for(i&#61;0;i<2;i&#43;&#43;){string_send[i]&#61;tempture[i];}string_send[2]&#61;&#39;t&#39;;string_send[3]&#61;fire;string_send[4]&#61;&#39;g&#39;;string_send[5]&#61;gas;string_send[6]&#61;&#39;f&#39;;string_data1[]&#61;"{\"type\":\"02\",\"deviceCode\":\"Device\",\"deviceData\":\"";string_data2[]&#61;"\"}";len_a&#61;strlen(string_data1);leb_b&#61;strlen(string_data2);len_c&#61;strlen(string_send);len_sum&#61;len_a&#43;len_b&#43;len_c;Uart_SendStrData("AT&#43;CIPSTART&#61;\"TCP\",\"\",\r\n"); delay5ms();Uart_SendStrData("AT&#43;CIPSEND&#61;");Uart_SendStrData(len_sum);Uart_SendStrData("\r\n");delay5ms(); Uart_SendStrData(string_data1);Uart_SendStrData(string_send);Uart_SendStrData(string_data2);delay1_relay(2);}
}void UART_Interrupt(void) interrupt 4 {unsigned char temp;if(RI){temp &#61; SBUF;RI &#61; 0;if(temp &#61;&#61; 1){flag &#61; 1;}}if(TI){TI &#61; 0;uart_busy &#61; 0;}
}

调试通信

        ESP8266上的TX和RX一定要和单片机上的RX与TX交叉连接&#xff0c;                                                        8266-TX连接51-RX&#xff0c;8266-RX连接51-TX

以下为单片机串口调试图&#xff1a;

使用Socket-Tools&#xff0c;在云服务器上创建TCPServer指定端口号&#xff0c;开启单片机连接WiFi

下图为端口通信调试图&#xff1a;


二、服务器软件开发 


 TCP接收服务开发

创建socket通信端口以多线程方式等待监听端口

package com.bl.demo;import javax.annotation.PostConstruct;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;import static com.bl.utli.SocketParam.*;public class TCPServer extends Thread {ServerSocket serverSocket &#61; null;public static TCPServer tcpServer;&#64;PostConstructpublic void init(){tcpServer &#61; this;tcpServer.start();}public String socketSendData(String deviceCode,String sendData){//不为空时subSocketClient temp &#61; DeviceCode2SocketMap.get(deviceCode);if(null!&#61;temp){return temp.sendSocketData(sendData,deviceCode);}else{return SendError;}}&#64;Overridepublic void run() {try {serverSocket &#61; new ServerSocket(PortNum);System.out.println("PortNum: "&#43;PortNum);} catch (IOException e) {System.out.println("the port cannot open.");}while(true){try {System.out.println("wait. .. ...");//使用accept()是阻塞方法Socket socketTemp &#61; serverSocket.accept();new subSocketClient(this.serverSocket,socketTemp).start();//为每个连接都创建一个线程客户端} catch (IOException e) {System.out.println("happening");}}}
}

使用JDBC对MySQL进行操作&#xff0c; 在run()方法中解析数据并存储到数据库中

package com.bl.demo;import com.alibaba.fastjson.JSONObject;
import com.bl.Data.Data;
import com.bl.Data.DataMapper;
import com.bl.Data.DataService;
import com.bl.utli.SocketParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.sql.*;import static com.bl.utli.SocketParam.*;//&#64;Component
public class subSocketClient extends Thread {private ServerSocket serverSocket;private Socket socket;&#64;Autowired&#64;Resourceprivate DataMapper tempMapper_udp_save;public static subSocketClient subSocketClient;public subSocketClient(ServerSocket serverSocket, Socket socket) {this.serverSocket &#61; serverSocket;this.socket &#61; socket;}//初始化通信程序&#64;PostConstructpublic void init(){subSocketClient &#61; this;subSocketClient.tempMapper_udp_save &#61; this.tempMapper_udp_save;}private static final String DRIVER &#61; "com.mysql.jdbc.Driver";public void addTemp(String temp, String humi, String beam, String time) {String url &#61; "jdbc:mysql://localhost:3306/iot?serverTimezone&#61;UTC&allowMultiQueries&#61;true";// 数据库用户名String user &#61; "root";// 数据库密码String password &#61; "123456";// 建立数据库连接&#xff0c;获得连接对象conntry {Connection conn &#61; DriverManager.getConnection(url, user, password);Class.forName("com.mysql.jdbc.Driver");String sql &#61; "insert into data_info_t (temp,humi,beam,time) values(?,?,?,?)";PreparedStatement ps &#61; conn.prepareStatement(sql);ps.setString(1, temp);ps.setString(2, humi);ps.setString(3, beam);ps.setString(4, time);// 执行sql语句ps.executeUpdate();System.out.println("SQL插入完毕&#xff01;");// 关闭数据库连接对象conn.close();} catch (Exception e) {e.printStackTrace();}}String temp &#61; "";String humi &#61; "";String beam &#61; "";String time &#61; "";String str1 &#61; "";String str2 &#61; "";String str3 &#61; "";public String sendSocketData(String sendData, String deviceCode) {try {BufferedReader br &#61; null;PrintWriter pw &#61; null;br &#61; new BufferedReader(new InputStreamReader(System.in));pw &#61; new PrintWriter(socket.getOutputStream(), true);//查看socket是否存在if (!socket.isClosed()) {pw.println(sendData);pw.flush();return SendSuccess;} else {//不存在则移除该socketDeviceCode2SocketMap.remove(deviceCode);return SendError;}} catch (IOException e) {e.printStackTrace();}return SendError;}&#64;Overridepublic void run() {try {//获取输入流InputStream inputStream &#61; socket.getInputStream();BufferedReader br &#61; new BufferedReader(new InputStreamReader(inputStream));byte[] buf &#61; new byte[1024];//接收数据int line &#61; 0;while ((line &#61; inputStream.read(buf)) !&#61; -1) {String param &#61; new String(buf, 0, line);//转成json格式JSONObject jsonObject &#61; JSONObject.parseObject(param);//获取type类型&#xff0c;如果是02则自动注册设备String type &#61; jsonObject.getString("type");if (type.equals(TypeUpdateData)) {//获取设备编号String deviceCode &#61; jsonObject.getString("deviceCode");System.out.println(deviceCode);//获取传感数据String deviceData &#61; jsonObject.getString("deviceData");System.out.println(deviceData);//字符串解析str1 &#61; deviceData;String[] strArr1 &#61; StringUtils.split(str1, "t");for (int i &#61; 0; i }

创建restful端口&#xff0c;调用获取设备数据方法将设备传感数据返回&#xff0c;访问方法为POST

&#64;RequestMapping(value &#61; "/getData", method &#61; RequestMethod.POST, produces &#61; MediaType.APPLICATION_JSON_VALUE)&#64;CrossOriginpublic List getData() {List temps &#61; dataService.getTemps();return temps;}

创建数据服务接口&#xff0c;用于获取和添加传感器数据 

package com.bl.Data;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;&#64;Mapper
public interface DataMapper {int addTemp(Map param);List getTemps();}

package com.bl.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
&#64;Service
public class DataService {&#64;AutowiredDataMapper dataMapper;public int addTemp(Map param){return dataMapper.addTemp(param);}public List getTemps(){return dataMapper.getTemps();}
}

 编写xml文件&#xff0c;设备数据插入与查询&#xff0c;查询排序按时间递减



insert into data_info_t(temp,humi,beam,time) values (#{temp},#{humi},#{beam},#{time})

postman通信测试图

 


三、前端页面数据展示

 

 

 

 页面实现


室内火灾监控平台

 

$("#search").click(function () {var name&#61;$("#input").val();$.ajax({async:true,type: "POST",url: "http://47.102.42.105:8456/Device/getData",dataType: "json",data: JSON.stringify({"name":name}),contentType: "application/json",success: function (res) {console.log(res);for(var i&#61;0; i&#39;&#43;res.resultList[i].temp&#43;&#39;&#39;&#43;&#39;&#39; &#43;res.resultList[i].fire&#43;&#39;&#39;&#43;&#39;&#39;&#43;res.resultList[i].gas&#43;&#39;&#39;&#43;&#39;&#39;&#43;res.resultList[i].time&#43;&#39;&#39;;$("#table").append(&#39;&#39; &#43; tr &#43; &#39;&#39;);}}})})
})


推荐阅读
  • Java实战之电影在线观看系统的实现
    本文介绍了Java实战之电影在线观看系统的实现过程。首先对项目进行了简述,然后展示了系统的效果图。接着介绍了系统的核心代码,包括后台用户管理控制器、电影管理控制器和前台电影控制器。最后对项目的环境配置和使用的技术进行了说明,包括JSP、Spring、SpringMVC、MyBatis、html、css、JavaScript、JQuery、Ajax、layui和maven等。 ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 标题: ... [详细]
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
    本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
  • 本文介绍了在满足特定条件时如何在输入字段中使用默认值的方法和相应的代码。当输入字段填充100或更多的金额时,使用50作为默认值;当输入字段填充有-20或更多(负数)时,使用-10作为默认值。文章还提供了相关的JavaScript和Jquery代码,用于动态地根据条件使用默认值。 ... [详细]
  • 开发笔记:spring boot项目打成war包部署到服务器的步骤与注意事项
    本文介绍了将spring boot项目打成war包并部署到服务器的步骤与注意事项。通过本文的学习,读者可以了解到如何将spring boot项目打包成war包,并成功地部署到服务器上。 ... [详细]
  • 本文介绍了Java后台Jsonp处理方法及其应用场景。首先解释了Jsonp是一个非官方的协议,它允许在服务器端通过Script tags返回至客户端,并通过javascript callback的形式实现跨域访问。然后介绍了JSON系统开发方法,它是一种面向数据结构的分析和设计方法,以活动为中心,将一连串的活动顺序组合成一个完整的工作进程。接着给出了一个客户端示例代码,使用了jQuery的ajax方法请求一个Jsonp数据。 ... [详细]
  • 本文介绍了使用FormData对象上传文件同时附带其他参数的方法。通过创建一个表单,将文件和参数添加到FormData对象中,然后使用ajax发送POST请求进行文件上传。在发送请求时,需要设置processData为false,告诉jquery不要处理发送的数据;同时设置contentType为false,告诉jquery不要设置content-Type请求头。 ... [详细]
author-avatar
幸福的肖巍
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有