STM32-心知天气项目

一、项目需求

使用 ESP8266 通过 HTTP 获取天气数据(心知天气),并显示在 OLED 屏幕上。
按键 1 :循环切换今天 / 明天 / 后天天气数据;
按键 2 :更新天气。

二、项目框图

三、cjson作用

https://github.com/DaveGamble/cJSON/releases/tag/v1.7.18

cjson可以把json代码来回解析和打包

cjson的移植

1、把cjson拷贝到项目文件中

2、#include添加cjson头文件

3、根据自己的需求修改堆栈

四、项目实现

4.1 项目前期准备

 加载文件

在主函数中写入头文件和初始化函数

4.2 修改oled文件

先从oled开始修改

取字模

在心知天气平台中可以看到有39种天气

这里只取晴、多云、阴、雨,雪五种天气,也可以按需求自己取天气

生成字模,放到font.h文件中

修改oled中显示汉字的代码

别忘了修改.h文件

编译之后--无错误

接下来将oled的排版排一下

重新定义一个函数

 别忘了在oled.h文件中加入函数

主函数中调用一下函数名,就可以显示(可以先把esp8266的初始化函数先注释掉,太浪费时间)

显示结果如下:

4.3 修改esp8266文件

剩下的信息就要从json包中获取了

日期、天气状态、温度

需要修改esp8266代码,通过http协议访问心知天气平台,利用cjosn包解析想要的信息

esp8266是通过串口2来传递信息的,所以在uart1.c文件中需要加入串口2的应用

打开项目文件36-编程实现ESP8266连接TCP服务器

复制这段代码到本项目中的uart1.c

如何获取心知天气的天气呢?

在心知天气中,可以获取一个关于天气的api

将这个api丢到浏览器上,就可以看到关于天气的json包

这个过程就是http请求。

那么esp8266如何发起一个http的请求呢?

直接通过esp8266把api给发送(send)出去

代码如下:

