找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4550|回复: 3
打印 上一主题 下一主题
收起左侧

战舰V3通过ESP8266获得网络天气

[复制链接]
跳转到指定楼层
楼主
ID:137406 发表于 2017-11-27 16:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
之前用8266和机智云成功通信了, 但是一直不知道8266是怎么设置联网,因为这个是下载的机智云的固件。后来就寻思着做了这个网络天气的。网上几乎没有人用STM32做天气的,基本上都是用arduino或者直接用esp8266+oled。

一、
硬件:战舰V3 + ESP8266 + 2.8寸屏
软件:1、esp8266的配置
         2、连接天气的服务器,get API数据
         3、cjson的移植与解析
         4、UTF8转GBK转码,这个网上很少例程
         5、图标的取模

   首先配置esp8266为透传模式


01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

while(atk_8266_send_cmd("AT","OK",20))//¼ì2éWIFIÄ£¿éêÇ·ñÔúÏß
        {
                atk_8266_quit_trans();//íË3öí¸′«
                atk_8266_send_cmd("AT+CIPMODE=0","OK",200);  //1رÕí¸′«Ä£ê½        
                Show_Str(40,55,200,16,"Î′¼ì2aμ½Ä£¿é!!!",16,0);
                delay_ms(800);
                LCD_Fill(40,55,200,55+16,WHITE);
                Show_Str(40,55,200,16,"3¢êÔᬽóÄ£¿é...",16,0);
        }
        while(atk_8266_send_cmd("ATE0","OK",20));//1رջØÏÔ
        atk_8266_send_cmd("AT+CWMODE=1","OK",50);                //éèÖÃWIFI STAÄ£ê½
        atk_8266_send_cmd("AT+RST","OK",20);                //DHCP·tÎñÆ÷1رÕ(½öAPÄ£ê½óDD§)
        delay_ms(1000);         //Ñóê±3Sμè′yÖØÆô3é1|
        delay_ms(1000);
        delay_ms(1000);
        delay_ms(1000);
        //éèÖÃᬽóμ½μÄWIFIíøÂçÃû3Æ/¼óÃü·½ê½/ÃüÂë,Õa¼¸¸ö2ÎêyDèòa¸ù¾YÄú×Ô¼oμÄ·óéÆ÷éèÖýøDDDT¸Ä!!
        atk_8266_send_cmd("AT+CIPMUX=0","OK",20);   //0£oμ¥ᬽó£¬1£o¶àᬽó
        sprintf((char*)p,"AT+CWJAP=\"%s\",\"%s\"",wifista_ssid,wifista_password);//éèÖÃÎTÏß2Îêy:ssid,ÃüÂë
        while(atk_8266_send_cmd(p,"WIFI GOT IP",300));                                        //ᬽóÄ¿±ê·óéÆ÷,2¢Çò»ñμÃIP





然后连接天气服务器,get API


01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

sprintf((char*)p,"AT+CIPSTART=\"TCP\",\"%s\",%s",WEATHER_SERVERIP,WEATHER_PORTNUM);    //ÅäÖÃÄ¿±êTCP·tÎñÆ÷
        res = atk_8266_send_cmd(p,"OK",200);//ᬽóμ½Ä¿±êTCP·tÎñÆ÷
        if(res==1)
        {
                myfree(SRAMIN,p);
                return 1;
        }
        delay_ms(300);
        atk_8266_send_cmd("AT+CIPMODE=1","OK",100);      //′«êäÄ£ê½Îa£oí¸′«        
        atk_8266_get_wanip(ipbuf);//»ñè¡WAN IP
        sprintf((char*)p,"IPμØÖ·:%s ¶Ë¿ú:%s",ipbuf,(u8*)WEATHER_PORTNUM);
