之前用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 感谢
- #include "sys.h"
- #include "delay.h"
- #include "usart.h"
- #include "led.h"
- #include "lcd.h"
- #include "key.h"
- #include "malloc.h"
- #include "sdio_sdcard.h"
- #include "w25qxx.h"
- #include "ff.h"
- #include "exfuns.h"
- #include "text.h"
- #include "touch.h"
- #include "usart3.h"
- #include "wifista.h"
- #include "weather.h"
- #include "cJSON.h"
- #include "picture.h"
- #include "rtc.h"
- //static void create_complex(void);
- void show_weather(void);
- void show_time(void);
- int main(void)
- {
- u8 key,fontok=0;
- u16 t=0;
- u8 min;
- u8 hour;
- u8 constate=0; //连接状态
- delay_init(); //延时函数初始化
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
- uart_init(115200); //串口初始化为115200
-
- LED_Init(); //初始化与LED连接的硬件接口
- KEY_Init(); //初始化按键
- LCD_Init(); //初始化LCD
- RTC_Init();
- W25QXX_Init(); //初始化W25Q128
- tp_dev.init(); //初始化触摸屏
- usart3_init(115200); //初始化串口3
- my_mem_init(SRAMIN); //初始化内部内存池
- exfuns_init(); //为fatfs相关变量申请内存
- f_mount(fs[0],"0:",1); //挂载SD卡
- f_mount(fs[1],"1:",1); //挂载FLASH.
- key=KEY_Scan(0);
- if(key==KEY0_PRES&&((tp_dev.touchtype&0X80)==0))//强制校准
- {
- LCD_Clear(WHITE); //清屏0
- TP_Adjust(); //屏幕校准
- TP_Save_Adjdata();
- LCD_Clear(WHITE); //清屏
- }
- fontok=font_init(); //检查字库是否OK
- if(fontok||key==KEY1_PRES) //需要更新字库
- {
- LCD_Clear(WHITE); //清屏
- POINT_COLOR=WHITE; //设置字体为红色
- LCD_ShowString(60,50,200,16,16,"ALIENTEK STM32");
- while(SD_Init()) //检测SD卡
- {
- LCD_ShowString(60,70,200,16,16,"SD Card Failed!");
- delay_ms(200);
- LCD_Fill(60,70,200+60,70+16,WHITE);
- delay_ms(200);
- }
- LCD_ShowString(60,70,200,16,16,"SD Card OK");
- LCD_ShowString(60,90,200,16,16,"Font Updating...");
- key=update_font(20,110,16,"0:");//从SD卡更新
- while(key)//更新失败
- {
- LCD_ShowString(60,110,200,16,16,"Font Update Failed!");
- delay_ms(200);
- LCD_Fill(20,110,200+20,110+16,WHITE);
- delay_ms(200);
- }
- LCD_ShowString(60,110,200,16,16,"Font Update Success!");
- delay_ms(1500);
- LCD_Clear(WHITE);//清屏
- }
-
- // create_complex();
- delay_ms(200);
- LED0 = 0;
- show_weather();
- atk_8266_wifista_config();
- printf("wifi init ok!");
- POINT_COLOR = WHITE;
- delay_ms(1000);
- get_current_weather();
- delay_ms(200);
- get_3days_weather();
- min = calendar.min;
- hour = calendar.hour;
- while(1)
- {
- key = KEY_Scan(0);
- if(key==KEY0_PRES)
- {
- get_current_weather();
- }
- else if(key==KEY1_PRES)
- {
- get_3days_weather();
- }
- else if(key==KEY2_PRES)
- {
- get_beijing_time();
- }
- delay_ms(10);
- t++;
- if(t==1000)
- {
- constate=atk_8266_consta_check();//得到连接状态
- t=0;
- }
- else if((t%100)==0)
- {
- LED1 = !LED1;
- show_time();
- }
-
- if(min!=calendar.min)
- {
- get_current_weather();
- min = calendar.min;
- }
- if(hour!=calendar.hour)
- {
- get_3days_weather();
- hour = calendar.hour;
- }
- atk_8266_at_response(1);
- }
- }
- //void create_complex(void) {
- // cJSON *root, *rows, *row;
- // char *out;
- // int i = 0;
- //
- // char *title[3] = { "树莓派学习笔记-索引博文",
- // "树莓派学习笔记-GPIO功能学习",
- // "物联网学习笔记-索引博文"};
- // char *url[3] = { "http://blog.csdn.net/xukai871105/article/details/23115627",
- // "http://blog.csdn.net/xukai871105/article/details/12684617",
- // "http://blog.csdn.net/xukai871105/article/details/23366187"};
- //
- // root = cJSON_CreateObject(); // 创建根
- // cJSON_AddNumberToObject(root, "total", 3);
- //
- // // 在object加入array
- // cJSON_AddItemToObject(root, "rows", rows = cJSON_CreateArray());
- //
- // for(i = 0; i < 3; i++) {
- // // 在array加入object
- // cJSON_AddItemToArray(rows, row = cJSON_CreateObject());
- // cJSON_AddItemToObject(row, "title", cJSON_CreateString(title[i]));
- // cJSON_AddItemToObject(row, "url", cJSON_CreateString(url[i]));
- // }
- //
- // // 打印并释放
- // out = cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); my_free(out);
- //}
- void show_weather(void)
- {
- u8 res;
- file = mymalloc(SRAMIN,sizeof(FIL));
- res=f_open(file,(const TCHAR*)APP_ASCII_5427,FA_READ);//打开文件
- if(res==FR_OK)
- {
- asc2_5427 = mymalloc(SRAMIN,file->fsize);
- if(asc2_5427 != NULL)
- {
- res = f_read(file,asc2_5427,file->fsize,&br);
- }
- f_close(file);
- }
- LCD_Clear(BLACK);
- POINT_COLOR = WHITE;
- BACK_COLOR = BLACK;
- Show_Str(0,0,lcddev.width,lcddev.height,"中国",16,0);
- LCD_ShowString(160,0,lcddev.width,lcddev.height,16,"0000-00-00");
- LCD_ShowString(255,0,lcddev.width,lcddev.height,16,"00:00:00");
- // POINT_COLOR = RED;
- LCD_Draw_Picture(30,5,130,105,(u8 *)gImage_sunny);
- gui_show_num(140,22,2,WHITE,54,0,0x80);
- // POINT_COLOR = WHITE;
- Show_Str(200,25,lcddev.width,lcddev.height,"°",24,0);
- // POINT_COLOR = GBLUE;
- Show_Str(220,25,lcddev.width,lcddev.height,"晴天",16,0);
- Show_Str(220,45,lcddev.width,lcddev.height,"北风",16,0);
- Show_Str(220,65,lcddev.width,lcddev.height,"0级",16,0);
- Show_Str(220,85,lcddev.width,lcddev.height,"风速 0Km/h",16,0);
- // POINT_COLOR = WHITE;
- LCD_DrawLine(0,105,lcddev.width,105);
- LCD_DrawLine(105,130,105,220);
- LCD_DrawLine(215,130,215,220);
- LCD_Draw_Picture(0,140,100,240,(u8 *)gImage_sunny);
- LCD_Draw_Picture(110,140,210,240,(u8 *)gImage_sunny);
- LCD_Draw_Picture(220,140,320,240,(u8 *)gImage_sunny);
- // POINT_COLOR = YELLOW;
- Show_Str(30,117,lcddev.width,lcddev.height,"今天",12,0);
- LCD_ShowString(30,130,lcddev.width,lcddev.height,12,"00/00");
- // POINT_COLOR = GREEN;
- Show_Str(140,117,lcddev.width,lcddev.height,"明天",12,0);
- LCD_ShowString(140,130,lcddev.width,lcddev.height,12,"00/00");
- // POINT_COLOR = MAGENTA;
- Show_Str(250,117,lcddev.width,lcddev.height,"后天",12,0);
- LCD_ShowString(250,130,lcddev.width,lcddev.height,12,"00/00");
-
- myfree(SRAMIN,file);
- myfree(SRAMIN,asc2_5427);
- }
- void show_time(void)
- {
- LCD_ShowNum(160,0,calendar.w_year,4,16);
- LCD_ShowxNum(200,0,calendar.w_month,2,16,0x80);
- LCD_ShowxNum(224,0,calendar.w_date,2,16,0x80);
- LCD_ShowxNum(255,0,calendar.hour,2,16,0x80);
- LCD_ShowxNum(279,0,calendar.min,2,16,0x80);
- LCD_ShowxNum(303,0,calendar.sec,2,16,0x80);
- }
复制代码
以下是源码,喜欢的可自行下载。 ESP8266获取网络天气适配战舰V3.zip
|