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)出去

代码如下:

cpp 复制代码
//获取天气的信息,从天这个单位来获取,某一天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)//判断返回值是否是ok
        return ESP8266_EOK;
    else
        return 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是用来书写天气的信息的

代码如下:

cpp 复制代码
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键

代码如下:

cpp 复制代码
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);
}

主函数代码如下:

cpp 复制代码
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;
        }
    }
相关推荐
嵌入式分享15 分钟前
嵌入式分享#41:RK3576改UART波特率【精简版】
linux·嵌入式硬件·ubuntu·嵌入式
典则1 小时前
STM32FreeRtos入门(四)——任务状态和调度
stm32·单片机·嵌入式硬件
充哥单片机设计1 小时前
【STM32项目开源】基于STM32的智能天然气火灾监控
stm32·单片机·嵌入式硬件
充哥单片机设计1 小时前
【STM32项目开源】基于STM32的智能仓库火灾检测系统
stm32·单片机·嵌入式硬件
就叫飞六吧3 小时前
普中stm32大Dap烧录流程
stm32
A9better4 小时前
嵌入式开发学习日志38——stm32之看门狗
stm32·嵌入式硬件·学习
小莞尔4 小时前
【51单片机】【protues仿真】基于51单片机智能路灯控制系统
c语言·stm32·单片机·嵌入式硬件·51单片机
辰哥单片机设计14 小时前
TT直流减速电机(STM32)
stm32
A9better14 小时前
嵌入式开发学习日志36——stm32之USART串口通信前述
stm32·单片机·嵌入式硬件·学习
思诺学长14 小时前
BMS(电池管理系统)的主要功能和架构简述
单片机·嵌入式硬件