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

[复制链接]
 楼主| xinmeng_wit 发表于 2022-5-1 21:17 | 显示全部楼层 |阅读模式
本帖最后由 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对各个模块进行初始化,然后显示一些初始化的界面:
  1. int main(void)
  2. {
  3.         uint32_t  i;
  4.         RemapVtorTable();
  5.         SystemClk_HSEInit(RCC_PLLMul_20);//启动PLL时钟,12MHz*20=240MHz
  6.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//2:2,全局性函数,仅需设置一次
  7.         UartInit(UART1,115200);      //配置串口1,波特率为460800
  8.         TIM3_Config(1000,240);//1ms interrupt,use for LVGL period update
  9.         TIM8_Config(1000,240);//1ms,use for esp8266        
  10.         lv_init();//初始化LVGL库
  11.         lv_port_disp_init();//LVGL显示相关的初始化
  12.         lv_port_indev_init();//LVGL触摸相关的初始化
  13.         welcome2_windows_init();//欢迎界面初始化
  14.         welcome_windows_show(welcome_label2,"www.21ic.com\r\nxinmeng_wit");//显示欢迎界面
  15.         Delay_nms ( 3000 );
  16.         lv_obj_del(welcome_label2);
  17.         welcome_windows_init();
  18.         welcome_windows_show(welcome_label1,"Initializing...");
  19.         //TIM10_Config(2000,240);//10ms
  20.         printf("Welcome to use HJR TK499!\r\n");
  21.         Delay_nms ( 200 );//等待esp8266上电完成        
  22.         Uart2Init(115200);        
  23.         ESP8266_Tcp_mode_Test();//sta TCP client
  24.         //test_demo();
  25.         //test_demo2();
  26.         //lv_demo_widgets();
  27.         while(1)//无限循环
  28.         {               
  29.                 char temp[50];
  30.                 lv_task_handler();
  31.                
  32.                 if(uart2_rec_flag != 0)//需要接收uart2返回
  33.                 {
  34.                         printf("uart2_rec_flag:%d\r\n",uart2_rec_flag);
  35.                         Delay_nms(1000);
  36.                         
  37.                         weather_str[weather_cnt] = '\0';
  38.                         printf("%d\r\n",weather_cnt);
  39.                         printf("%s\r\n",(char *)&weather_str[0]);
  40.                         //welcome_windows_show(welcome_label1,(char *)&weather_str[0]);
  41.                         weather_data_analysis((char *)&weather_str[0]);
  42.                         weather_cnt = 0;        
  43.                         uart2_rec_flag = 0;
  44.                 }
  45.         }
  46. }
天气信息的解析是最重要的部分,主要解析五个元素:
  • 城市
  • 天气
  • 温度
  • 湿度
  • 风力
  • 数据的更新时间

