Advertisement

基于STM32+ESP8266的奥运会奖牌榜设计之经典

阅读量:

本实验旨在掌握ESP8266模块的TCP协议应用及JSCon库的使用,并通过编程实现东京奥运会奖牌榜的显示功能。实验中使用Windows系统安装有KEIL5和USART HMI软件完成硬件搭建。主要步骤包括:1)配置WiFi与服务器连接;2)通过串口获取奖牌榜数据接口;3)利用JSON格式解析数据并显示结果。实验中发现,在STM32F103系列芯片中若采用STM32F103C8T6可能会导致内存溢出问题。

(一)实验目的和任务

1、掌握esp8266模块的TCP协议,进行联网和服务器

2、熟悉jscon库的移植和API的使用,对jscon格式的数据进行解析

3、掌握LCD或串口屏显示东京奥运会奖牌榜

(二)实验设备介绍

1、系统需求:安装有windows系统的PC机

KEIL 5开发套件将支持串口 USART模块与HMI界面开发工具。

(三)实验步骤

3.1 WiFi****和服务器连接

AT指令:

1.AT

回复:AT OK

2.WiFi连接

WIFI功能指令(模式)

该方案采用客户端架构设计,在无线局域网环境下实现与其他设备间的通信功能

**SoftAP模式(软路由模式):该模块类似于一个路由器,并通过网络接口与外部设备进行通信

Station+softAP模式(混合模式):当其他设备进行连接时,该模块可充当无线接入点

station模式:

1、WIFI模式设置指令:AT+CWMODE_DEF=1 回复:AT+CWMODE_DEF=1 OK
2、WIFI 模式查询指令:AT+CWMODE? 回复:+CWMODE:1 //1:station 模式 2:softAP 模式 3:station+softAP 模式 OK
3、连接 AP 指令:AT+CWJAP_DEF=”mwh”,”123123123” 回复:AT+CWJAP_DEF="mwh","123123123" WIFI CONNECTED WIFI GOT IP OK
4、断开与 AP 连接指令:AT+CWQAP 回复:AT+CWQAP OK WIFI DISCONNECT
5**、连接 TCP 服务器** 指令:AT+CIPSTART="TCP","111.206.176.78",80 响应:OK
6**、开启透传模式传输数据** 指令:AT+CIPMODE=1 响应:OK
7**、发送数据** 指令:AT+CIPSEND 响应:>
8、退出透传模式 在透传传输数据过程中,若识别到数据“+++”就会退出透传模式。所以,发送“+++”即可退出透传模式,注 意不要加\r\n 结尾。
9**、断开与 TCP 服务器连接** 指令:AT+CIPCLOSE 响应:CLOSED OK
10**、断开与 AP 的连接** 指令:AT+CWQAP 响应:OK

3.2获取网址API接口数据

