xinmeng_wit 发表于 2022-5-1 21:17

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

本帖最后由 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_ti;
      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;
                lv_task_handler();
               
                if(uart2_rec_flag != 0)//需要接收uart2返回
                {
                        printf("uart2_rec_flag:%d\r\n",uart2_rec_flag);
                        Delay_nms(1000);
                        
                        weather_str = '\0';
                        printf("%d\r\n",weather_cnt);
                        printf("%s\r\n",(char *)&weather_str);
                        //welcome_windows_show(welcome_label1,(char *)&weather_str);
                        weather_data_analysis((char *)&weather_str);
                        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 != 'C') || (city_code != 'H'))
      {
                return;
      }
      if((city_code == '0') && (city_code == '1'))
      {
                memcpy(des,"Beijing",sizeof("Beijing"));
      }
      else if((city_code == '0') && (city_code == '2'))
      {
                memcpy(des,(char *)"Shanghai",sizeof("Shanghai"));
                printf("code:%s,%d\n",city_code,sizeof("Shanghai"));
      }
      else if((city_code == '0') && (city_code == '3'))
      {
                memcpy(des,"Tianjin",sizeof("Tianjin"));
      }      
      else if((city_code == '0') && (city_code == '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')* 10 + (num_code - '0');//代码转为为数字
      }
      else if(len == 3)
      {
                temp = (num_code - '0') * 100 + (num_code - '0') * 10 + (num_code - '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';
      
      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;
      char temp_str2;
      
      //判断是否收到了正确的天气数据帧
      if(strstr(str,"Sucess") == NULL)
      {
                return;
      }
      
      //解析城市id
      temp = strstr(str,"cityId");
      index = temp - str;
      memcpy(&weather_data.cityid,temp + CITY_ID_OFFSET,CITY_ID_SIZE);
      weather_data.cityid = '\0';//添加字符串结束符
      
      city_code_to_city(&(weather_data.cityid), temp_str2);//代码转换为城市拼音
      printf("%s\r\n",&(weather_data.cityid));
      
      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,temp + QW_OFFSET,QW_SIZE);
      weather_data.air_temperature = 'C';
      weather_data.air_temperature = '\0';//添加字符串结束符
      
      sprintf(temp_str,"temp : %s",&(weather_data.air_temperature));
      weather_windows_show(temp_label,temp_str);      

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

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

      numtq_to_tq(&(weather_data.weather_num), 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,temp + FL_NUM_OFFSET,FL_NUM_SIZE);
      weather_data.wind_power = '\0';//添加字符串结束符      
      
      numfl_to_fl(&(weather_data.wind_power), 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,temp + UPDATE_TIME_OFFSET,UPDATE_TIME_SIZE);
      weather_data.update_time = '\0';//添加字符串结束符      
      
      sprintf(temp_str,"lastUpdate : %s",&(weather_data.update_time));
      weather_windows_show(update_label,temp_str);      
}
其它相关的都比较简单,不在这里详细讲解,如有疑问,可以线上或向下详细沟通。

三、效果图片



视频演示




xinmeng_wit 发表于 2022-5-1 21:20

视频链接为什么没有显示
页: [1]
查看完整版本: 【自选开发板活动】基于单片机TK499的天气信息获取与显示