之前用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
|