//获取天气的信息,从天这个单位来获取,某一天day
uint8_t esp8266_get_weather(uint8_t day)
{//4、定义一个变量判断返回值是否是正确的uint8_t ret = ESP8266_ERROR;//默认返回值为error//1、构建HTTP请求的数据包,存放api的char http_request[200] = {0};//2、使用sprintf将api丢到数据包数组中,前面加一个GET,获取这个API包sprintf(http_request,"GET https://api.seniverse.com/v3/weather/daily.json?key=S35Rrryu2DExg-Hku&location=beijing&language=zh-Hans&unit=c&start=%d&days=3\r\n",day);//3、如何判断发给服务器的数据发送成功?//进入到获取数据这部分了,通过串口将数据发送到服务器上,ret = esp8266_send_command(http_request,"results");//同时期待返回值results//打印出来结果printf("%s\r\n",esp8266_rx_buf);if(ret == ESP8266_EOK)//判断返回值是否是okreturn ESP8266_EOK;elsereturn ESP8266_ERROR;}//复制RX引脚接收到的信息--目的是避免使用了extern
uint16_t esp8266_copy_rxdata(char *data)
{//将数据复制到data中memcpy(data, esp8266_rx_buf, esp8266_cntPre);return esp8266_cntPre;
}

要修改心知天气的地址和端口号

主函数

扩大长度

结果如下所示:

4.4 解析提取JSON数据包中需要的信息

根据自己的需求修改堆栈

新建文件weather

加载项目文件

头文件

新建的weather是用来书写天气的信息的

代码如下:

void get_3days_weather(void)
{uint8_t i = 0;for(i = 0; i < 3; i++){memset(weather_data, 0, sizeof(weather_data));esp8266_get_weather(i);esp8266_copy_rxdata(weather_data);//1. 将JSON字符串转换成JSON结构体cJSON *cjson = cJSON_Parse((const char *)weather_data);//2. 解析JSON各个字段//2.1 获取根对象里的results字段的值(数组1)cJSON *results = cJSON_GetObjectItem(cjson, "results");//2.2 获取数组1的第一个元素(对象1)cJSON *first_result = cJSON_GetArrayItem(results, 0);//2.3 获取对象1中的daily字段的值(数组2)cJSON *daily = cJSON_GetObjectItem(first_result, "daily");//2.4 获取数组2中的第一个元素(对象2)cJSON *first_daily = cJSON_GetArrayItem(daily, 0);//2.5 获取对象2中的data字段的值cJSON *date = cJSON_GetObjectItem(first_daily, "date");const char *date_str = date->valuestring;printf("date: %s\r\n", date_str);strcpy(three_day_weather[i].date, date_str);//2.6 获取对象2中的code_day字段的值cJSON *code_day = cJSON_GetObjectItem(first_daily, "code_day");const char *code_day_str = code_day->valuestring;printf("code_day: %s\r\n", code_day_str);strcpy(three_day_weather[i].code_day, code_day_str);//2.7 获取对象2中的high字段的值cJSON *high = cJSON_GetObjectItem(first_daily, "high");const char *high_str = high->valuestring;printf("high: %s\r\n", high_str);strcpy(three_day_weather[i].high, high_str);//2.8 获取对象2中的low字段的值cJSON *low = cJSON_GetObjectItem(first_daily, "low");const char *low_str = low->valuestring;printf("low: %s\r\n\r\n", low_str);strcpy(three_day_weather[i].low, low_str);//3. 清除JSON结构体cJSON_Delete(cjson);delay_ms(1000);}
}

在主函数中和.h文件中调用一下,应该会产生的结果是:

这里注意,如果产生的结果全部是乱码,或者部分信息是乱码,如下图所示:

这就有可能是你的堆栈没有设置足够

详情见下面链接

CSDN

扩大堆的空间只后,即可正确显示数据

最后我这里堆增加到了0x00001C00

4.5 显示天气

接下来就是显示天气,在主函数的while循环中判断按下的key键

代码如下:

void show_weather(uint8_t day)
{oled_show_init();oled_show_string(10,0,three_day_weather[day].date,16);//将字符串的”11“转变成数字的”11 “uint8_t code_day = atoi(three_day_weather[day].code_day);switch(code_day){case 0:case 1:case 2:case 3:oled_show_chinese(77, 2, 8); //晴break;case 4:case 5:case 6:case 7:case 8:oled_show_chinese(77, 2, 9); //多oled_show_chinese(90, 2, 10); //云break;case 9:oled_show_chinese(77, 2, 11); //阴break;case 10:case 11:case 12:case 13:case 14:case 15:case 16:case 17:case 18:case 19:case 20:oled_show_chinese(77, 2, 12); //雨break;case 21:case 22:case 23:case 24:case 25:oled_show_chinese(77, 2, 13); //雪break;default:break;        }oled_show_string(77,4,three_day_weather[day].high,16);oled_show_string(77,6,three_day_weather[day].low,16);
}

主函数代码如下:

uint8_t key_num = 0;uint8_t day = 0;while(1){ key_num = key_scan();if(key_num == 1)//切换天气{day++;day %= 3;show_weather(day);}else if(key_num == 2)//更新天气{printf("更新天气\r\n");get_3days_weather();show_weather(0);day = 0;}}

心知天气项目

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/22589.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自由学习记录(37)

课 对于这一方面&#xff0c;先把课都过一遍吧&#xff0c;尽量快的摸清楚底 软件工程 没有复杂的逻辑推理&#xff0c;概念性和理论很强&#xff0c;所以靠记 ------ 数据&#xff1a;是使程序能够适当处理信息的数据结构 程序&#xff1a;是能够完成预定功能和性能的可执行…

Docker仿真宇树狗GO1

1. 启动容器 docker run -it --rm humble_suo bash2. 安装Go1 的仿真包 apt update apt install -y git cmake build-essential git clone https://github.com/unitreerobotics/unitree_ros.git cd unitree_ros colcon build source install/setup.bash3. 启动仿真环境 ros2…

《游戏人工智能编程 案例精粹》阅读心得

最近读完了这本《游戏人工智能编程 案例精粹》&#xff0c;感觉获益匪浅&#xff0c;在对游戏人工智能的设计上有了更深的感悟。 这本书既适合初学者学习&#xff0c;因为次书会从最基础的数学物理公式推导一步一步介绍到完整的人工智能开发&#xff1b;同时也适合进阶程序员&a…

黑马点评_商品信息缓存模块

保证缓存不要有空档期 删除后马上要写入中间不能插入任何阶段(如查询数据库) 对于单体系统1&#xff0c;将缓存与数据库操作放在同一个事务中&#xff08;当前项目就是一个单体项目&#xff0c;所以选择这种方式&#xff09; 对于分布式系统2&#xff0c;利用TCC&#xff08;Tr…

OnlyOffice:前端编辑器与后端API实现高效办公

OnlyOffice&#xff1a;前端编辑器与后端API实现高效办公 一、OnlyOffice概述二、前端编辑器&#xff1a;高效、灵活且易用1. 完善的编辑功能2. 实时协作支持3. 自动保存与版本管理4. 高度自定义的界面 三、后端API&#xff1a;管理文档、用户与权限1. 轻松集成与定制2. 实时协…

面阵工业相机提高餐饮业生产效率

餐饮行业是一个快节奏、高要求的领域&#xff0c;该领域对生产过程中每一个阶段的效率和准确性都有很高的要求。在食品加工、包装、质量控制和库存管理等不同生产阶段实现生产效率的优化是取得成功的关键步骤。面阵工业相机能够一次性捕捉对象的二维区域图像&#xff0c;并支持…

现场可以通过手机或者pad实时拍照上传到大屏幕的照片墙现场大屏电子照片墙功能

现场可以通过手机或者pad实时拍照上传到大屏幕的照片墙现场大屏电子照片墙功能&#xff0c;每个人都可以通过手机实时拍照上传到大屏幕上,同时还可以发布留言内容&#xff0c;屏幕上会同步滚动播放展示所有人的照片和留言。相比校传统的照片直播功能更加灵活方便&#xff0c;而…

【多线程】线程安全

目录 一、初识线程安全 什么是线程安全问题 理解线程不安全的原因 原因总结 二、解决线程不安全 加锁&#x1f510; 锁对象 synchronized几种使用方式 死锁&#x1f50f; 死锁的三个场景 (1)一个线程针对一把锁连续加锁两次 (2)两个线程两把锁 (3)N个线程M个锁 如…

传统文旅+AI构建数字文旅新生态

传统文旅AI构建数字文旅新生态 前言&#xff1a; 当前许多旅游景区在旅游管理和旅游基础设施配套上都下足了功夫&#xff0c;在一定程度上也给旅客和消费者带来了舒适的体验感。但是针对于我们游客而言&#xff0c;似乎只有欣赏沿途风景、了解景区历史文化、拍照打卡和品尝特色…

VSCode - VSCode 切换自动换行

VSCode 自动换行 1、基本介绍 在 VSCode 中&#xff0c;启用自动换行可以让长行代码自动折行显示&#xff0c;避免水平滚动条频繁使用&#xff0c;提升代码阅读体验 如果禁用自动换行&#xff0c;长行代码就需要手动结合水平滚动条来阅读 2、演示 启用自动换行 禁用自动换…

解锁音频新境界:LALAL.AI 与 Audo Studio 深度解析

在音频处理的世界里&#xff0c;噪音常常是困扰我们的一大难题。无论是专业的音频工作者&#xff0c;还是普通的音频爱好者&#xff0c;都渴望拥有一款强大的工具来解决这个问题。今天&#xff0c;就为大家介绍两款来自 AI 工具导航&#xff08;AIDH.NET&#xff09;的 AI 语音…

线上死锁问题排查和处理

Java 死锁排查 通过 jps jstack 来定位和排查 如果线程长时间处于阻塞&#xff0c;就需要考虑是否是死锁了。 模拟死锁 public class DeadlockDemo {private static final Object lock1 new Object();private static final Object lock2 new Object();public static vo…

5 分钟用满血 DeepSeek R1 搭建个人 AI 知识库(含本地部署)

最近很多朋友都在问&#xff1a;怎么本地部署 DeepSeek 搭建个人知识库。 老实说&#xff0c;如果你不是为了研究技术&#xff0c;或者确实需要保护涉密数据&#xff0c;我真不建议去折腾本地部署。 为什么呢&#xff1f; 目前 Ollama 从 1.5B 到 70B 都只是把 R1 的推理能力…

MT7628基于原厂的SDK包, 修改ra1网卡的MAC方法。

1、在/etc/config/wireless文件添加多个WIFI网卡的方法。 2、修改WIFI驱动&#xff0c;在src/embedded/ap/ap.c文件里面&#xff0c;从系统文件信息来修改ra1网卡的MAC内容&#xff0c;添加红色部分源代码。 RTMP_IO_WRITE32(pAd, RMAC_RMACDR, Value); if (idx > 0) …

brew Nushell mac升级版本

运行命令&#xff1a; brew upgrade nushell 国内更新比较慢建议架个梯子。 如果没有更新则先更新一下brew brew update 更新后看下版本是否死最新的了

windows怎样查看系统信息(处理器等)

首先打开命令行工具 win R 输入 cmd&#xff0c; 输入 msinfo32 &#xff0c;然后回车 这个页面就可以看到 电脑的锐龙版就是 AMD 芯片 酷睿版就是 intel 芯片

mysql之Innodb数据页

Innodb数据页结构 InnoDB数据页结构一、数据页基础概念二、数据页核心结构1. 头部控制区2. 数据存储区3. 尾部与目录区 三、关键机制详解1. 记录链表与删除优化2. 页目录与二分查找3. 空间复用与碎片管理4. 数据页的合并与分裂 四、应用与性能影响1. 索引效率2. 插入优化3. 事务…

1200沿指令和取反指令的应用。

以下是关于西门子S7-1200 PLC中沿指令&#xff08;边沿检测指令&#xff09;和取反指令的详细解析及应用示例&#xff0c;结合其工作原理、编程方法和典型场景&#xff1a; 一、沿指令&#xff08;边沿检测指令&#xff09; 1. 功能说明 沿指令用于检测信号状态的变化&#x…

three.js之特殊材质效果

*案例42 创建一个透明的立方体 <template><div ref"container" className"container"></div> </template><script setup> import * as THREE from three; import WebGL from three/examples/jsm/capabilities/WebGL.js // 引…

三格电子上新了——PLC 数据采集网关

型号&#xff1a;SG-PLC-Private 第一章 产品概述 PLC 转 Modbus 网关型号 SG-PLC-Private &#xff08; PLC 私有协议网关&#xff09;&#xff0c;是三格电子推出的工业 级网关&#xff08;以下简称网关&#xff09;&#xff0c;主要用于 在不需要对 PLC 编程的情况…