目錄
第一部分、前言
1、獲取心知天氣API接口
2、硬件準(zhǔn)備
第二部分、電腦串口助手調(diào)試WIFI模塊獲取天氣
1、ESP8266獲取天氣的流程
2、具體步驟
第三部分、STM32驅(qū)動(dòng)ESP8266模塊獲取天氣數(shù)據(jù)
1、天氣數(shù)據(jù)的解析
1.1、什么函數(shù)來(lái)解析天氣數(shù)據(jù)?
2.1、解析后的數(shù)據(jù)如何使用?
?2、相關(guān)代碼
2.1、main.c文件
2.2、esp8266.c文件
第四部分、總結(jié)
1、效果展示
2、完整的工程
3、補(bǔ)充
第一部分、前言
? ? ? ? 這篇博客拖了很久很久,本來(lái)是打算和前面一篇一起發(fā)出來(lái)的,但是那段時(shí)間因?yàn)橐恍┦虑榈R了,這篇博客寫了一半,剩下的一直都沒有寫,其次就是人也有點(diǎn)懶,也不太想動(dòng)????。
? ? ? ? 這幾天考試周來(lái)了,復(fù)習(xí)又不想復(fù)習(xí),不如把這篇內(nèi)容更新完整,這篇更新完之后,STM32專欄應(yīng)該不會(huì)再更新了。
? ? ? ? 然后,后面我打算出一期C語(yǔ)言的學(xué)習(xí)筆記專欄,再后面就是FPGA的學(xué)習(xí)筆記專欄。想是這么想的,不知道能不能做好,哈哈??。
1、獲取心知天氣API接口
? ? ? ? 這里還是希望大家先去看我的第一篇博客:【STM32訓(xùn)練—WiFi模塊】第一篇、STM32驅(qū)動(dòng)ESP8266WiFi模塊獲取網(wǎng)絡(luò)時(shí)間通過(guò)這篇博客你會(huì)明白WIFI模塊獲取網(wǎng)絡(luò)流程是什么樣子的,搞懂了這個(gè),你會(huì)發(fā)現(xiàn)獲取天氣和獲取時(shí)間的步驟完全一樣,代碼也沒有什么大的變化。
? ? ? ? 接著再來(lái)說(shuō)一下心知天氣,上一篇文章提到時(shí)間的接口是由蘇寧后臺(tái)提供的“quan.suning.com/getSysTime.do”,那么這里想獲取天氣,那么也需要一個(gè)API的接口,這里的API接口由心知天氣給我們提供。
????????因此需要注冊(cè)一個(gè)心知天氣,獲取自己的密鑰。關(guān)于注冊(cè)的過(guò)程可以參考心知天氣提供的文檔:注冊(cè)與登陸 | 心知天氣文檔 (seniverse.com)
????????注冊(cè)完成后,如何獲取屬于自己的API接口呢,參考文檔如下:查看/修改你的API密鑰 (yuque.com)
????????這是我的API接口,點(diǎn)進(jìn)去之后就會(huì)看到目前杭州的天氣數(shù)據(jù):https://api.seniverse.com/v3/weather/now.json?key=SwLQ3i0Q5TNa6NSKT&location=hangzhou&language=zh-Hans&unit=c
? ? ? ? 點(diǎn)擊上面的鏈接,就會(huì)獲取到天氣數(shù)據(jù),接下來(lái)的步驟就和前面獲取時(shí)間一樣,主要區(qū)別就是將時(shí)間的API接口換成剛剛注冊(cè)得到的心知天氣的API接口即可,是不是發(fā)現(xiàn)原來(lái)也就這么回事。
2、硬件準(zhǔn)備
?????????STM32選用核心板F103C8T6,然后再加一個(gè)ESP8266 WiFi模塊(任何型號(hào)應(yīng)該都可以,我這次用的ESP-01s),最后需要一個(gè)USB-TTL模塊用來(lái)打印串口數(shù)據(jù)。
? ? ? ? 需要注意的是:我的這個(gè)ESP-01S,有一個(gè)EN使能端,必須要給高電平才能用,上一篇博客用的那個(gè)WIFI模塊沒有EN使能端。所以希望大家注意自己的模塊。
第二部分、電腦串口助手調(diào)試WIFI模塊獲取天氣
1、ESP8266獲取天氣的流程
? ? ? ? 流程和獲取時(shí)間的流程大致一樣,只不過(guò)這里獲取的為天氣數(shù)據(jù)。
2、具體步驟
?第一步、AT指令集
0:AT
1:AT+RST
2:AT+CWMODE=1
3:AT+CIPMUX=0
4:AT+CWJAP="你的WiFi名稱","你的WiFi密碼"
5:AT+CIPMODE=1
6:AT+CIPSTART="TCP","api.seniverse.com",80
7:AT+CIPSEND
8:GET https://api.seniverse.com/v3/weather/now.json?key=SwLQ3i0Q5TNa6NSKT&location=hangzhou&language=en&unit=c
9:+++
? ? ? ? 注意:所有串口步驟同前一篇文章,這里直接有區(qū)別的步驟為第八步,因此這里直接跳轉(zhuǎn)到第八步
?第八步、連接目標(biāo)的服務(wù)器,TCP是傳輸協(xié)議,api.seniverse.com是心知天氣服務(wù)器的IP地址,80是服務(wù)器端口。
?第十步、第九步和前文一樣,接著再發(fā)送獲取數(shù)據(jù)的請(qǐng)求,得到天氣數(shù)據(jù)
?第十一步、關(guān)于退出透?jìng)鞯姆绞揭埠颓懊娌┛屯耆粯?,這里就不再展示,所以一定要看第一篇文章,那個(gè)文章介紹的太詳細(xì)了。
第三部分、STM32驅(qū)動(dòng)ESP8266模塊獲取天氣數(shù)據(jù)
1、天氣數(shù)據(jù)的解析
? ? ? ? 這里天氣的解析我調(diào)用了cJSON的庫(kù),你不用管這個(gè)庫(kù)怎么寫的,原理是啥,知道它是怎么用的就可以了,例如調(diào)用什么函數(shù)來(lái)解析天氣數(shù)據(jù)?解析后的數(shù)據(jù)如何使用?弄明白這兩個(gè)問題,就夠了。
? ? ? ? 1.1、什么函數(shù)來(lái)解析天氣數(shù)據(jù)?
????????時(shí)間太久了,我都不知道我哪里弄來(lái)的這個(gè)函數(shù),反正挺好用的,侵權(quán)聯(lián)系我刪除!
? ? ? ? 這個(gè)函數(shù)我放在我工程的"cJSON.c"文件最下面。
/*********************************************************************************
* Function Name : cJSON_WeatherParse,解析天氣數(shù)據(jù)
* Parameter : JSON:天氣數(shù)據(jù)包 results:保存解析后得到的有用的數(shù)據(jù)
* Return Value : 0:成功 其他:錯(cuò)誤
* Function Explain :
* Create Date : 2017.12.6 by lzn
**********************************************************************************/
int cJSON_WeatherParse(char *JSON, Results *results)
{
cJSON *json,*arrayItem,*object,*subobject,*item;
json = cJSON_Parse(JSON); //解析JSON數(shù)據(jù)包
if(json == NULL) //檢測(cè)JSON數(shù)據(jù)包是否存在語(yǔ)法上的錯(cuò)誤,返回NULL表示數(shù)據(jù)包無(wú)效
{
printf("Error before: [%s] \r\n",cJSON_GetErrorPtr()); //打印數(shù)據(jù)包語(yǔ)法錯(cuò)誤的位置
return 1;
}
else
{
if((arrayItem = cJSON_GetObjectItem(json,"results")) != NULL); //匹配字符串"results",獲取數(shù)組內(nèi)容
{
int size = cJSON_GetArraySize(arrayItem); //獲取數(shù)組中對(duì)象個(gè)數(shù)
printf("cJSON_GetArraySize: size=%d \r\n",size);
if((object = cJSON_GetArrayItem(arrayItem,0)) != NULL)//獲取父對(duì)象內(nèi)容
{
/* 匹配子對(duì)象1 */
if((subobject = cJSON_GetObjectItem(object,"location")) != NULL)
{
printf("---------------------------------subobject1-------------------------------\r\n");
if((item = cJSON_GetObjectItem(subobject,"id")) != NULL) //匹配子對(duì)象1成員"id"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.id,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"name")) != NULL) //匹配子對(duì)象1成員"name"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.name,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"country")) != NULL)//匹配子對(duì)象1成員"country"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.country,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"path")) != NULL) //匹配子對(duì)象1成員"path"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.path,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"timezone")) != NULL)//匹配子對(duì)象1成員"timezone"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.timezone,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"timezone_offset")) != NULL)//匹配子對(duì)象1成員"timezone_offset"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.timezone_offset,item->valuestring,strlen(item->valuestring));
}
}
/* 匹配子對(duì)象2 */
if((subobject = cJSON_GetObjectItem(object,"now")) != NULL)
{
printf("---------------------------------subobject2-------------------------------\r\n");
if((item = cJSON_GetObjectItem(subobject,"text")) != NULL)//匹配子對(duì)象2成員"text"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].now.text,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"code")) != NULL)//匹配子對(duì)象2成員"code"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].now.code,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"temperature")) != NULL) //匹配子對(duì)象2成員"temperature"
{
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].now.temperature,item->valuestring,strlen(item->valuestring));
}
}
/* 匹配子對(duì)象3 */
if((subobject = cJSON_GetObjectItem(object,"last_update")) != NULL)
{
printf("---------------------------------subobject3-------------------------------\r\n");
printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",subobject->type,subobject->string,subobject->valuestring);
memcpy(results[0].last_update,item->valuestring,strlen(subobject->valuestring));
}
}
}
}
cJSON_Delete(json); //釋放cJSON_Parse()分配出來(lái)的內(nèi)存空間
return 0;
}
????????2.1、解析后的數(shù)據(jù)如何使用?
? ? ? ? 調(diào)用上面那個(gè)函數(shù)后,解析的數(shù)據(jù)存放在一個(gè)雙層結(jié)構(gòu)體當(dāng)中,因此只需訪問結(jié)構(gòu)體的成員就可以,每個(gè)成員的名稱與心知天氣返回的名稱相匹配。
????????具體的信息參考心知天氣的文檔:極速實(shí)況 (yuque.com)
?2、相關(guān)代碼
? ? ? ? 2.1、main.c文件
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
#include "esp8266.h"
#include "cJSON.h" //解析天氣
//天氣數(shù)據(jù)
extern unsigned char Weather_buff[300];
//天氣解析
Results Weather_results[] = {{0}};
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中斷控制器分組設(shè)置
Usart1_Init(115200);
Usart2_Init(115200);
LED_Init();
delay_init();//初始化很重要//用不了的函數(shù)一般都是沒有初始化
ESP8266_Init();
Get_current_weather();//獲取天氣
while(1)
{
LED0 = 0;
delay_ms(500);
delay_ms(500);
delay_ms(500);
delay_ms(500);
LED0 = 1;
delay_ms(500);
delay_ms(500);
delay_ms(500);
delay_ms(500);
cJSON_WeatherParse((char *)Weather_buff, Weather_results);
printf("%s",Weather_buff);
//打印結(jié)構(gòu)體內(nèi)內(nèi)容
printf("\r\n 打印結(jié)構(gòu)體內(nèi)內(nèi)容如下: \r\n");
printf("%s \r\n",Weather_results[0].now.text);
printf("%s \r\n",Weather_results[0].now.temperature);
printf("%s \r\n",Weather_results[0].location.path);
printf("%s \r\n",Weather_results[0].location.country);
}
}
? ? ? ? 2.2、esp8266.c文件
#include "stm32f10x.h"
#include "sys.h"
#include "string.h"
#include "stdlib.h"
#include "esp8266.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
//WIFI和密碼·
#define ESP8266_WIFI_INFO "AT+CWJAP=\"iPhone111\",\"123456789\"\r\n"
//心知天氣的API
#define Weather_TCP "AT+CIPSTART=\"TCP\",\"api.seniverse.com\",80\r\n"
//心知天氣GET報(bào)文
/*這里城市 恩施 語(yǔ)言為 英文*/
#define Weather_GET "GET https://api.seniverse.com/v3/weather/now.json?key=SwLQ3i0Q5TNa6NSKT&location=enshi&language=en&unit=c\r\n"
//ESP8266數(shù)據(jù)存放
unsigned char esp8266_buf[300] = {0};
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;
//存放天氣數(shù)據(jù)
unsigned char Weather_buff[300]; //位數(shù)是隨機(jī)確定的
/**************************************************************************/
//函數(shù)作用:ESP8266_Init初始化函數(shù)
//函數(shù)名稱:ESP8266_Init(void);
//內(nèi)部參數(shù):
//修改日期:2022年4月18日 下午16:18
//作者: 大屁桃
/**************************************************************************/
void ESP8266_Init(void)
{
ESP8266_Clear();
/*讓W(xué)IFI推出透?jìng)髂J?/
while(ESP8266_SendCmd("+++", ""))
delay_ms(500);
UsartPrintf(USART_DEBUG, "1.AT\r\n");
while(ESP8266_SendCmd("AT\r\n", "OK"))
delay_ms(500);
//
//加一步ESP8266復(fù)位操作
UsartPrintf(USART_DEBUG, "2.RST\r\n");
ESP8266_SendCmd("AT+RST\r\n", "");
delay_ms(500);
ESP8266_SendCmd("AT+CIPCLOSE\r\n", "");
delay_ms(500);
/
UsartPrintf(USART_DEBUG, "3.CWMODE\r\n");
while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))
delay_ms(500);
UsartPrintf(USART_DEBUG, "4.AT+CIPMUX\r\n");
while(ESP8266_SendCmd("AT+CIPMUX=0\r\n", "OK"))
delay_ms(500);
UsartPrintf(USART_DEBUG, "5.CWJAP\r\n");
while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "WIFI GOT IP"))
delay_ms(500);
delay_ms(500);
delay_ms(500);
UsartPrintf(USART_DEBUG, "ESP8266_Init OK\r\n");
}
/*獲取網(wǎng)絡(luò)天氣數(shù)據(jù)*/
/**************************************************************************/
//函數(shù)作用:獲取心知天氣函數(shù)
//函數(shù)名稱:Get_current_weather(void);
//內(nèi)部參數(shù):
//修改日期:2022年4月18日 下午16:18
//作者: 大屁桃
/**************************************************************************/
void Get_current_weather(void)
{
ESP8266_Clear();
UsartPrintf(USART_DEBUG, "6.Weather_TCP OK\r\n");
while(ESP8266_SendCmd(Weather_TCP, "CONNECT"))
delay_ms(500);
delay_ms(500);
UsartPrintf(USART_DEBUG, "7.AT+CIPMODE=1 OK\r\n");
while(ESP8266_SendCmd("AT+CIPMODE=1\r\n", "OK"))
delay_ms(500);
delay_ms(500);
delay_ms(500);
/*sizeof(Weather_GET),必須用sizeof函數(shù),用strlen沒有用*/
ESP8266_SendData((u8 *)Weather_GET, sizeof(Weather_GET)); //發(fā)送AT+CIPSEND 以及 Weather_GET
ESP8266_GetIPD_GET(200,Weather_buff);
ESP8266_Clear();//清除緩存數(shù)據(jù)
delay_ms(500);
delay_ms(500);
while(ESP8266_SendCmd("+++", "")) /*退出透?jìng)髂J?/
delay_ms(500);
UsartPrintf(USART_DEBUG, "+++ OK\r\n");
while(ESP8266_SendCmd("AT\r\n", "OK")) //驗(yàn)證是否退出透?jìng)髂J? delay_ms(500);
UsartPrintf(USART_DEBUG, "1.AT\r\n");
}
/**************************************************************************/
//函數(shù)作用:串口二中斷函數(shù)
//函數(shù)名稱:USART2_IRQHandler();
//內(nèi)部參數(shù):
//修改日期:2022年4月18日 下午4:18
//作者: 大屁桃
/**************************************************************************/
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中斷
{
if(esp8266_cnt >= sizeof(esp8266_buf)) esp8266_cnt = 0; //防止串口被刷爆
esp8266_buf[esp8266_cnt++] = USART2->DR;
// USART_SendData(USART1,USART2->DR); //讓接收到的數(shù)據(jù)打印在串口一上
USART_ClearFlag(USART2, USART_FLAG_RXNE);
}
}
//==========================================================
// 函數(shù)名稱: ESP8266_Clear
//
// 函數(shù)功能: 清空緩存
//
// 入口參數(shù): 無(wú)
//
// 返回參數(shù): 無(wú)
//
// 說(shuō)明:
//==========================================================
void ESP8266_Clear(void)
{
memset(esp8266_buf, 0, sizeof(esp8266_buf));
esp8266_cnt = 0;
}
//==========================================================
// 函數(shù)名稱: ESP8266_WaitRecive
//
// 函數(shù)功能: 等待接收完成
//
// 入口參數(shù): 無(wú)
//
// 返回參數(shù): REV_OK-接收完成 REV_WAIT-接收超時(shí)未完成
//
// 說(shuō)明: 循環(huán)調(diào)用檢測(cè)是否接收完成
//==========================================================
_Bool ESP8266_WaitRecive(void)
{
if(esp8266_cnt == 0) //如果接收計(jì)數(shù)為0 則說(shuō)明沒有處于接收數(shù)據(jù)中,所以直接跳出,結(jié)束函數(shù)
return REV_WAIT;
if(esp8266_cnt == esp8266_cntPre) //如果上一次的值和這次相同,則說(shuō)明接收完畢
{
esp8266_cnt = 0; //清0接收計(jì)數(shù)
return REV_OK; //返回接收完成標(biāo)志
}
esp8266_cntPre = esp8266_cnt; //置為相同
return REV_WAIT; //返回接收未完成標(biāo)志
}
//==========================================================
// 函數(shù)名稱: ESP8266_GetIPD
//
// 函數(shù)功能: copy天氣數(shù)據(jù)到Weather_buff數(shù)組里面
//
// 返回參數(shù): 平臺(tái)返回的原始數(shù)據(jù)
//
// 說(shuō)明: copy天氣數(shù)據(jù)到Weather_buff
//==========================================================
unsigned char *ESP8266_GetIPD_GET(unsigned short timeOut,u8 *buff)//這里我用了一個(gè)全局變量將esp8266buf儲(chǔ)存到這個(gè)全局變量里面
{
do
{
delay_ms(5);
} while(timeOut--);
strcpy((char*)buff,(char*)esp8266_buf);
return buff;
}
/*還未用到*/
//==========================================================
// 函數(shù)名稱: ESP8266_GetIPD
//
// 函數(shù)功能: 獲取平臺(tái)返回的數(shù)據(jù)
//
// 入口參數(shù): 等待的時(shí)間(乘以10ms)
//
// 返回參數(shù): 平臺(tái)返回的原始數(shù)據(jù)
//
// 說(shuō)明: 不同網(wǎng)絡(luò)設(shè)備返回的格式不同,需要去調(diào)試
// 如ESP8266的返回格式為 "+IPD,x:yyy" x代表數(shù)據(jù)長(zhǎng)度,yyy是數(shù)據(jù)內(nèi)容
//==========================================================
unsigned char *ESP8266_GetIPD(unsigned short timeOut)
{
char *ptrIPD = NULL;
do
{
if(ESP8266_WaitRecive() == REV_OK) //如果接收完成
{
ptrIPD = strstr((char *)esp8266_buf, "IPD,"); //搜索“IPD”頭
if(ptrIPD == NULL) //如果沒找到,可能是IPD頭的延遲,還是需要等待一會(huì),但不會(huì)超過(guò)設(shè)定的時(shí)間
{
//UsartPrintf(USART_DEBUG, "\"IPD\" not found\r\n");
}
else
{
ptrIPD = strchr(ptrIPD, ':'); //找到':'
if(ptrIPD != NULL)
{
ptrIPD++;
return (unsigned char *)(ptrIPD);
}
else
return NULL;
}
}
delay_ms(5); //延時(shí)等待
} while(timeOut--);
return NULL; //超時(shí)還未找到,返回空指針
}
//==========================================================
// 函數(shù)名稱: ESP8266_SendCmd
//
// 函數(shù)功能: 發(fā)送命令
//
// 入口參數(shù): cmd:命令
// res:需要檢查的返回指令
//
// 返回參數(shù): 0-成功 1-失敗
//
// 說(shuō)明:
//==========================================================
_Bool ESP8266_SendCmd(char *cmd, char *res)
{
unsigned char timeOut = 250;
Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));
while(timeOut--)
{
if(ESP8266_WaitRecive() == REV_OK) //如果收到數(shù)據(jù)
{
if(strstr((const char *)esp8266_buf, res) != NULL) //如果檢索到關(guān)鍵詞
{
ESP8266_Clear(); //清空緩存
return 0;
}
}
delay_ms(10);
}
return 1;
}
//==========================================================
// 函數(shù)名稱: ESP8266_SendData
//
// 函數(shù)功能: 發(fā)送數(shù)據(jù)
//
// 入口參數(shù): data:數(shù)據(jù)
// len:長(zhǎng)度
//
// 返回參數(shù): 無(wú)
//
// 說(shuō)明:
//==========================================================
void ESP8266_SendData(unsigned char *data, unsigned short len)
{
char cmdBuf[32];
ESP8266_Clear(); //清空接收緩存
sprintf(cmdBuf, "AT+CIPSEND\r\n"); //發(fā)送命令
if(!ESP8266_SendCmd(cmdBuf, ">")) //收到‘>’時(shí)可以發(fā)送數(shù)據(jù)
{
UsartPrintf(USART_DEBUG, "8.AT+CIPSEND\r\n");
/*發(fā)送請(qǐng)求數(shù)據(jù)*/
Usart_SendString(USART2, data, len); //發(fā)送設(shè)備連接請(qǐng)求數(shù)據(jù)
}
}
第四部分、總結(jié)
1、效果展示
? ? ? ? 這是連接單片機(jī)后,單片機(jī)通過(guò)串口返回的數(shù)據(jù),這里串口只展示了當(dāng)前天氣、當(dāng)前溫度,所在地區(qū)和所在國(guó)家的數(shù)據(jù),若想增加在主程序中增加即可。
? ? ? ? 單片機(jī)通過(guò)串口返回的數(shù)據(jù)和網(wǎng)址上顯示的一致。
?2、完整的工程
? ? ? ? 完整的工程代碼點(diǎn)擊該鏈接下載,無(wú)需積分,直接下載:STM32工程文件???????
3、補(bǔ)充
? ? ? ? 這篇博客說(shuō)明了天氣的獲取方式,天氣的讀取,后面想做天氣顯示等應(yīng)用,只需要加上LCD的驅(qū)動(dòng)程序即可,花里胡哨的功能要靠自己去琢磨噻。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-490906.html
? ? ? ? 最后希望博客對(duì)你有幫助,喜歡的話可以點(diǎn)個(gè)贊呢??????。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-490906.html
到了這里,關(guān)于【STM32訓(xùn)練—WiFi模塊】第二篇、STM32驅(qū)動(dòng)ESP8266WiFi模塊獲取天氣的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!