具体解析过程详见代码:

  1. #include "lvgl.h"
  2. #include "string.h"
  3. #include "weather.h"
  4. #include "gui_app.h"

  5. t_weather_type weather_data;


  6. //城市代码转换为城市的拼音
  7. static void city_code_to_city(char *city_code, char *des)
  8. {
  9.         if((city_code[0] != 'C') || (city_code[1] != 'H'))
  10.         {
  11.                 return;
  12.         }
  13.         if((city_code[2] == '0') && (city_code[3] == '1'))
  14.         {
  15.                 memcpy(des,"Beijing",sizeof("Beijing"));
  16.         }
  17.         else if((city_code[2] == '0') && (city_code[3] == '2'))
  18.         {
  19.                 memcpy(des,(char *)"Shanghai",sizeof("Shanghai"));
  20.                 printf("code:%s,%d\n",city_code,sizeof("Shanghai"));
  21.         }
  22.         else if((city_code[2] == '0') && (city_code[3] == '3'))
  23.         {
  24.                 memcpy(des,"Tianjin",sizeof("Tianjin"));
  25.         }        
  26.         else if((city_code[2] == '0') && (city_code[3] == '4'))
  27.         {
  28.                 memcpy(des,"Chongqing",sizeof("Chongqing"));
  29.         }        
  30. }

  31. //天气代码转换为天气英文
  32. static void numtq_to_tq(char *num_code, char *des)
  33. {
  34.         uint16_t temp = 0;
  35.         uint16_t len;
  36.         
  37.         len = strlen(num_code);
  38.         
  39.         if(len == 2)
  40.         {
  41.                 temp = (num_code[0] - '0')* 10 + (num_code[1] - '0');//代码转为为数字
  42.         }
  43.         else if(len == 3)
  44.         {
  45.                 temp = (num_code[0] - '0') * 100 + (num_code[1] - '0') * 10 + (num_code[2] - '0');//代码转为为数字
  46.         }
  47.         
  48.         if(temp > 100)//超出范围,数据无效
  49.         {
  50.                 return;
  51.         }
  52.         
  53.         switch(temp)
  54.         {
  55.                 case 0://晴
  56.                         memcpy(des,"Sunny",sizeof("Sunny"));
  57.                 break;
  58.                
  59.                 case 1://多云
  60.                         memcpy(des,"Cloudy",sizeof("Cloudy"));
  61.                 break;               

  62.                 case 2://阴
  63.                         memcpy(des,"Overcast",sizeof("Overcast"));
  64.                 break;
  65.                
  66.                 case 3://阵雨
  67.                         memcpy(des,"1Shower",sizeof("1Shower"));
  68.                 break;

  69.                 case 4://雷阵雨
  70.                         memcpy(des,"Thundershower",sizeof("Thundershower"));
  71.                 break;
  72.                
  73.                 case 5://雷阵雨伴有冰雹
  74.                         memcpy(des,"Thundershower with hail",sizeof("Thundershower with hail"));
  75.                 break;               

  76.                 case 6://雨夹雪
  77.                         memcpy(des,"1Sleet",sizeof("1Sleet"));
  78.                 break;
  79.                
  80.                 case 7://小雨
  81.                         memcpy(des,"Light rain",sizeof("Light rain"));
  82.                 break;        

  83.                 case 8://中雨
  84.                         memcpy(des,"Moderate rain",sizeof("Moderate rain"));
  85.                 break;
  86.                
  87.                 case 9://大雨
  88.                         memcpy(des,"Heavy rain",sizeof("Heavy rain"));
  89.                 break;               

  90.                 case 10://暴雨
  91.                         memcpy(des,"Storm",sizeof("Storm"));
  92.                 break;
  93.                
  94.                 case 11://大暴雨
  95.                         memcpy(des,"Heavy storm",sizeof("Heavy storm"));
  96.                 break;

  97.                 case 12://特大暴雨
  98.                         memcpy(des,"Severe storm",sizeof("Severe storm"));
  99.                 break;
  100.                
  101.                 case 13://阵雪
  102.                         memcpy(des,"Snow flurry",sizeof("Snow flurry"));
  103.                 break;               

  104.                 case 14://小雪
  105.                         memcpy(des,"Light snow",sizeof("Light snow"));
  106.                 break;
  107.                
  108.                 case 15://中雪
  109.                         memcpy(des,"Moderate snow",sizeof("Moderate snow"));
  110.                 break;        

  111.                 case 16://大雪
  112.                         memcpy(des,"Heavy snow",sizeof("Heavy snow"));
  113.                 break;
  114.                
  115.                 case 17://暴雪
  116.                         memcpy(des,"Snowstorm",sizeof("Snowstorm"));
  117.                 break;               

  118.                 case 18://雾
  119.                         memcpy(des,"Fog",sizeof("Fog"));
  120.                 break;
  121.                
  122.                 case 19://冻雨
  123.                         memcpy(des,"Ice rain",sizeof("Ice rain"));
  124.                 break;

  125.                 case 20://沙尘暴
  126.                         memcpy(des,"Duststorm",sizeof("Duststorm"));
  127.                 break;
  128.                
  129.                 case 21://小到中雨
  130.                         memcpy(des,"Light to moderate rain",sizeof("Light to moderate rain"));
  131.                 break;               

  132.                 case 22://中到大雨
  133.                         memcpy(des,"Moderate to heavy rain",sizeof("Moderate to heavy rain"));
  134.                 break;
  135.                
  136.                 case 23://大到暴雨
  137.                         memcpy(des,"Heavy rain to storm",sizeof("Heavy rain to storm"));
  138.                 break;

  139.                 case 24://暴雨到大暴雨
  140.                         memcpy(des,"Storm to heavy storm",sizeof("Storm to heavy storm"));
  141.                 break;
  142.                
  143.                 case 25://暴雨到特大暴雨
  144.                         memcpy(des,"Heavy to severe storm",sizeof("Heavy to severe storm"));
  145.                 break;               

  146.                 case 26://小到中雪
  147.                         memcpy(des,"1Light to moderate snow",sizeof("1Light to moderate snow"));
  148.                 break;
  149.                
  150.                 case 27://中到大雪
  151.                         memcpy(des,"Moderate to heavy snow",sizeof("Moderate to heavy snow"));
  152.                 break;

  153.                 case 28://大到暴雪
  154.                         memcpy(des,"Heavy snow to snowstorm",sizeof("Heavy snow to snowstorm"));
  155.                 break;
  156.                
  157.                 case 29://浮尘
  158.                         memcpy(des,"Dust",sizeof("Dust"));
  159.                 break;               

  160.                 case 30://扬沙
  161.                         memcpy(des,"Sand",sizeof("Sand"));
  162.                 break;
  163.                
  164.                 case 31://强沙尘暴
  165.                         memcpy(des,"Sandstorm",sizeof("Sandstorm"));
  166.                 break;        

  167.                 case 32://浓雾
  168.                         memcpy(des,"Dense fog",sizeof("Dense fog"));
  169.                 break;
  170.                
  171.                 case 49://强浓雾
  172.                         memcpy(des,"Heavy dense fog",sizeof("Heavy dense fog"));
  173.                 break;               

  174.                 case 53://霾
  175.                         memcpy(des,"Haze",sizeof("Haze"));
  176.                 break;
  177.                
  178.                 case 54://中度霾
  179.                         memcpy(des,"Moderate haze",sizeof("Moderate haze"));
  180.                 break;

  181.                 case 55://重度霾
  182.                         memcpy(des,"Severe haze",sizeof("Severe haze"));
  183.                 break;
  184.                
  185.                 case 56://严重霾
  186.                         memcpy(des,"Hazardous haze",sizeof("Hazardous haze"));
  187.                 break;               

  188.                 case 57://大雾
  189.                         memcpy(des,"heavy fog",sizeof("heavy fog"));
  190.                 break;
  191.                
  192.                 case 58://特强浓雾
  193.                         memcpy(des,"Extra-heavy dense fog",sizeof("Extra-heavy dense fog"));
  194.                 break;

  195.                 case 99://无
  196.                         memcpy(des,"Unknown",sizeof("Unknown"));
  197.                 break;
  198.                
  199.                 case 100://刮风
  200.                         memcpy(des,"Windy",sizeof("Windy"));
  201.                 break;

  202.                 default:
  203.                
  204.                 break;
  205.         }
  206. }

  207. //风力代码转换为风力英文
  208. static void numfl_to_fl(char *num_code, char *des)
  209. {
  210.         uint16_t temp = 0;
  211.         
  212.         temp = num_code[0] - '0';
  213.         
  214.         switch(temp)
  215.         {
  216.                 case 0:
  217.                         memcpy(des,"breeze",sizeof("breeze"));
  218.                 break;
  219.                
  220.                 case 1:
  221.                         memcpy(des,"3~4",sizeof("3~4"));
  222.                 break;        

  223.                 case 2:
  224.                         memcpy(des,"4~5",sizeof("4~5"));
  225.                 break;
  226.                
  227.                 case 3:
  228.                         memcpy(des,"5~6",sizeof("5~6"));
  229.                 break;        
  230.                
  231.                 case 4:
  232.                         memcpy(des,"6~7",sizeof("6~7"));
  233.                 break;
  234.                
  235.                 case 5:
  236.                         memcpy(des,"7~8",sizeof("7~8"));
  237.                 break;        

  238.                 case 6:
  239.                         memcpy(des,"8~9",sizeof("8~9"));
  240.                 break;
  241.                
  242.                 case 7:
  243.                         memcpy(des,"9~10",sizeof("9~10"));
  244.                 break;        

  245.                 case 8:
  246.                         memcpy(des,"10~11",sizeof("10~11"));
  247.                 break;
  248.                
  249.                 case 9:
  250.                         memcpy(des,"11~12",sizeof("11~12"));
  251.                 break;        
  252.                
  253.                 default:
  254.                
  255.                 break;
  256.         }
  257.         
  258. }

  259. void weather_data_analysis(char* str)
  260. {
  261.         uint16_t index = 0;
  262.         char* temp;
  263.         char temp_str[50];
  264.         char temp_str2[50];
  265.         
  266.         //判断是否收到了正确的天气数据帧
  267.         if(strstr(str,"Sucess") == NULL)
  268.         {
  269.                 return;
  270.         }
  271.         
  272.         //解析城市id
  273.         temp = strstr(str,"cityId");
  274.         index = temp - str;
  275.         memcpy(&weather_data.cityid[0],temp + CITY_ID_OFFSET,CITY_ID_SIZE);
  276.         weather_data.cityid[CITY_ID_SIZE] = '\0';//添加字符串结束符
  277.         
  278.         city_code_to_city(&(weather_data.cityid[0]), temp_str2);//代码转换为城市拼音
  279.         printf("%s\r\n",&(weather_data.cityid[0]));
  280.         
  281.         sprintf(temp_str,"city : %s",temp_str2);
  282.         weather_windows_show(city_label,temp_str);
  283.         
  284.         //解析气温
  285.         temp = strstr(str,"qw");
  286.         index = temp - str;
  287.         memcpy(&weather_data.air_temperature[0],temp + QW_OFFSET,QW_SIZE);
  288.         weather_data.air_temperature[QW_SIZE] = 'C';
  289.         weather_data.air_temperature[QW_SIZE + 1] = '\0';//添加字符串结束符
  290.         
  291.         sprintf(temp_str,"temp : %s",&(weather_data.air_temperature[0]));
  292.         weather_windows_show(temp_label,temp_str);        

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

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

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

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

三、效果图片



视频演示




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| xinmeng_wit 发表于 2022-5-1 21:20 | 显示全部楼层
视频链接为什么没有显示
您需要登录后才可以回帖 登录 | 注册

本版积分规则

70

主题

276

帖子

2

粉丝
快速回复 返回顶部 返回列表