//        Show_Str(30,65,200,12,p,12,0);                                //ÏÔê¾IPμØÖ·oí¶Ë¿ú        
        USART3_RX_STA=0;
        atk_8266_send_cmd("AT+CIPSEND","OK",100);         //¿aê¼í¸′«
        printf("start trans...\r\n");

        u3_printf("GET [color=rgb(0, 130, 0) !important][url=https://api.seniverse.com/]https://api.seniverse.com[/url]);







然后再解析这个API返回的数据,并予以显示。

二、
1.目前免费的API有很多,我比较喜欢“心知天气”( https://www.seniverse.com/ )和 “和风天气”(http://www.heweather.com/  )。
  大家可以到这两个网站去注册,选择你们喜欢的天气API。心知天气的免费API返回的数据表少,功能较少。而和风天气的免费API则返回的比较详细。
  我这里选择心知天气,然后大家可以去看看心知天气的文档,里面有详细的数据结构(cjson数据)。
2.移植和解析cjson。
  这个东西很简单,我也是第一次移植,不过看了一篇教程就会了。推荐大家看下这两篇文章就可以了。
  http://blog.csdn.net/xukai871105/article/details/32346797    这个讲cjson的格式讲的蛮好的
  http://blog.csdn.net/lintax/article/details/50993958     这个讲cjson的使用
  https://sourceforge.net/projects/cjson/          这个网站是下载cjson的

  移植cjson,注意两点,一个是cjson占用堆比较大,大约3K,这个坑我就遇到了,使用默认的堆大小不能运行,于是我把堆改成了4K。




  第二点就是 要为 cjson 配置malloc ,打开cjson.c,修改下面几处。修改成原子的mymalloc,由于原子的mymalloc有个选择SRAMIN的参数,所以我又封装了下,弄了个my_malloc。
  



3.连接天气服务器,然后get 天气的api。
   这里卡了好半天,一开始用网口调试助手连上了服务器,然后get那个API链接的时候,一直不成功,原来是要在这个链接后面加两个回车,这个得感谢坛友  svwydh


4.解析天气数据
  用cjson库来解析天气数据,这里有个问题就是获得的天气数据的格式都是  utf8 的,无法直接显示在屏上,需要转码成GBK的,而原子哥的汉字例程就是gbk的。
  utf8转gbk这个网上也比较少,问了很多网友,有人说用查表法,于是又去找,侥幸找到了一个类似的,然后修改了下,居然可以用。


5.图标的制作
  首先自己去选一套漂亮的天气图标,我刚才推荐的那两个网站里已经为大家准备了图标,可自行下载。
  然后用战舰光盘里那个Image2lcd的软件,选择输出灰度为单色,这样取模以后的数据最小。打开你的天气图标,然后点保存,就可以保存为一个数组的c文件,将这个
  数组添加到你的工程里去。


大体上的难点和知识点就是上面这些。

上几张效果图。一张彩色的,一张白色的,大家觉得哪个好看点。


接下来传个演示视频由于视频不能播放,先放个链接:http://v.youku.com/v_show/id_XMz ... qq-pf-to=pcqq.group


如果大家感兴趣,将会上传源码。
@svwydh 感谢


  1. #include "sys.h"
  2. #include "delay.h"
  3. #include "usart.h"
  4. #include "led.h"                           
  5. #include "lcd.h"  
  6. #include "key.h"     
  7. #include "malloc.h"
  8. #include "sdio_sdcard.h"  
  9. #include "w25qxx.h"   
  10. #include "ff.h"  
  11. #include "exfuns.h"   
  12. #include "text.h"       
  13. #include "touch.h"               
  14. #include "usart3.h"
  15. #include "wifista.h"
  16. #include "weather.h"
  17. #include "cJSON.h"
  18. #include "picture.h"
  19. #include "rtc.h"

  20. //static void create_complex(void);
  21. void show_weather(void);
  22. void show_time(void);

  23. int main(void)
  24. {         
  25.         u8 key,fontok=0;
  26.         u16 t=0;
  27.         u8 min;         
  28.         u8 hour;
  29.         u8 constate=0;        //连接状态
  30.         delay_init();                     //延时函数初始化          
  31.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
  32.         uart_init(115200);                 //串口初始化为115200
  33.        
  34.         LED_Init();                                          //初始化与LED连接的硬件接口
  35.         KEY_Init();                                        //初始化按键
  36.         LCD_Init();                                           //初始化LCD   
  37.         RTC_Init();
  38.         W25QXX_Init();                                //初始化W25Q128
  39.         tp_dev.init();                                //初始化触摸屏
  40.         usart3_init(115200);                //初始化串口3
  41.         my_mem_init(SRAMIN);                //初始化内部内存池
  42.         exfuns_init();                                //为fatfs相关变量申请内存  
  43.         f_mount(fs[0],"0:",1);                 //挂载SD卡
  44.         f_mount(fs[1],"1:",1);                 //挂载FLASH.
  45.         key=KEY_Scan(0);  
  46.         if(key==KEY0_PRES&&((tp_dev.touchtype&0X80)==0))//强制校准
  47.         {
  48.                 LCD_Clear(WHITE);                //清屏0
  49.                 TP_Adjust();                          //屏幕校准
  50.                 TP_Save_Adjdata();          
  51.                 LCD_Clear(WHITE);                //清屏
  52.         }
  53.         fontok=font_init();                        //检查字库是否OK
  54.         if(fontok||key==KEY1_PRES)        //需要更新字库                                 
  55.         {
  56.                 LCD_Clear(WHITE);                //清屏
  57.                 POINT_COLOR=WHITE;                //设置字体为红色                                
  58.                 LCD_ShowString(60,50,200,16,16,"ALIENTEK STM32");
  59.                 while(SD_Init())                //检测SD卡
  60.                 {
  61.                         LCD_ShowString(60,70,200,16,16,"SD Card Failed!");
  62.                         delay_ms(200);
  63.                         LCD_Fill(60,70,200+60,70+16,WHITE);
  64.                         delay_ms(200);                    
  65.                 }                                                                                                                     
  66.                 LCD_ShowString(60,70,200,16,16,"SD Card OK");
  67.                 LCD_ShowString(60,90,200,16,16,"Font Updating...");
  68.                 key=update_font(20,110,16,"0:");//从SD卡更新
  69.                 while(key)//更新失败               
  70.                 {                                           
  71.                         LCD_ShowString(60,110,200,16,16,"Font Update Failed!");
  72.                         delay_ms(200);
  73.                         LCD_Fill(20,110,200+20,110+16,WHITE);
  74.                         delay_ms(200);                       
  75.                 }                   
  76.                 LCD_ShowString(60,110,200,16,16,"Font Update Success!");
  77.                 delay_ms(1500);       
  78.                 LCD_Clear(WHITE);//清屏               
  79.         }
  80.        
  81. //        create_complex();
  82.         delay_ms(200);
  83.         LED0 = 0;
  84.         show_weather();
  85.         atk_8266_wifista_config();
  86.         printf("wifi init ok!");
  87.         POINT_COLOR = WHITE;
  88.         delay_ms(1000);
  89.         get_current_weather();
  90.         delay_ms(200);
  91.         get_3days_weather();
  92.         min = calendar.min;
  93.         hour = calendar.hour;
  94.         while(1)
  95.         {
  96.                 key = KEY_Scan(0);
  97.                 if(key==KEY0_PRES)
  98.                 {
  99.                         get_current_weather();                       
  100.                 }
  101.                 else if(key==KEY1_PRES)
  102.                 {
  103.                         get_3days_weather();
  104.                 }
  105.                 else if(key==KEY2_PRES)
  106.                 {
  107.                         get_beijing_time();
  108.                 }
  109.                 delay_ms(10);
  110.                 t++;
  111.                 if(t==1000)
  112.                 {
  113.                         constate=atk_8266_consta_check();//得到连接状态         
  114.                         t=0;
  115.                 }
  116.                 else if((t%100)==0)
  117.                 {
  118.                         LED1 = !LED1;
  119.                         show_time();
  120.                 }
  121.                
  122.                 if(min!=calendar.min)
  123.                 {
  124.                         get_current_weather();                               
  125.                         min = calendar.min;
  126.                 }
  127.                 if(hour!=calendar.hour)
  128.                 {
  129.                         get_3days_weather();
  130.                         hour = calendar.hour;
  131.                 }

  132.                 atk_8266_at_response(1);
  133.         }
  134. }

  135. //void create_complex(void) {  
  136. //        cJSON *root, *rows, *row;  
  137. //        char *out;  
  138. //        int i = 0;  
  139. //               
  140. //        char *title[3] = { "树莓派学习笔记-索引博文",  
  141. //        "树莓派学习笔记-GPIO功能学习",  
  142. //        "物联网学习笔记-索引博文"};  
  143. //        char *url[3] = { "http://blog.csdn.net/xukai871105/article/details/23115627",  
  144. //        "http://blog.csdn.net/xukai871105/article/details/12684617",  
  145. //        "http://blog.csdn.net/xukai871105/article/details/23366187"};  
  146. //               
  147. //        root = cJSON_CreateObject(); // 创建根
  148. //        cJSON_AddNumberToObject(root, "total", 3);  
  149. //               
  150. //        // 在object加入array  
  151. //        cJSON_AddItemToObject(root, "rows", rows = cJSON_CreateArray());  
  152. //               
  153. //        for(i = 0; i < 3; i++) {  
  154. //        // 在array加入object  
  155. //        cJSON_AddItemToArray(rows, row = cJSON_CreateObject());  
  156. //        cJSON_AddItemToObject(row, "title", cJSON_CreateString(title[i]));  
  157. //        cJSON_AddItemToObject(row, "url", cJSON_CreateString(url[i]));  
  158. //        }  
  159. //               
  160. //        // 打印并释放  
  161. //        out = cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); my_free(out);  
  162. //}  


  163. void show_weather(void)
  164. {
  165.         u8 res;
  166.         file = mymalloc(SRAMIN,sizeof(FIL));
  167.         res=f_open(file,(const TCHAR*)APP_ASCII_5427,FA_READ);//打开文件
  168.         if(res==FR_OK)
  169.         {
  170.                 asc2_5427 = mymalloc(SRAMIN,file->fsize);
  171.                 if(asc2_5427 != NULL)
  172.                 {
  173.                         res = f_read(file,asc2_5427,file->fsize,&br);
  174.                 }
  175.                 f_close(file);
  176.         }
  177.         LCD_Clear(BLACK);
  178.         POINT_COLOR = WHITE;
  179.         BACK_COLOR = BLACK;
  180.         Show_Str(0,0,lcddev.width,lcddev.height,"中国",16,0);
  181.         LCD_ShowString(160,0,lcddev.width,lcddev.height,16,"0000-00-00");
  182.         LCD_ShowString(255,0,lcddev.width,lcddev.height,16,"00:00:00");
  183. //        POINT_COLOR = RED;
  184.         LCD_Draw_Picture(30,5,130,105,(u8 *)gImage_sunny);
  185.         gui_show_num(140,22,2,WHITE,54,0,0x80);
  186. //        POINT_COLOR = WHITE;
  187.         Show_Str(200,25,lcddev.width,lcddev.height,"°",24,0);
  188. //        POINT_COLOR = GBLUE;
  189.         Show_Str(220,25,lcddev.width,lcddev.height,"晴天",16,0);
  190.         Show_Str(220,45,lcddev.width,lcddev.height,"北风",16,0);
  191.         Show_Str(220,65,lcddev.width,lcddev.height,"0级",16,0);
  192.         Show_Str(220,85,lcddev.width,lcddev.height,"风速  0Km/h",16,0);
  193. //        POINT_COLOR = WHITE;
  194.         LCD_DrawLine(0,105,lcddev.width,105);
  195.         LCD_DrawLine(105,130,105,220);
  196.         LCD_DrawLine(215,130,215,220);
  197.         LCD_Draw_Picture(0,140,100,240,(u8 *)gImage_sunny);
  198.         LCD_Draw_Picture(110,140,210,240,(u8 *)gImage_sunny);
  199.         LCD_Draw_Picture(220,140,320,240,(u8 *)gImage_sunny);
  200. //        POINT_COLOR = YELLOW;
  201.         Show_Str(30,117,lcddev.width,lcddev.height,"今天",12,0);

  202.         LCD_ShowString(30,130,lcddev.width,lcddev.height,12,"00/00");
  203. //        POINT_COLOR = GREEN;
  204.         Show_Str(140,117,lcddev.width,lcddev.height,"明天",12,0);

  205.         LCD_ShowString(140,130,lcddev.width,lcddev.height,12,"00/00");
  206. //        POINT_COLOR = MAGENTA;
  207.         Show_Str(250,117,lcddev.width,lcddev.height,"后天",12,0);       

  208.         LCD_ShowString(250,130,lcddev.width,lcddev.height,12,"00/00");
  209.        
  210.         myfree(SRAMIN,file);
  211.         myfree(SRAMIN,asc2_5427);
  212. }


  213. void show_time(void)
  214. {
  215.         LCD_ShowNum(160,0,calendar.w_year,4,16);
  216.         LCD_ShowxNum(200,0,calendar.w_month,2,16,0x80);
  217.         LCD_ShowxNum(224,0,calendar.w_date,2,16,0x80);       
  218.         LCD_ShowxNum(255,0,calendar.hour,2,16,0x80);
  219.         LCD_ShowxNum(279,0,calendar.min,2,16,0x80);       
  220.         LCD_ShowxNum(303,0,calendar.sec,2,16,0x80);       
  221. }












复制代码


以下是源码,喜欢的可自行下载。 ESP8266获取网络天气适配战舰V3.zip

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:339500 发表于 2018-11-12 19:04 | 只看该作者
我想用51单片机实现显示天气功能,不知道怎么实现第三步,就这个天气服务器怎么连接,假设我用python语言自己写了一个服务器,我已经把天气信息写在服务器里该怎么连接怎么把数据弄给51单片机是个问题
3.连接天气服务器,然后get 天气的api。
   这里卡了好半天,一开始用网口调试助手连上了服务器
回复

使用道具 举报

板凳
ID:192650 发表于 2019-8-22 08:51 | 只看该作者
qq23230233 发表于 2018-11-12 19:04
我想用51单片机实现显示天气功能,不知道怎么实现第三步,就这个天气服务器怎么连接,假设我用python语言自 ...

使用WiFi模块连接你服务器获取数据
回复

使用道具 举报

地板
ID:184978 发表于 2022-4-16 13:04 | 只看该作者
为什么下载不了呢?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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