目录
1.简介:
2.硬件:
3.开发平台:
4.需要的库:
5.实验代码:
5.1 TCPClient端(负责JSON接收及解析):
5.2 TCPServer端(负责JSON打包及发送):
6.实验效果:
在2019年夏季的全国大学生电子设计大赛中,我们组选择了电磁炮这个题目, 并且确定方案为STM32+OPENMV4(串口通讯),但当时苦于没有一个好的通信协议(毕竟当时还是小白~),只能选择了按位读取的办法,但在玩ESP8266这么久后突然想到各种物联网接入貌似都是用JSON来传输数据的,于是我便想到用各种方式来发送JSON数据(TCP、串口、IIC、UDP、各种你能想到的通信方式~),我们只需要解决Json的数据解析工作即可,令人高兴的是,Arduino方面我们有ArduinoJson库,STM32方面keil5也提供了官方的JSON库——Jansson,就算是其他单片机平台,也不要怕,我们还有开源C++编写的cJSON库,我们只需要简单移植,就可以让你的单片机使用JSON。
两个连接了0.96寸OLED的ESP8266开发板;
Arduino (1.8.10) 或 VScode 环境下 PlatformIO 插件
U8g2 :https://github.com/olikraus/U8g2_Arduino
ArduinoJson V5版本:https://github.com/bblanchon/ArduinoJson.git
/**
* @功能 两块ESP8266通过TCP发送Json消息并解析
* @author 刘泽文
* @date 2020/4/13
* @TCP Client客户端
*/
#include
#include
#include
#include
//以下三个定义为调试定义
#define DebugBegin(baud_rate) Serial.begin(baud_rate)
#define DebugPrintln(message) Serial.println(message)
#define DebugPrint(message) Serial.print(message)
#define DebugPrintf(message) Serial.printf(message)
#define LED D4
const char* ssid = "liuzewen";
const char* password = "17609245102liu";
const char* Server = "192.168.31.53";
const int Port = 23;
short Status = 0;
uint8_t apple[60];
WiFiClient client;
//定义OLED型号
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
void setup() {
DebugBegin(115200);
u8g2.begin();
u8g2.enableUTF8Print();
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_wqy16_t_gb2312);
u8g2.setCursor(40, 40);
u8g2.print("Json解析");
u8g2.sendBuffer();
pinMode(LED,OUTPUT);
digitalWrite(LED,LOW);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
DebugPrint("\nConnecting to ");
DebugPrintln(ssid);
uint8_t i = 0;
while (WiFi.status() != WL_CONNECTED && i++ < 20) {
delay(500);
DebugPrint(".");
}
if (i == 21) {
DebugPrint("Could not connect to");
DebugPrintln(ssid);
while (1) {
delay(500);
}
}
DebugPrint("Ready! Use 'telnet ");
DebugPrint(WiFi.localIP());
}
void loop() {
if(Status==0 && WiFi.status()==WL_CONNECTED)
{
Status=1;
client.connect(Server, Port);
DebugPrint("连接到服务器~");
}
while(client.available()){
digitalWrite(LED,!digitalRead(LED));
client.read(apple,60);
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(apple);
if (!root.success()) {
Serial.println("parseObject() failed");
return;
}
const char* name = root["name"];
int rand = root["rand"];
double data = root["data"][0];
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_wqy16_t_gb2312);
u8g2.setCursor(40, 16*1-2);
u8g2.print("Json解析");
u8g2.setCursor(0, 16*2-2);
u8g2.print("name:");
u8g2.setCursor(40, 16*2-2);
u8g2.print(name);
u8g2.setCursor(0, 16*3-2);
u8g2.print("rand:");
u8g2.setCursor(40, 16*3-2);
u8g2.print(rand);
u8g2.setCursor(0, 16*4-2);
u8g2.print("data:");
u8g2.setCursor(40, 16*4-2);
u8g2.print(data);
u8g2.sendBuffer();
delay(200);
if(!client.status()){
DebugPrint("跳出循环");
Status = 0;
break;
}
}
}
/**
* @功能 两块ESP8266通过TCP发送Json消息并解析
* @author 刘泽文
* @date 2020/4/13
* @TCP Server服务端
*/
#include
#include
#include
#include
//定义最多多少个client可以连接本server(一般不要超过4个)
#define MAX_SRV_CLIENTS 2
//以下三个定义为调试定义
#define DebugBegin(baud_rate) Serial.begin(baud_rate)
#define DebugPrintln(message) Serial.println(message)
#define DebugPrint(message) Serial.print(message)
#define DebugPrintf(message) Serial.printf(message)
#define LED D4
const char* ssid = "liuzewen";
const char* password = "17609245102liu";
//创建server 端口号是23
WiFiServer server(23);
//管理clients
WiFiClient serverClients[MAX_SRV_CLIENTS];
//定义OLED型号
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
long pushtime = 0;
void setup() {
DebugBegin(115200);
u8g2.begin();
u8g2.enableUTF8Print();
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_wqy16_t_gb2312);
u8g2.setCursor(40, 40);
u8g2.print("Json发送");
u8g2.sendBuffer();
pinMode(LED,OUTPUT);
digitalWrite(LED,LOW);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
DebugPrint("\nConnecting to ");
DebugPrintln(ssid);
uint8_t i = 0;
while (WiFi.status() != WL_CONNECTED && i++ < 30) {
digitalWrite(LED,!digitalRead(LED));
DebugPrint(".");
delay(500);
}
if (i == 21) {
DebugPrint("Could not connect to");
DebugPrintln(ssid);
while (1) {
delay(500);
}
}
//启动server
server.begin();
//关闭小包合并包功能,不会延时发送数据
server.setNoDelay(true);
DebugPrint("Ready! Use 'telnet ");
DebugPrint(WiFi.localIP());
DebugPrintln(" 23' to connect");
pushtime = millis();
}
void loop() {
uint8_t i;
//检测是否有新的client请求进来
if (server.hasClient()) {
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
//释放旧无效或者断开的client
if (!serverClients[i] || !serverClients[i].connected()) {
if (serverClients[i]) {
serverClients[i].stop();
}
//分配最新的client
serverClients[i] = server.available();
DebugPrint("New client: ");
DebugPrint(i);
break;
}
}
//当达到最大连接数 无法释放无效的client,需要拒绝连接
if (i == MAX_SRV_CLIENTS) {
WiFiClient serverClient = server.available();
serverClient.stop();
DebugPrintln("Connection rejected ");
}
}
//检测client发过来的数据
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
if (serverClients[i] && serverClients[i].connected()) {
if (serverClients[i].available()) {
//get data from the telnet client and push it to the UART
while (serverClients[i].available()) {
//发送到串口调试器
Serial.write(serverClients[i].read());
}
}
}
}
if (Serial.available()) {
//把串口调试器发过来的数据 发送给client
size_t len = Serial.available();
uint8_t sbuf[len];
Serial.readBytes(sbuf, len);
//给每个Client客户端发送数据
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
if (serverClients[i] && serverClients[i].connected()) {
serverClients[i].write(sbuf, len);
delay(1);
}
}
}
if(millis()-pushtime >= 500){
digitalWrite(LED,!digitalRead(LED));
pushtime = millis();
int num = rand() % 130;
// Json对象对象树的内存工具 静态buffer
// 200 是大小 如果这个Json对象更加复杂,那么就需要根据需要去增加这个值.
StaticJsonBuffer<256> jsonBuffer;
char json[60];
// StaticJsonBuffer 在栈区分配内存 它也可以被 DynamicJsonBuffer(内存在堆区分配) 代替
// DynamicJsonBuffer jsonBuffer;
//创建最外层的json对象 —— root对象,顶节点
JsonObject& root = jsonBuffer.createObject();
//给最外层json对象添加属性
root["name"] = "liuzewen";
root["rand"] = num;
//在root对象中加入data数组
JsonArray& data = root.createNestedArray("data");
data.add(48.756080);
data.add(2.302038);
//root.printTo(server);
//root.printTo(serverClients[0]);
root.printTo(Serial);
DebugPrintln();
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_wqy16_t_gb2312);
u8g2.setCursor(40, 16*1-2);
u8g2.print("Json发送");
u8g2.setCursor(0, 16*2-2);
u8g2.print("name:");
u8g2.setCursor(40, 16*2-2);
u8g2.print("liuzewen");
u8g2.setCursor(0, 16*3-2);
u8g2.print("rand:");
u8g2.setCursor(40, 16*3-2);
u8g2.print(num);
u8g2.setCursor(0, 16*4-2);
u8g2.print("date:");
u8g2.setCursor(40, 16*4-2);
u8g2.print("48.756080");
u8g2.sendBuffer();
sprintf(json, "{\"name\":\"liuzewen\",\"rand\":%d,\"data\":[48.756080,2.302038]}",num);
int len = sizeof(json);
//Serial.printf("缓存大小是:%d",sizeof("{\"name\":\"liuzewen\",\"rand\":200,\"data\":[48.756080,2.302038]}"));
//给每个Client客户端发送数据
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
if (serverClients[i] && serverClients[i].connected()) {
serverClients[i].write(json, len);
//root.printTo(serverClients[i]);
delay(1);
}
}
}
}