由于之前使用STM32單片機(jī)來開發(fā)一些物聯(lián)網(wǎng)的小項(xiàng)目,接觸到了WIFI模塊ESP8266,所以寫下來記錄一下。本文主要介紹的是STM32通過發(fā)送AT指令集來控制ESP8266 WIFI模塊連接WiFi并與心知天氣API建立TCP連接獲取天氣信息。
一、硬件連接
ESP8266我使用的是正點(diǎn)原子的ATK-ESP8266,已經(jīng)提前燒錄好AT指令集固件,至于固件的燒錄可以參考正點(diǎn)原子的教程或者去安可信官網(wǎng)查找相關(guān)資料即可。STM32單片機(jī)設(shè)計(jì)有USB轉(zhuǎn)串口即可。
STM32 VCC -> ESP8266 VCC
STM32 TXD2 -> ESP8266 RXD
STM32 RXD2 -> ESP8266 TXD
STM32 GND -> ESP8266 GND
這里用到了兩組串口,USART1用于打印調(diào)試信息到電腦的串口助手中;USART2用于主控與ESP8266的通信。串口配置代碼直接沿用了正點(diǎn)原子提供的。在這里就不貼出來了。
二、連接WiFi
ESP8266有三種WiFi模式,分別是station模式,AP模式和station+AP模式。簡(jiǎn)單來說,station模式就是8266作為連接WiFi的設(shè)備;AP模式就是8266作為提供WiFi的設(shè)備,相當(dāng)于手機(jī)的熱點(diǎn)功能。連接WiFi最簡(jiǎn)單的步驟就兩步:8266為station模式和連接WiFi。
設(shè)置WiFi模式
設(shè)置WiFi模式的AT指令有AT+CWMODE,AT+CWMODE_CUR和AT+CWMODE_DEF。后面兩種指令的區(qū)別是后綴為DEF的指令會(huì)將設(shè)置保存到flash中,重新上電不需要再次設(shè)置。第一種不帶后綴的指令,官方文檔寫的是不建議使用,所以就用最后一種就行了。以下是官方文檔的具體說明
連接WiFi
連接WiFi指令和設(shè)置WiFi模式指令一樣有三個(gè)版本,這里使用AT+CWJAP_DEF來說明。
ssid是你要連接WiFi的名字,pwd是密碼,bssid是當(dāng)有多個(gè)相同名字WiFi區(qū)分用的。值得注意的是,WiFi名字或者密碼有特殊符號(hào)要使用\進(jìn)行轉(zhuǎn)義。
所以,連接WiFi只需要發(fā)送以下指令即可:
//設(shè)置為station模式
AT+CWMODE_DEF=1\r\n
//連接WiFi
AT+CWJAP_DEF="你的WiFi名","你的WiFi密碼"\r\n
三、建立TCP連接
TCP連接這里以連接心知天氣獲取天氣信息為例。主要為3步:與心知天氣網(wǎng)站建立TCP連接,開啟透?jìng)?,發(fā)送GET請(qǐng)求獲取天氣信息。
心知天氣
心知天氣是提供天氣信息的API,可以使用GET請(qǐng)求獲取JSON格式的天氣信息,有免費(fèi)的版本可用,非常適合嵌入式應(yīng)用的開發(fā)。具體文檔說明和賬號(hào)申請(qǐng)可自行官網(wǎng)查看(https://www.seniverse.com) 。心知天氣會(huì)為每個(gè)賬戶提供公鑰和私鑰,這里我們只用到私鑰,只需替代掉接口網(wǎng)址中your_api_key為自己的私鑰即可。
https://api.seniverse.com/v3/weather/now.json?key=your_api_key&location=zhaoqing&language=en&unit=c
建立TCP連接
建立TCP,UDP或SSL連接使用指令AT+CIPSTART,具體參數(shù)如下:
因?yàn)槲覀円褂猛競(jìng)髋c網(wǎng)站通信,所以TCP必須設(shè)置為單連接;連接類型為TCP;遠(yuǎn)端IP可以是心知天氣的具體IP地址,也可以用域名api.seniverse.com來代替;心知天氣提供該服務(wù)的端口號(hào)是80端口。最后,建立TCP連接的AT指令是:
//建立TCP連接,參數(shù)為 連接類型 遠(yuǎn)端IP 遠(yuǎn)端端口號(hào)
AT+CIPSTART="TCP","api.seniverse.com",80\r\n
開啟透?jìng)?/h5>
開啟透?jìng)魇紫纫褂?mark>AT+CIPMODE=mode設(shè)置傳輸模式,mode為0是普通傳輸模式,mode為1是透?jìng)髂J?。設(shè)置完成后使用指令AT+CIPSEND開始傳輸,具體指令參數(shù)說明如下:
開啟透?jìng)骱鬅o需寫發(fā)送數(shù)據(jù)的長(zhǎng)度,直接發(fā)送AT+CIPSEND即可,8266返回>即表示成功進(jìn)入透?jìng)?,此時(shí)無法再發(fā)送AT指令,發(fā)送的字符將會(huì)被當(dāng)做數(shù)據(jù)全部發(fā)送給對(duì)方。若要退出透?jìng)鞣祷谹T指令模式,則要單獨(dú)發(fā)送+++,注意這里無需換行。
//設(shè)置傳輸模式為透?jìng)髂J?/span>
AT+CIPMODE=1\r\n
//開始透?jìng)?/span>
AT+CIPSEND\r\n
//退出透?jìng)?/span>
+++
GET請(qǐng)求
在進(jìn)入透?jìng)髦缶涂梢园l(fā)送我們的GET請(qǐng)求。在GET和空格后加上要訪問的接口地址就可以獲取到網(wǎng)站返回給我們的天氣信息了。記得更改私鑰和在后面加上換行。文章來源:http://www.zghlxwxcb.cn/news/detail-404016.html
GET https://api.seniverse.com/v3/weather/now.json?key=your_api_key&location=zhaoqing&language=en&unit=c\r\n
文章來源地址http://www.zghlxwxcb.cn/news/detail-404016.html
四、核心代碼
//檢測(cè)接收到的應(yīng)答
uint8_t* Check_Command(char *str)
{
char *strx = 0;
if(USART2_RX_STA&0X8000) //接收到一次數(shù)據(jù)了
{
USART2_RX_BUF[USART2_RX_STA&0X7FFF]=0;//添加結(jié)束符
strx=strstr((const char*)USART2_RX_BUF,(const char*)str);
}
return (uint8_t *)strx;
}
//向8266發(fā)送命令
//cmd:發(fā)送的命令字符串
//ack:期待的應(yīng)答結(jié)果
//waittime:等待時(shí)間(單位:10ms)
//返回值:1,發(fā)送成功(得到了期待的應(yīng)答結(jié)果)
// 0,發(fā)送失敗
uint8_t Send_Command(char *cmd, char *ack, uint8_t waittime)
{
uint8_t res=1;
USART2_RX_STA=0;
u2_printf("%s\r\n",cmd); //發(fā)送命令
if(ack&&waittime) //需要等待應(yīng)答
{
while(--waittime) //等待倒計(jì)時(shí)
{
HAL_Delay(10);
if(USART2_RX_STA&0X8000)//接收到期待的應(yīng)答結(jié)果
{
if(Check_Command(ack))
{
printf("ack:%s\r\n",(uint8_t*)USART2_RX_BUF);
break;//得到有效數(shù)據(jù)
}
USART2_RX_STA=0;
}
}
if(waittime==0)res=0;
}
return res;
}
//向8266發(fā)送數(shù)據(jù)
void Send_Data(char *data)
{
USART2_RX_STA=0;
u2_printf("%s",data); //發(fā)送數(shù)據(jù)
}
char Rcv_Str[1024] = "NULL";
//建立TCP連接,并開啟透?jìng)?/span>
void TCP_Connect()
{
Send_Command("AT+CIPSTART=\"TCP\",\"api.seniverse.com\",80","OK",50);
HAL_Delay(500);
//查詢是否成功建立連接,成功則開啟透?jìng)靼l(fā)送數(shù)據(jù)
if(Send_Command("AT+CIPSTATUS","TCP",20))
{
Send_Command("AT+CIPMODE=1","OK",20); //設(shè)置為透?jìng)髂J?/span>
Send_Command("AT+CIPSEND",">",20); //開啟透?jìng)?/span>
HAL_Delay(1000);
//發(fā)送GET請(qǐng)求
Send_Data("GET https://api.seniverse.com/v3/weather/now.json?key=SJhnSCUV2ASZsxCzh&location=zhaoqing&language=zh-Hans&unit=c\r\n");
HAL_Delay(1000);
strcpy(Rcv_Str,(const char*)USART2_RX_BUF); //將接收到的返回?cái)?shù)據(jù)復(fù)制
}
}
//退出透?jìng)?,斷開TCP連接
void TCP_Disconnect(void)
{
//退出發(fā)送模式
while((USART2->SR&0X40)==0); //等待發(fā)送空
USART2->DR='+';
HAL_Delay(15); //大于串口組幀時(shí)間(10ms)
while((USART2->SR&0X40)==0); //等待發(fā)送空
USART2->DR='+';
HAL_Delay(15); //大于串口組幀時(shí)間(10ms)
while((USART2->SR&0X40)==0); //等待發(fā)送空
USART2->DR='+';
HAL_Delay(1000); //等待1s
while(!Send_Command("AT","OK",20))//退出透?jìng)髋袛?
{
HAL_Delay(200);
}
//關(guān)閉透?jìng)髂J?/span>
Send_Command("AT+CIPMODE=0","OK",20);
//斷開TCP連接
Send_Command("AT+CIPCLOSE","OK",20);
}
//主函數(shù)
int main(void)
{
HAL_Init();
SystemClock_Config();
USART1_Init(115200);
USART2_Init(115200);
HAL_Delay(1000);
//測(cè)試ESP8266模塊是否正常
if(Send_Command("AT","OK",10))
{
printf("ESP8266 Is Ready\r\n");
}
else
{
printf("ESP8266 Not Ready\r\n");
}
//如果WIFI不是Station模式,則設(shè)置為Station模式
if(!Send_Command("AT+CWMODE_DEF?","1",20))
{
Send_Command("AT+CWMODE_DEF=1","OK",20);
}
//查詢WIFI是否連接,未連接則連接
if(Send_Command("AT+CWJAP_DEF?","No AP",20))
{
HAL_Delay(500);
Send_Command("AT+CWJAP_DEF=\"BieLai\",\"12345678\"","OK",50);
}
HAL_Delay(1000);
TCP_Connect(); //建立TCP連接
printf("%s",Rcv_Str); //打印網(wǎng)站返回的信息
TCP_Disconnect(); //斷開TCP連接
while(1)
{
HAL_Delay(1000);
}
到了這里,關(guān)于STM32使用ESP8266模塊AT指令連接心知天氣API獲取天氣信息的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!