打印
[国产单片机]

【自选开发板活动】基于单片机TK499的天气信息获取与显示

[复制链接]
561|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 xinmeng_wit 于 2022-5-1 21:20 编辑


一、介绍
上一篇帖子已经对TK499单片机和开发板进行了大致的介绍,并且基于TK499开发板进行了LVGL的开源图形库的移植。
具体详细信息可以参考帖子:【自选开发板活动】基于国产单片机TK499的GUI图形库LVGL移植

TK499开发板显著的特征除了分辨率为800*480的显示屏以外,还带有板载的wifi模块:esp8266。
正是因为有esp8266的存在,这款开发板具有很多无线通讯方面的可玩性。

这一篇帖子将使用esp8266与外网进行连接并获取实时天气信息并显示在LCD屏上。

二、功能实现
1、软硬件使用情况
  • 开发环境:Keil MDK5.26.2
  • 使用到的硬件资源:UART1、UART2、timer3、timer8、ADC
  • esp8266配置为sta模式TCP client
以上用到的硬件资源中,UART1作为调试串口使用,打印关键信息便于调试;
UART2与esp8266连接;
timer3配置为1ms的中断,用于lvgl调度和单片机时基
timer8用于串口的超时定时器
ADC用于触摸,该单片机不需要外加触摸芯片,自带有触摸功能,是使用ADC的四个通道实现的。

2、esp8266使用到的指令
  • AT+CWMODE=1
esp8266设置为STA模式
  • AT+CWJAP=ssid,password
加入无线网络
  • AT+CIPMUX=?
是否启用多连接
  • AT+CIPSTART=TCP,IP,PORT
连接到指定的服务器
  • AT+CIPMODE=1
设置为透传


3、天气数据的请求与解析
要获取天气信息就需要向天气网站请求天气数据,然后进行解析。
常用的天气网站有很多,比如大家熟悉的心知天气,还有YY天气;
我这篇使用的是YY天气,网址:http://www.yytianqi.com/
数据请求格式:





返回的数据格式:

显然,YY天气返回的数据是JSON格式的。
对于JSON格式的解析,有很多开源库可以很方便的解析出来,例如比较常用的cJSON库。
因为这段JSON数据非常简单,我这里就直接手动解析了,不想折腾开源库了。

4、代码实现
以上原理性的东西大概都说了,现在就开始骂代码的了。
下面对主要功能模块进行讲解。

主函数主要hi对各个模块进行初始化,然后显示一些初始化的界面:
int main(void)
{
        uint32_t  i;
        RemapVtorTable();
        SystemClk_HSEInit(RCC_PLLMul_20);//启动PLL时钟,12MHz*20=240MHz
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//2:2,全局性函数,仅需设置一次
        UartInit(UART1,115200);      //配置串口1,波特率为460800
        TIM3_Config(1000,240);//1ms interrupt,use for LVGL period update
        TIM8_Config(1000,240);//1ms,use for esp8266        
        lv_init();//初始化LVGL库
        lv_port_disp_init();//LVGL显示相关的初始化
        lv_port_indev_init();//LVGL触摸相关的初始化
        welcome2_windows_init();//欢迎界面初始化
        welcome_windows_show(welcome_label2,"www.21ic.com\r\nxinmeng_wit");//显示欢迎界面
        Delay_nms ( 3000 );
        lv_obj_del(welcome_label2);
        welcome_windows_init();
        welcome_windows_show(welcome_label1,"Initializing...");
        //TIM10_Config(2000,240);//10ms
        printf("Welcome to use HJR TK499!\r\n");
        Delay_nms ( 200 );//等待esp8266上电完成        
        Uart2Init(115200);        
        ESP8266_Tcp_mode_Test();//sta TCP client
        //test_demo();
        //test_demo2();
        //lv_demo_widgets();
        while(1)//无限循环
        {               
                char temp[50];
                lv_task_handler();
               
                if(uart2_rec_flag != 0)//需要接收uart2返回
                {
                        printf("uart2_rec_flag:%d\r\n",uart2_rec_flag);
                        Delay_nms(1000);
                        
                        weather_str[weather_cnt] = '\0';
                        printf("%d\r\n",weather_cnt);
                        printf("%s\r\n",(char *)&weather_str[0]);
                        //welcome_windows_show(welcome_label1,(char *)&weather_str[0]);
                        weather_data_analysis((char *)&weather_str[0]);
                        weather_cnt = 0;        
                        uart2_rec_flag = 0;
                }
        }
}
天气信息的解析是最重要的部分,主要解析五个元素:
  • 城市
  • 天气
  • 温度
  • 湿度
  • 风力
  • 数据的更新时间