//串口2,printf 函数 //确保一次发送数据不超过USART2_MAX_SEND_LEN字节 void u2_printf(char *fmt, ...) { u16 i, j; va_list ap; va_start(ap, fmt); vsprintf((char *)USART2_TX_BUF, fmt, ap); va_end(ap); i = strlen((const char *)USART2_TX_BUF); //此次发送数据的长度 for (j = 0; j < i; j++) //循环发送数据 { while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); //循环发送,直到发送完毕 USART_SendData(USART2, USART2_TX_BUF[j]); } }
uint8_t get_api(char *api_addr, uint8_t (parse_fun)(void)) { printf("获取东京奥运会奖牌榜:\r\nGET %s\r\n", api_addr); u2_printf("GET %s\r\n\r\n", api_addr); delay_ms(20); USART2_RX_STA = 0; delay_ms(1000); printf("%d\r\n",USART2_RX_STA); if (USART2_RX_STA & 0X8000) { USART2_RX_BUF[USART2_RX_STA & 0X7FFF] = 0; //添加结束符 } // printf("接收到:%d bytes\r\n%s\r\n\r\n", strlen((const char)USART2_RX_BUF),USART2_RX_BUF); parse_fun(); USART2_RX_STA = 0; memset(USART2_RX_BUF, 0, sizeof(USART2_RX_BUF)); // atk_8266_quit_trans(); // printf("退出透传\r\n"); return 0; }

3.3解析JOSN字符串

在cJSON.h中定义了一个名为cJSON的结构体类型:
使用typedef关键字声明该结构体类型{
该结构体内包含以下几个字段:

  • 前向和后向链表指针_next,_ prev;
  • 存储父节点孩子的_child域;
  • 指定键的数据类型的type字段;
  • 存储字符串值的valuestring字段;
  • 记录整数值信息的价值int字段;
  • 存储浮点数值数据的valuedouble字段;
    以及表示键名信息的string字段。

实现将const char类型的字符串解析为cJSON结构体。
该方法用于获取指定键名的方法:给定一个指向器和const char
参数。
该方法用于释放指向器所指的cJSON数据结构。

| 1、解析一个简单的键值对字符串:
|
$${}$
| 其中字符串中健为 key ,值为 value 。 使用如下:
| char *str = "花括号里面的(")前面必须加()"将其转换为转义字符以避免与C语言字符串冲突";
| char *root = NULL , *ret = NULL;
| root = cJSON_Parse(str); // 将cJSON字符串转换为cJSON结构体指针
| ret = cJSON_GetObjectItem(root, "key"); // 在 root 结构体中查找 "key" 这个键(一个字符串),成功返回一个cJSON结构体失败返回NULL 。
| printf("%s\n", ret->valuestring); // 打印出来的结果是 value
| cJSON_Delete(root); // 释放cJSON结构体
|
|
||

| 2、解析复杂一点的cJSON结构体:
{
"json": {
"num": -1,
"num_1": 0,
"num_2": 1,
"string": "str",
"string_1": "abcd",
"string_2": "123abc123"
},
"string": "str",
"num": 2
}
同样使用上面那三个函数搞定:
/****解析cJSON/
char str = "{"json": {"num": -1,"num_1": 0,"num_2": 1,"string": "str","string_1": "abcd","string_2": "123abc123"},"string": "str","num": 2}";
char root = NULL , ret = NULL, json = NULL;//定义三个cJOSN结构体指针
root = cJSON_Parse(str);//将cJSON字符串转换为cJSON结构体指针
json = cJSON_GetObjectItem(root, "json");//在root结构体中查找"josn"

_/--------------------------_解析"json"---------------------------/
ret = cJSON_GetObjectItem(json, "num");//在josn结构体中查找"num"
printf("%d\n", ret->valueint);//打印出来的结果是-1

_ret = cJSON_GetObjectItem(json, "num_1");//_在josn结构体中查找"num_1"
printf("%d\n", ret->valueint);//打印出来的结果是0

_ret = cJSON_GetObjectItem(json, "num_2");//_在josn结构体中查找"num_2"
printf("%d\n", ret->valueint);//打印出来的结果是1

_ret = cJSON_GetObjectItem(json, "string");//_在josn结构体中查找"string"
printf("%s\n", ret->valuestring);//打印出来的结果是str

_ret = cJSON_GetObjectItem(json, "string_1");//_在josn结构体中查找"string_1"
printf("%s\n", ret->valuestring);//打印出来的结果是abcd

_ret = cJSON_GetObjectItem(json, "string_2");//_在josn结构体中查找"string_2"
printf("%s\n", ret->valuestring);//打印出来的结果是123abc123

_/-------------------------------_解析"json" end----------------------- /
json = cJSON_GetObjectItem(root, "string");//在root结构体中查找"string"
printf("%s\n", ret->valuestring);//打印出来的结果是str
ret = cJSON_GetObjectItem(root, "num");//在root结构体中查找"num"
printf("%d\n", ret->valueint);//打印出来的结果是2

cJSON_Delete(root);//释放总的cJSON结构体只需要释放cJSON_Parse函数创建的cJOSN结构体即可

| 3、解析JSON结构体数组:
再多用到两个函数:
int cJSON_GetArraySize(cJSON array);//__获取JSON数组的大小
cJSON_cJSON_GetArrayItem(cJSON *array,int item); //获取数组下标的成员
解析复杂更一点的JSON结构体和JSON结构体:
{
"array": [{
"num_0": 0,
"string_0": "str0"
},
{
"num_1": 1,
"string_1": "str1"
},
{
"num_2": 2,
"string_2": "str2"
}
]
}
char *str = "{"array": [{"num_0": 0,"string_0": "str0"},{"num_1": 1,"string_1": "str1"},{"num_2": 2,"string_2": "str2"}]}";
char *root = NULL, *ret = NULL, *arr = NULL, *json = NULL;//定义4个cJOSN结构体指针
int size = 0;//用于存储数组大小
/****解析cJSON/
root = cJSON_Parse(str);//将cJSON字符串转换为cJSON结构体指针
arr= cJSON_GetObjectItem(root, "array");//在root结构体中查找"array" size = cJSON_GetArraySize(arr);//此时size值为3
/
-------------------------1------------------------------------_ /
json= cJSON_GetArrayItem(arr, 0);//获取数组第1个成员
ret = cJSON_GetObjectItem(json, "num_0");//在josn结构体中查找"num_0"
printf("%d\n", ret->valueint);//打印出来的结果为:0
ret = cJSON_GetObjectItem(json, "string_0");//在josn结构体中查找"string_0"
printf("%s\n", ret->valuestring);//打印出来的结果为:str0
/-------------------------1 end------------------------------- /
/-------------------------2------------------------------------ /
json= cJSON_GetArrayItem(arr, 1);//获取数组第2个成员
ret = cJSON_GetObjectItem(json, "num_1");//在josn结构体中查找"num_1"
printf("%d\n", ret->valueint);//打印出来的结果为:1
ret = cJSON_GetObjectItem(json, "string_1");//在josn结构体中查找"string_1"
printf("%s\n", ret->valuestring);//打印出来的结果为:str1
/-------------------------2 end------------------------------- /
/-------------------------3------------------------------------ /
json= cJSON_GetArrayItem(arr, 2);//获取数组第3个成员
ret = cJSON_GetObjectItem(json, "num_2");//在josn结构体中查找"num_1"
printf("%d\n", ret->valueint);//打印出来的结果为:2
ret = cJSON_GetObjectItem(json, "string_2");//在josn结构体中查找"string_2"
printf("%s\n", ret->valuestring);//打印出来的结果为:str2
/-------------------------3 end------------------------------- /
cJSON_Delete(root);//释放cJSON结构体

(四)实验现象

注意:使用的芯片为STM32F103系列 如果使用STM32F103C8T6会出现内存溢出的情况。

参考文献链接:[(15条消息) STM32使用API函数奖牌具体实现了相应功能-嵌入式文档类资源-文库

icon-default.png?t=M276

"15条消息 STM32使用API函数奖牌的具体阐述其功能实现细节-嵌入式文档类资源-文库"

案例参考网址为:http://www.wangchaochao.top/2021/04/18/stm32-ncov-vaccine/

总结:只有在实践中总结,才能走的更远,领悟技术的细节。

全部评论 (0)

还没有任何评论哟~