具体解析过程详见代码:

#include "lvgl.h"
#include "string.h"
#include "weather.h"
#include "gui_app.h"

t_weather_type weather_data;


//城市代码转换为城市的拼音
static void city_code_to_city(char *city_code, char *des)
{
        if((city_code[0] != 'C') || (city_code[1] != 'H'))
        {
                return;
        }
        if((city_code[2] == '0') && (city_code[3] == '1'))
        {
                memcpy(des,"Beijing",sizeof("Beijing"));
        }
        else if((city_code[2] == '0') && (city_code[3] == '2'))
        {
                memcpy(des,(char *)"Shanghai",sizeof("Shanghai"));
                printf("code:%s,%d\n",city_code,sizeof("Shanghai"));
        }
        else if((city_code[2] == '0') && (city_code[3] == '3'))
        {
                memcpy(des,"Tianjin",sizeof("Tianjin"));
        }        
        else if((city_code[2] == '0') && (city_code[3] == '4'))
        {
                memcpy(des,"Chongqing",sizeof("Chongqing"));
        }        
}

//天气代码转换为天气英文
static void numtq_to_tq(char *num_code, char *des)
{
        uint16_t temp = 0;
        uint16_t len;
        
        len = strlen(num_code);
        
        if(len == 2)
        {
                temp = (num_code[0] - '0')* 10 + (num_code[1] - '0');//代码转为为数字
        }
        else if(len == 3)
        {
                temp = (num_code[0] - '0') * 100 + (num_code[1] - '0') * 10 + (num_code[2] - '0');//代码转为为数字
        }
        
        if(temp > 100)//超出范围,数据无效
        {
                return;
        }
        
        switch(temp)
        {
                case 0://晴
                        memcpy(des,"Sunny",sizeof("Sunny"));
                break;
               
                case 1://多云
                        memcpy(des,"Cloudy",sizeof("Cloudy"));
                break;               

                case 2://阴
                        memcpy(des,"Overcast",sizeof("Overcast"));
                break;
               
                case 3://阵雨
                        memcpy(des,"1Shower",sizeof("1Shower"));
                break;

                case 4://雷阵雨
                        memcpy(des,"Thundershower",sizeof("Thundershower"));
                break;
               
                case 5://雷阵雨伴有冰雹
                        memcpy(des,"Thundershower with hail",sizeof("Thundershower with hail"));
                break;               

                case 6://雨夹雪
                        memcpy(des,"1Sleet",sizeof("1Sleet"));
                break;
               
                case 7://小雨
                        memcpy(des,"Light rain",sizeof("Light rain"));
                break;        

                case 8://中雨
                        memcpy(des,"Moderate rain",sizeof("Moderate rain"));
                break;
               
                case 9://大雨
                        memcpy(des,"Heavy rain",sizeof("Heavy rain"));
                break;               

                case 10://暴雨
                        memcpy(des,"Storm",sizeof("Storm"));
                break;
               
                case 11://大暴雨
                        memcpy(des,"Heavy storm",sizeof("Heavy storm"));
                break;

                case 12://特大暴雨
                        memcpy(des,"Severe storm",sizeof("Severe storm"));
                break;
               
                case 13://阵雪
                        memcpy(des,"Snow flurry",sizeof("Snow flurry"));
                break;               

                case 14://小雪
                        memcpy(des,"Light snow",sizeof("Light snow"));
                break;
               
                case 15://中雪
                        memcpy(des,"Moderate snow",sizeof("Moderate snow"));
                break;        

                case 16://大雪
                        memcpy(des,"Heavy snow",sizeof("Heavy snow"));
                break;
               
                case 17://暴雪
                        memcpy(des,"Snowstorm",sizeof("Snowstorm"));
                break;               

                case 18://雾
                        memcpy(des,"Fog",sizeof("Fog"));
                break;
               
                case 19://冻雨
                        memcpy(des,"Ice rain",sizeof("Ice rain"));
                break;

                case 20://沙尘暴
                        memcpy(des,"Duststorm",sizeof("Duststorm"));
                break;
               
                case 21://小到中雨
                        memcpy(des,"Light to moderate rain",sizeof("Light to moderate rain"));
                break;               

                case 22://中到大雨
                        memcpy(des,"Moderate to heavy rain",sizeof("Moderate to heavy rain"));
                break;
               
                case 23://大到暴雨
                        memcpy(des,"Heavy rain to storm",sizeof("Heavy rain to storm"));
                break;

                case 24://暴雨到大暴雨
                        memcpy(des,"Storm to heavy storm",sizeof("Storm to heavy storm"));
                break;
               
                case 25://暴雨到特大暴雨
                        memcpy(des,"Heavy to severe storm",sizeof("Heavy to severe storm"));
                break;               

                case 26://小到中雪
                        memcpy(des,"1Light to moderate snow",sizeof("1Light to moderate snow"));
                break;
               
                case 27://中到大雪
                        memcpy(des,"Moderate to heavy snow",sizeof("Moderate to heavy snow"));
                break;

                case 28://大到暴雪
                        memcpy(des,"Heavy snow to snowstorm",sizeof("Heavy snow to snowstorm"));
                break;
               
                case 29://浮尘
                        memcpy(des,"Dust",sizeof("Dust"));
                break;               

                case 30://扬沙
                        memcpy(des,"Sand",sizeof("Sand"));
                break;
               
                case 31://强沙尘暴
                        memcpy(des,"Sandstorm",sizeof("Sandstorm"));
                break;        

                case 32://浓雾
                        memcpy(des,"Dense fog",sizeof("Dense fog"));
                break;
               
                case 49://强浓雾
                        memcpy(des,"Heavy dense fog",sizeof("Heavy dense fog"));
                break;               

                case 53://霾
                        memcpy(des,"Haze",sizeof("Haze"));
                break;
               
                case 54://中度霾
                        memcpy(des,"Moderate haze",sizeof("Moderate haze"));
                break;

                case 55://重度霾
                        memcpy(des,"Severe haze",sizeof("Severe haze"));
                break;
               
                case 56://严重霾
                        memcpy(des,"Hazardous haze",sizeof("Hazardous haze"));
                break;               

                case 57://大雾
                        memcpy(des,"heavy fog",sizeof("heavy fog"));
                break;
               
                case 58://特强浓雾
                        memcpy(des,"Extra-heavy dense fog",sizeof("Extra-heavy dense fog"));
                break;

                case 99://无
                        memcpy(des,"Unknown",sizeof("Unknown"));
                break;
               
                case 100://刮风
                        memcpy(des,"Windy",sizeof("Windy"));
                break;

                default:
               
                break;
        }
}

//风力代码转换为风力英文
static void numfl_to_fl(char *num_code, char *des)
{
        uint16_t temp = 0;
        
        temp = num_code[0] - '0';
        
        switch(temp)
        {
                case 0:
                        memcpy(des,"breeze",sizeof("breeze"));
                break;
               
                case 1:
                        memcpy(des,"3~4",sizeof("3~4"));
                break;        

                case 2:
                        memcpy(des,"4~5",sizeof("4~5"));
                break;
               
                case 3:
                        memcpy(des,"5~6",sizeof("5~6"));
                break;        
               
                case 4:
                        memcpy(des,"6~7",sizeof("6~7"));
                break;
               
                case 5:
                        memcpy(des,"7~8",sizeof("7~8"));
                break;        

                case 6:
                        memcpy(des,"8~9",sizeof("8~9"));
                break;
               
                case 7:
                        memcpy(des,"9~10",sizeof("9~10"));
                break;        

                case 8:
                        memcpy(des,"10~11",sizeof("10~11"));
                break;
               
                case 9:
                        memcpy(des,"11~12",sizeof("11~12"));
                break;        
               
                default:
               
                break;
        }
        
}

void weather_data_analysis(char* str)
{
        uint16_t index = 0;
        char* temp;
        char temp_str[50];
        char temp_str2[50];
        
        //判断是否收到了正确的天气数据帧
        if(strstr(str,"Sucess") == NULL)
        {
                return;
        }
        
        //解析城市id
        temp = strstr(str,"cityId");
        index = temp - str;
        memcpy(&weather_data.cityid[0],temp + CITY_ID_OFFSET,CITY_ID_SIZE);
        weather_data.cityid[CITY_ID_SIZE] = '\0';//添加字符串结束符
        
        city_code_to_city(&(weather_data.cityid[0]), temp_str2);//代码转换为城市拼音
        printf("%s\r\n",&(weather_data.cityid[0]));
        
        sprintf(temp_str,"city : %s",temp_str2);
        weather_windows_show(city_label,temp_str);
        
        //解析气温
        temp = strstr(str,"qw");
        index = temp - str;
        memcpy(&weather_data.air_temperature[0],temp + QW_OFFSET,QW_SIZE);
        weather_data.air_temperature[QW_SIZE] = 'C';
        weather_data.air_temperature[QW_SIZE + 1] = '\0';//添加字符串结束符
        
        sprintf(temp_str,"temp : %s",&(weather_data.air_temperature[0]));
        weather_windows_show(temp_label,temp_str);        

        //解析湿度
        temp = strstr(str,"sd");
        index = temp - str;
        memcpy(&weather_data.humidity[0],temp + SD_OFFSET,SD_SIZE);
        weather_data.humidity[SD_SIZE] = '%';
        weather_data.humidity[SD_SIZE + 1] = '\0';//添加字符串结束符        

        sprintf(temp_str,"humi : %s",&(weather_data.humidity[0]));
        weather_windows_show(humi_label,temp_str);        
        
        //解析天气编码
        temp = strstr(str,"numtq");
        index = temp - str;
        memcpy(&weather_data.weather_num[0],temp + TQ_NUM_OFFSET,TQ_NUM_SIZE);
        weather_data.weather_num[TQ_NUM_SIZE] = '\0';//添加字符串结束符        

        numtq_to_tq(&(weather_data.weather_num[0]), temp_str2);//天气代码转换为天气英文
        sprintf(temp_str,"weather : %s",temp_str2);
        weather_windows_show(weather_label,temp_str);

        //解析风力编码
        temp = strstr(str,"numfl");
        index = temp - str;        
        memcpy(&weather_data.wind_power[0],temp + FL_NUM_OFFSET,FL_NUM_SIZE);
        weather_data.wind_power[FL_NUM_SIZE] = '\0';//添加字符串结束符        
        
        numfl_to_fl(&(weather_data.wind_power[0]), temp_str2);
        sprintf(temp_str,"wind : %s",temp_str2);
        weather_windows_show(wind_label,temp_str);
        
        //解析更新时间
        temp = strstr(str,"lastUpdate");
        index = temp - str;               
        memcpy(&weather_data.update_time[0],temp + UPDATE_TIME_OFFSET,UPDATE_TIME_SIZE);
        weather_data.update_time[UPDATE_TIME_SIZE] = '\0';//添加字符串结束符        
        
        sprintf(temp_str,"lastUpdate : %s",&(weather_data.update_time[0]));
        weather_windows_show(update_label,temp_str);        
}
其它相关的都比较简单,不在这里详细讲解,如有疑问,可以线上或向下详细沟通。

三、效果图片



视频演示




使用特权

评论回复

相关帖子

沙发
xinmeng_wit|  楼主 | 2022-5-1 21:20 | 只看该作者
视频链接为什么没有显示

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

61

主题

214

帖子

1

粉丝