ESP8266系列無線模塊是安信可科技自主研發(fā)設(shè)計(jì)的一系列高性價(jià)比WiFisOC模組。該系列模塊支持標(biāo)準(zhǔn)的IEEE802.11 b/g/n 協(xié)議,內(nèi)置完整的TCP/IP協(xié)議棧。用戶可以使用該系列模塊為現(xiàn)有的設(shè)備添加聯(lián)網(wǎng)功能,也可以構(gòu)建獨(dú)立的網(wǎng)絡(luò)控制器。即使在不了解其原理的情況下,只要有一定的串口知識理解,那么就可以輕松上手該模塊,進(jìn)而實(shí)現(xiàn)手機(jī)WiFi操作。功能特點(diǎn):基于ESP8266芯片開發(fā),模組集成了透傳功能,即買即用,支持串口AT指令集,用戶通過串口即可實(shí)現(xiàn)網(wǎng)絡(luò)訪問,廣泛應(yīng)用于智能穿戴,智能家居,家庭安防,遙控器,汽車電子,智慧照明,工業(yè)物聯(lián)網(wǎng)等領(lǐng)域。
一、模塊來源
模塊實(shí)物展示:
資料鏈接:https://pan.baidu.com/s/13mQInPq5drMzs8sXzC14dQ
資料提取碼:pj4z
二、規(guī)格參數(shù)
工作電壓:3.0V-3.6V
工作電流:IMAX = 170mA
模塊尺寸:14.4 x 24.7 MM
控制方式:串口
三、移植過程
我們的目標(biāo)是在立創(chuàng)·CW32F030C8T6開發(fā)板上能夠完成無線傳輸?shù)墓δ堋J紫纫@取資料,查看數(shù)據(jù)手冊應(yīng)如何實(shí)現(xiàn),再移植至我們的工程。
3.1查看資料
該WIFI模塊,有三種模式即STA、AP、STA+AP。
這里主要使用AP和STA模式作為案例,實(shí)現(xiàn)近距離無線控制和遠(yuǎn)距離無線控制。
- STA模式是指ESP8266作為客戶端連接到一個無線路由器上(或者無線熱點(diǎn)),可以訪問網(wǎng)絡(luò)中的其他設(shè)備。
- AP模式是指ESP8266作為熱點(diǎn),其他設(shè)備可以連接到它上面,實(shí)現(xiàn)無線網(wǎng)絡(luò)通信。
- STA+AP模式就是兩者同時實(shí)現(xiàn)。、
使用前,需要燒入MQTT固件,后續(xù)的案例有使用MQTT,如不燒入MQTT固件,在涉及到MQTT的AT命令時會不斷失敗。
固件下載地址:
鏈接:https://pan.baidu.com/s/1BB_X7XhKpedunGY1EIFX7A?pwd=LCKF
提取碼:LCKF
固件燒錄接線:
燒錄步驟:
鏈接:https://pan.baidu.com/s/1acnXmU3ASNQMjsner4DSrA?pwd=LCKF
提取碼:LCKF
3.2引腳選擇
使用串口2(串口2-TX=PA2,串口2-RX=PA3)
模塊接線圖
3.3移植至工程
移植步驟中的導(dǎo)入.c和.h文件與【CW32模塊使用】DHT11溫濕度傳感器相同,只是將.c和.h文件更改為bsp_esp01s.c與bsp_esp01s.h。這里不再過多講述,移植完成后面修改相關(guān)代碼。
在文件bsp_esp01s.c中,編寫如下代碼。
/*
* Change Logs:
* Date Author Notes
* 2024-06-21 LCKFB-LP first version
*/
#include "bsp_ESP01S.h"
#include "stdio.h"
#include "hmacsha1.h"
#include "string.h"
#include
unsigned char WIFI_RX_BUFF[WIFI_RX_LEN_MAX];
unsigned char WIFI_RX_FLAG = 0;
unsigned char WIFI_RX_LEN = 0;
uint8_t wifi_link_flag = 0;//設(shè)備連接狀態(tài)
//配合 Get_Device_connection_status 函數(shù)使用
// * 0=沒有設(shè)備連接
// * 1=有設(shè)備連接了WIFI
// * 0=有設(shè)備斷開了WIFI
// * 2=有設(shè)備連接了服務(wù)器
// * 3=有設(shè)備斷開了服務(wù)器
/************************************************************
* 函數(shù)名稱:WIFI_USART_Init
* 函數(shù)說明:連接WIFI的初始化
* 型 參:bund=串口波特率
* 返 回 值:無
* 備 注:無
*************************************************************/
void WIFI_USART_Init(unsigned int bund)
{
GPIO_InitTypeDef GPIO_InitStruct; // GPIO初始化結(jié)構(gòu)體
RCC_WIFI_GPIO_ENABLE(); // 使能GPIO時鐘
RCC_WIFI_USART_ENABLE(); // 使能UART時鐘
GPIO_InitStruct.Pins = GPIO_WIFI_TX; // GPIO引腳
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽輸出
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; // 輸出速度高
GPIO_Init(PORT_WIFI_GPIO, &GPIO_InitStruct); // 初始化
GPIO_InitStruct.Pins = GPIO_WIFI_RX; // GPIO引腳
GPIO_InitStruct.Mode = GPIO_MODE_INPUT_PULLUP; // 上拉輸入
GPIO_Init(PORT_WIFI_GPIO, &GPIO_InitStruct); // 初始化
BSP_GPS_AF_UART_TX(); // UART_TX復(fù)用
BSP_GPS_AF_UART_RX(); // UART_RX復(fù)用
// 配置UART
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = bund; // 波特率
USART_InitStructure.USART_Over = USART_Over_16; // 配置USART的過采樣率。
USART_InitStructure.USART_Source = USART_Source_PCLK; // 設(shè)置時鐘源
USART_InitStructure.USART_UclkFreq = 64000000; //設(shè)置USART時鐘頻率(和主頻一致即可)
USART_InitStructure.USART_StartBit = USART_StartBit_FE; //RXD下降沿開始
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 停止位1
USART_InitStructure.USART_Parity = USART_Parity_No ; // 不使用校驗(yàn)
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 不使用流控
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 收發(fā)模式
USART_Init(WIFI_USART, &USART_InitStructure); // 初始化串口2
// 優(yōu)先級,無優(yōu)先級分組
NVIC_SetPriority(WIFI_USART_IRQ, 0);
// UARTx中斷使能
NVIC_EnableIRQ(WIFI_USART_IRQ);
// 使能UARTx RC中斷
USART_ITConfig(WIFI_USART, USART_IT_RC, ENABLE);
}
/******************************************************************
* 函 數(shù) 名 稱:WIFI_USART_Send_Bit
* 函 數(shù) 說 明:向WIFI模塊發(fā)送單個字符
* 函 數(shù) 形 參:ch=字符
* 函 數(shù) 返 回:無
* 作 者:LC
* 備 注:無
******************************************************************/
void WIFI_USART_Send_Bit(unsigned char ch)
{
// 發(fā)送一個字節(jié)
USART_SendData_8bit(WIFI_USART, (uint8_t)ch);
// 等待發(fā)送完成
while( RESET == USART_GetFlagStatus(WIFI_USART, USART_FLAG_TXE) ){}
}
/******************************************************************
* 函 數(shù) 名 稱:WIFI_USART_send_String
* 函 數(shù) 說 明:向WIFI模塊發(fā)送字符串
* 函 數(shù) 形 參:str=發(fā)送的字符串
* 函 數(shù) 返 回:無
* 作 者:LC
* 備 注:無
******************************************************************/
void WIFI_USART_send_String(unsigned char *str)
{
printf("string : %srn",str);
while( str && *str ) // 地址為空或者值為空跳出
{
WIFI_USART_Send_Bit(*str++);
}
}
//清除串口接收的數(shù)據(jù)
/******************************************************************
* 函 數(shù) 名 稱:Clear_WIFI_RX_BUFF
* 函 數(shù) 說 明:清除WIFI發(fā)過來的數(shù)據(jù)
* 函 數(shù) 形 參:無
* 函 數(shù) 返 回:無
* 作 者:LC
* 備 注:無
******************************************************************/
void Clear_WIFI_RX_BUFF(void)
{
unsigned char i = WIFI_RX_LEN_MAX-1;
while(i)
{
WIFI_RX_BUFF[i--] = 0;
}
WIFI_RX_LEN = 0;
WIFI_RX_FLAG = 0;
}
/******************************************************************
* 函 數(shù) 名 稱:WIFI_Send_Cmd
* 函 數(shù) 說 明:向WIFI模塊發(fā)送指令,并查看WIFI模塊是否返回想要的數(shù)據(jù)
* 函 數(shù) 形 參:cmd=發(fā)送的AT指令 ack=想要的應(yīng)答 waitms=等待應(yīng)答的時間 cnt=等待應(yīng)答多少次
* 函 數(shù) 返 回:1=得到了想要的應(yīng)答 0=沒有得到想要的應(yīng)答
* 作 者:LC
* 備 注:無
******************************************************************/
char WIFI_Send_Cmd(char *cmd,char *ack,unsigned int waitms,unsigned char cnt)
{
uint8_t tt = 0;
re:
WIFI_USART_send_String((unsigned char*)cmd);//1.發(fā)送AT指令
while(cnt--)
{
//時間間隔
delay_1ms(waitms);
//串口中斷接收藍(lán)牙應(yīng)答
if( WIFI_RX_FLAG == 1 )
{
WIFI_RX_FLAG = 0;
WIFI_RX_LEN = 0;
//查找是否有想要的數(shù)據(jù)
if( strstr((char*)WIFI_RX_BUFF, ack) != NULL )
{
return 1;
}
//清除接收的數(shù)據(jù)
memset( WIFI_RX_BUFF, 0, sizeof(WIFI_RX_BUFF) );
}
}
WIFI_RX_FLAG = 0;
WIFI_RX_LEN = 0;
if(tt < 3)
{
tt++;
goto re;
}
return 0;
}
/******************************************************************
* 函 數(shù) 名 稱:WIFI_ESP01S_Init
* 函 數(shù) 說 明:WIFI模塊ESP01S初始化
* 函 數(shù) 形 參:無
* 函 數(shù) 返 回:無
* 作 者:LC
* 備 注:ESP01S的默認(rèn)波特率是115200
******************************************************************/
void WIFI_ESP01S_Init(void)
{
WIFI_USART_Init(115200);//默認(rèn)波特率為115200
}
/******************************************************************
* 函 數(shù) 名 稱:WIFI_MODE_AP_Init
* 函 數(shù) 說 明:開啟AP模式,即模塊開啟熱點(diǎn)讓手機(jī)連接
* 函 數(shù) 形 參:無
* 函 數(shù) 返 回:1=配置成功 其他=失敗
* 作 者:LC
* 備 注:手機(jī)通過WIFI模塊默認(rèn)的IP地址192.168.4.1和設(shè)置的端口號,進(jìn)行連接
******************************************************************/
uint8_t WIFI_MODE_AP_Init(void)
{
uint8_t ret = 0;
char send_buff[200];
ret = WIFI_Send_Cmd("ATrn", "OK", 10, 3);//測試指令:ATrn 成功返回OK 失敗返回ERROR
if( ret != 1 ) return ret;
ret = WIFI_Send_Cmd("AT+CWMODE=2rn","OK",30,3); //配置WIFI AP模式
if( ret != 1 ) return ret;
sprintf(send_buff, "AT+CWSAP="%s","%s",11,4rn", AP_WIFISSID,AP_WIFIPASS );
ret = WIFI_Send_Cmd(send_buff,"OK",30,3); //設(shè)置wifi賬號與密碼
if( ret != 1 ) return ret;
ret = WIFI_Send_Cmd("AT+RSTrn","ready",800,3); //重新復(fù)位
if( ret != 1 ) return ret;
ret = WIFI_Send_Cmd("AT+CIPMUX=1rn","OK",50,3); //開啟多個連接
if( ret != 1 ) return ret;
ret = WIFI_Send_Cmd("AT+CIPSERVER=1,5000rn","OK",50,3); //開啟服務(wù)器設(shè)置端口號為5000
if( ret != 1 ) return ret;
return ret;
}
/******************************************************************
* 函 數(shù) 名 稱:Get_Device_connection_status
* 函 數(shù) 說 明:獲取設(shè)備連接狀態(tài)(AP模式)
* 函 數(shù) 形 參:無
* 函 數(shù) 返 回:0=沒有設(shè)備連接
* 1=有設(shè)備連接了WIFI
* 2=有設(shè)備斷開了WIFI
* 3=有設(shè)備連接了服務(wù)器
* 4=有設(shè)備斷開了服務(wù)器
* 作 者:LC
* 備 注:手機(jī)要連接WIFI模塊的步驟是先連接WIFI再連接服務(wù)器
//當(dāng)有設(shè)備連接AP模式下的熱點(diǎn)時,WIFI模塊會給連接的設(shè)備分配IP地址
//我們只需檢測是否有分配地址,則知道是否有設(shè)備連接。
//設(shè)備連接時WIFI返回:
// +STA_CONNECTED:"f0:6c:5d:d6:f6:18"
// +DIST_STA_IP:"f0:6c:5d:d6:f6:18","192.168.4.2"
//設(shè)備斷開連接時返回:
// +STA_DISCONNECTED:"f0:6c:5d:d6:f6:18"
******************************************************************/
uint8_t Get_Device_connection_status(void)
{
//串口中斷接收WIFI應(yīng)答
if( WIFI_RX_FLAG == 1 )
{
WIFI_RX_FLAG = 0;
WIFI_RX_LEN = 0;
//有設(shè)備連接了熱點(diǎn)
if( strstr((char*)WIFI_RX_BUFF, "+STA_CONNECTED") != NULL )
{
//清除接收的數(shù)據(jù)
wifi_link_flag = 1;
memset( WIFI_RX_BUFF, 0, sizeof(WIFI_RX_BUFF) );
#if DEBUG
printf("The device is connected to a hotspot.rn");
#endif
return 1;
}
//有設(shè)備斷開了熱點(diǎn)
if( strstr((char*)WIFI_RX_BUFF, "+STA_DISCONNECTED") != NULL )
{
//清除接收的數(shù)據(jù)
wifi_link_flag = 0;
memset( WIFI_RX_BUFF, 0, sizeof(WIFI_RX_BUFF) );
#if DEBUG
printf("The device is disconnected from the hotspot.rn");
#endif
return 2;
}
//有設(shè)備連接了服務(wù)器
if( strstr((char*)WIFI_RX_BUFF, ",CONNECT") != NULL )
{
//清除接收的數(shù)據(jù)
wifi_link_flag = 2;
memset( WIFI_RX_BUFF, 0, sizeof(WIFI_RX_BUFF) );
return 3;
#if DEBUG
printf("The device is connected to the server.rn");
#endif
}
//有設(shè)備斷開了服務(wù)器
if( strstr((char*)WIFI_RX_BUFF, ",CLOSED") != NULL )
{
//清除接收的數(shù)據(jù)
wifi_link_flag = 3;
memset( WIFI_RX_BUFF, 0, sizeof(WIFI_RX_BUFF) );
return 4;
#if DEBUG
printf("The device is disconnected from the server.rn");
#endif
}
}
return 0;
}
/**********************************************************
* 函 數(shù) 名 稱:Get_WIFI_AP_Data
* 函 數(shù) 功 能:解析設(shè)備發(fā)送過來的數(shù)據(jù)
* 傳 入 參 數(shù):ap_parameter要將數(shù)據(jù)保存的地址
* 函 數(shù) 返 回:1:有設(shè)備發(fā)送過來數(shù)據(jù) 0:沒有設(shè)備發(fā)送過來數(shù)據(jù)
* 作 者:LC
* 備 注:device_id最大5個 //+IPD,1,4:abcd
**********************************************************/
uint8_t Get_WIFI_AP_Data(AP_PARAMETER *ap_parameter)
{
char buff[50];
char *test;
char i=0;
//接收到設(shè)備發(fā)過來的數(shù)據(jù)
if( strstr((char*)WIFI_RX_BUFF,"+IPD,") != NULL )
{
test = strstr((char*)WIFI_RX_BUFF,"+IPD,");
//記錄設(shè)備ID號
strncpy(buff,test+5,1);
buff[1] ='';
ap_parameter-?>device_id = atoi(buff);
printf("device_id = %srn",buff);
//記錄發(fā)送過來的數(shù)據(jù)長度
strncpy(buff,test+7,strcspn(test+7,":") );
buff[ strcspn(test+7,":") ] ='';
printf("device_data = %srn",buff);
ap_parameter->device_datalen = atoi(buff);
printf("device_datalen = %srn",buff);
//記錄發(fā)送過來的數(shù)據(jù)
memset(buff,0,sizeof(buff));
while(test[i++]!=':');
strncpy(buff, test+i,strcspn(test+i,"r") );
printf("device_data = %srn",buff);
strcpy((char*)ap_parameter->device_data, buff);
//清除串口接近緩存
Clear_WIFI_RX_BUFF();
return 1;
}
return 0;
}
/******************************************************************
* 函 數(shù) 名 稱:WIFI_Send_To_Client
* 函 數(shù) 說 明:AP模式下,WIFI發(fā)送數(shù)據(jù)至客戶端(連接AP模式下熱點(diǎn)的設(shè)備)
* 函 數(shù) 形 參:id=向第幾個客戶端發(fā)送數(shù)據(jù) data=要發(fā)送的數(shù)據(jù)(字符串形式)
* 函 數(shù) 返 回:0=發(fā)送失敗 1=發(fā)送成功
* 作 者:LC
* 備 注:使用該函數(shù)函數(shù)請確保WIFI模塊處于AP模式
******************************************************************/
uint8_t WIFI_Send_To_Client(uint8_t id,char * data)
{
uint8_t send_buf[20]={0};
sprintf((char*)send_buf,"AT+CIPSEND=%d,%drn",id,strlen(data));
if(WIFI_Send_Cmd((char*)send_buf,">",20,3))
{
WIFI_USART_send_String((unsigned char *)data);
return 1;
}
return 0;
}
/******************************************************************
* 函 數(shù) 名 稱:mstrcat
* 函 數(shù) 說 明:字符串連接
* 函 數(shù) 形 參:s1:目標(biāo)字符串, s2:源字符串
* 函 數(shù) 返 回:無
* 作 者:LC
* 備 注:哈希使用
******************************************************************/
static void mstrcat(char *s1, const char *s2)
{
// 尋找s1的末尾(即''字符)
while(*s1 != '')
s1++;
// 將s2的內(nèi)容復(fù)制到s1的末尾,包括s2的結(jié)束字符''
while((*s1++ = *s2++));
}
/******************************************************************
* 函 數(shù) 名 稱:CalculateSha1
* 函 數(shù) 說 明:計(jì)算sha1密匙
* 函 數(shù) 形 參:password:密匙存放緩沖區(qū)
* 函 數(shù) 返 回:無
* 作 者:LC
* 備 注:無
******************************************************************/
static void CalculateSha1(unsigned char *password)
{
unsigned char temp[3] = {0};
unsigned char digest[30]={0};
unsigned char cnt = 0;
hmac_sha1((unsigned char *)DeviceSecret,32,(unsigned char *)Encryption,46,digest);
memset(temp, 0, sizeof(temp));
for(cnt=0;cnt20;cnt++)
{
sprintf((char *)temp,"%02X",digest[cnt]);
mstrcat((char *)password,(char *)temp);
}
}
/******************************************************************
* 函 數(shù) 名 稱:WIFI_MODE_STA_Aliyun_Init
* 函 數(shù) 說 明:配置WIFI模塊連接阿里云物聯(lián)網(wǎng)平臺
* 函 數(shù) 形 參:無
* 函 數(shù) 返 回:無
* 作 者:LC
* 備 注:無
******************************************************************/
void WIFI_MODE_STA_Aliyun_Init(void)
{
char AT_CMD[250]={0};
uint8_t PassWord[50] = {0}; //存放的是哈希計(jì)算的密鑰
RST:
//測試指令A(yù)T
WIFI_Send_Cmd("ATrn","OK",100,3);
//配置WIFI STA
WIFI_Send_Cmd("AT+CWMODE=1rn","OK",300,3);
//設(shè)置時區(qū) NTSP服務(wù)器 用于調(diào)整客戶端自身所在系統(tǒng)的時間,達(dá)到同步時間的目的
WIFI_Send_Cmd("AT+CIPSNTPCFG=1,8,"ntp1.alliyun.com"rn","OK",100,3);
//連接wifi 賬號&密碼
sprintf(AT_CMD,"AT+CWJAP="%s","%s"rn",WIFISSID,WIFIPASS);
if( WIFI_Send_Cmd(AT_CMD,"OK",3000,3) == 0 )
{
printf("WIFI名稱或密碼有錯,復(fù)位重啟rn");
//wifi連接不上,重啟
WIFI_Send_Cmd("AT+RSTrn","ready",1000,1);
goto RST;
}
//清0數(shù)組,備用
memset(AT_CMD,0,sizeof(AT_CMD));
//計(jì)算哈希
CalculateSha1(PassWord);
#if DEBUG
// sprintf(PassWord,"%s","AF7596ADFFD4C57C5FD43F1CA1A20DE961634360");
printf("haxi=%srn",PassWord);
printf("UserName=%srn",UserName);
#endif
sprintf(AT_CMD,"AT+MQTTUSERCFG=0,1,"NULL","%s","%s",0,0,""rn", UserName, PassWord);
WIFI_Send_Cmd(AT_CMD,"OK",2000,3);
//設(shè)置連接客戶端ID
memset(AT_CMD,0,sizeof(AT_CMD)); //清0數(shù)組,備用
sprintf(AT_CMD,"AT+MQTTCLIENTID=0,"%s"rn",ClientId);
WIFI_Send_Cmd(AT_CMD,"OK",1000,3);
//連接到MQTT代理(阿里云平臺)
memset(AT_CMD,0,sizeof(AT_CMD));
sprintf(AT_CMD,"AT+MQTTCONN=0,"%s",1883,1rn",IP);
if(WIFI_Send_Cmd(AT_CMD,"OK",2000,3)==0)
{
printf("連接aliyu失敗,復(fù)位STM32重連rn");
//wifi連接不上,重啟 1000延時1S 2鏈接次數(shù)
WIFI_Send_Cmd("AT+RSTrn","ready",1000,2);
// __set_FAULTMASK(1); //STM32程序軟件復(fù)位
NVIC_SystemReset();
}
//訂閱主題
memset(AT_CMD,0,sizeof(AT_CMD));
sprintf(AT_CMD, "AT+MQTTSUB=0,"%s",1rn", PublishMessageTopSet);
WIFI_Send_Cmd(AT_CMD,"OK",1000,3);
printf("連接aliyu成功rn");
Clear_WIFI_RX_BUFF();//清除串口接收緩存
//上電就上傳數(shù)據(jù)至手機(jī)
// Publish_MQTT_message(publish_mqtt_message,5,); //發(fā)布主題
}
/*點(diǎn)擊LED開關(guān)
+MQTTSUBRECV:0,"/sys/a1PJRLOWo3p/TEST/thing/service/property/set",100,
{"method":"thing.service.property.set","id":"367399823","params":{"LED_Switch":1},"version":"1.0.0"}
*/
/*滑動亮度條
+MQTTSUBRECV:0,"/sys/a1PJRLOWo3p/TEST/thing/service/property/set",101,
{"method":"thing.service.property.set","id":"812539841","params":{"brightness":75},"version":"1.0.0"}
*/
/******************************************************************
* 函 數(shù) 名 稱:Get_Aliyun_json_data
* 函 數(shù) 說 明:獲取阿里云JSON格式的數(shù)據(jù)(接收手機(jī)發(fā)送過來的數(shù)據(jù))
* 函 數(shù) 形 參:data=數(shù)據(jù)的保存地址
* 函 數(shù) 返 回:1=接收到JSON數(shù)據(jù)并處理 0=沒有接收到數(shù)據(jù)
* 作 者:LC
* 備 注:無
******************************************************************/
uint8_t Get_Aliyun_json_data(JSON_PUBLISH *data)
{
char *buff=0;
//串口中斷接收WIFI應(yīng)答
if( WIFI_RX_FLAG == SET )
{
printf("rn--rn");
WIFI_RX_FLAG = 0;
WIFI_RX_LEN = 0;
//有設(shè)備連接了熱點(diǎn)
if( strstr((char*)WIFI_RX_BUFF, "params":") != NULL )
{
//獲取功能名稱
buff = strstr((char*)WIFI_RX_BUFF, "params":");
buff += strlen("params":{"");
strcpy(data-?>keyname,strtok(buff,"""));
printf("data->keyname = %srn",data->keyname);
//獲取功能值
buff = strstr((char*)WIFI_RX_BUFF, "params":" );
buff += strlen("params":{"")+strlen(data->keyname)+2;
strcpy(data->value, strtok(buff,"}"));
return 1;
}
}
return 0;
}
/******************************************************************
* 函 數(shù) 名 稱:Clear_Aliyun_json_data
* 函 數(shù) 說 明:清除JSON接收過的數(shù)據(jù)
* 函 數(shù) 形 參:data=要清除的數(shù)據(jù)
* 函 數(shù) 返 回:無
* 作 者:LC
* 備 注:無
******************************************************************/
void Clear_Aliyun_json_data(JSON_PUBLISH *data)
{
uint16_t i = 0;
while( data->keyname[i] != 0 )
{
data->keyname[i++] = '';
}
i= 0;
while( data->value[i] != 0 )
{
data->keyname[i++] = '';
}
}
//在自定義功能時,有多少個標(biāo)識符,就添加多少個
//我就只有兩個標(biāo)識符。
//LED_Switch=LED開關(guān) 范圍0-1
//brightness=亮度 范圍0-100
JSON_PUBLISH publish_mqtt_message[2]=
{
{ ""LED_Switch":","0" },
{ ""brightness":","0" }
};
/******************************************************************
* 函 數(shù) 名 稱:Publish_MQTT_message
* 函 數(shù) 說 明:發(fā)布主題 ,上發(fā)多個數(shù)據(jù)(設(shè)備將數(shù)據(jù)發(fā)送至手機(jī))
* 函 數(shù) 形 參:data=publish_mqtt_message, data_num=上傳的數(shù)據(jù)個數(shù)
* 函 數(shù) 返 回:無
* 作 者:LC
* 備 注:無
******************************************************************/
void Publish_MQTT_message(JSON_PUBLISH *data,uint8_t data_num)
{
char AT_CMD[384]={0};
char params[256]={0},i,*sp;
sp=params;
sprintf(data[0].value,"%d",0); //把傳感器的值賦值給json結(jié)構(gòu)體的value
sprintf(data[1].value,"%d",90);
// 4
for(i=0;i
在文件bsp_esp01s.h中,編寫如下代碼。
/*
* Change Logs:
* Date Author Notes
* 2024-06-21 LCKFB-LP first version
*/
#ifndef _BSP_ESP01S_H_
#define _BSP_ESP01S_H_
#include "board.h"
#include "string.h"
//是否開啟串口0調(diào)試,查看WIFI回顯數(shù)據(jù)
#define DEBUG 1
/**************************** STA模式 ****************************/
//STA模式下,WIFI模塊要連接的熱點(diǎn)(需要自行修改為自己的參數(shù))
#define WIFISSID "aaa" //wifi熱點(diǎn)名稱
#define WIFIPASS "12345678" //wifi熱點(diǎn)密碼
//連接的阿里云IP端口(不可修改)
#define IP "203.107.45.14" //阿里云服務(wù)器IP或域名
//#define IP "a1PaQm83lGg.iot-as-mqtt.cn-shenzhen.aliyuncs.com" //服務(wù)器IP或域名
#define PORT 1883 //連接端口號,MQTT默認(rèn)1883
//阿里云三元組(需要自行修改為自己的參數(shù))
#define DeviceName "TEST" //設(shè)備名稱
#define ProductKey "a1PJRLOWo3p" //產(chǎn)品密匙
#define DeviceSecret "3e7a1a43694b65abdcbc4f5c724e9faf" //設(shè)備密匙
//計(jì)算哈希算法用到加密(不可修改)
#define Client "clientId123deviceName"
#define productKey "productKey"
#define Encryption (Client DeviceName productKey ProductKey)
//AT指令的
#define AND "&"
#define ClientId "123|securemode=3\,signmethod=hmacsha1|" //客戶端ID
#define UserName (DeviceName AND ProductKey) //用戶名
//訂閱發(fā)布的主題(不可修改)
#define SYS "/sys/"
#define LINK "/"
#define TOP "/thing/event/property/"
#define POST "post"
#define ESET "set"
#define PublishMessageTopPost (SYS ProductKey LINK DeviceName TOP POST)
#define PublishMessageTopSet (SYS ProductKey LINK DeviceName TOP ESET)
//上傳數(shù)據(jù)結(jié)構(gòu)體
typedef struct
{
char keyname[50]; //鍵讀取
char value[20]; //讀取到的值,類型字符串
}JSON_PUBLISH;
extern JSON_PUBLISH publish_mqtt_message[2];
/**************************** AP模式 ****************************/
//AP模式下,WIFI開啟的熱點(diǎn)
#define AP_WIFISSID "ESP-01S"
#define AP_WIFIPASS "12345678"
typedef struct
{
uint8_t device_id;
uint8_t device_datalen;
uint8_t device_data[200];
}AP_PARAMETER;
/**************************** 串口配置 ****************************/
#define RCC_WIFI_GPIO_ENABLE() __RCC_GPIOA_CLK_ENABLE() // 串口TX的端口時鐘
#define RCC_WIFI_USART_ENABLE() __RCC_UART2_CLK_ENABLE() // 串口2的時鐘
#define BSP_GPS_AF_UART_TX() PA02_AFx_UART2TXD() // GPIO的引腳復(fù)用
#define BSP_GPS_AF_UART_RX() PA03_AFx_UART2RXD() // GPIO的引腳復(fù)用
#define PORT_WIFI_GPIO CW_GPIOA // 串口TX的端口
#define GPIO_WIFI_TX GPIO_PIN_2 // 串口TX的引腳
#define GPIO_WIFI_RX GPIO_PIN_3 // 串口RX的引腳
#define WIFI_USART CW_UART2 // 串口2
#define WIFI_USART_IRQ UART2_IRQn // 串口2中斷
#define WIFI_USART_IRQHandler UART2_IRQHandler // 串口2中斷服務(wù)函數(shù)
#define WIFI_RX_LEN_MAX 200 //串口接收最大長度
extern uint8_t wifi_link_flag;//設(shè)備連接狀態(tài)
//配合 Get_Device_connection_status 函數(shù)使用
// * 0=沒有設(shè)備連接
// * 1=有設(shè)備連接了WIFI
// * 0=有設(shè)備斷開了WIFI
// * 2=有設(shè)備連接了服務(wù)器
// * 3=有設(shè)備斷開了服務(wù)器
void WIFI_ESP01S_Init(void); //WIFI模塊初始化
uint8_t WIFI_MODE_AP_Init(void); //AP模式初始化
uint8_t Get_Device_connection_status(void);//獲取連接狀態(tài)
void WIFI_MODE_STA_Aliyun_Init(void); //連接阿里云初始化
uint8_t Get_WIFI_AP_Data(AP_PARAMETER *ap_parameter);
uint8_t Get_Aliyun_json_data(JSON_PUBLISH *data);
void Clear_Aliyun_json_data(JSON_PUBLISH *data);
void Publish_MQTT_message(JSON_PUBLISH *data,uint8_t data_num);
char WIFI_Send_Cmd(char *cmd,char *ack,unsigned int waitms,unsigned char cnt);
#endif
四、案例一:AP模式下的手機(jī)控制
使用AP模式通過AT命令,控制WIFI模塊開啟熱點(diǎn)、多連接、服務(wù)器。待手機(jī)連接后,通過手機(jī)APP進(jìn)行數(shù)據(jù)互傳。
使用案例前,請確保bsp_esp01s.c和bsp_esp01s.h移植成功。
手機(jī)APP下載地址:
鏈接:https://pan.baidu.com/s/1-wh0aaqRMW8fJ5nLH1Lwyw?pwd=LCKF
提取碼:LCKF
APP操作
首先使用手機(jī)連接WIFI模塊的熱點(diǎn)。其次打開APP連接服務(wù)器。服務(wù)器默認(rèn)IP為192.168.4.1,端口號在代碼中設(shè)置為了5000。
連接上WIFI的熱點(diǎn)后,打開APP連接服務(wù)器。
編輯各個按鈕值,方便后面我們進(jìn)行控制。
在main.c中,編寫如下代碼。
/*
* Change Logs:
* Date Author Notes
* 2024-06-21 LCKFB-LP first version
*/
#include "board.h"
#include "stdio.h"
#include "bsp_uart.h"
#include "bsp_esp01s.h"
int32_t main(void)
{
AP_PARAMETER ap_parameter={0};
uint8_t test_ret = 0;
board_init();
uart1_init(115200U);
printf("Startrn");
//WIFI初始化
WIFI_ESP01S_Init();
//設(shè)置WIFI模塊為AP模式
WIFI_MODE_AP_Init();
while(1)
{
//判斷是否有設(shè)備連接
Get_Device_connection_status();
//如果當(dāng)前設(shè)備連接了服務(wù)器(手機(jī)APP連接上熱點(diǎn))
if( wifi_link_flag == 2 )
{
if( Get_WIFI_AP_Data(&ap_parameter) == 1 )//如果接收到數(shù)據(jù)
{
//輸出接收的數(shù)據(jù)
printf("ID = %drn", ap_parameter.device_id );//設(shè)備ID
printf("data len = %drn", ap_parameter.device_datalen );//發(fā)送過來的數(shù)據(jù)長度
printf("data = %srn", ap_parameter.device_data );//發(fā)送過來的數(shù)據(jù)
}
}
}
案例現(xiàn)象:
當(dāng)手機(jī)APP接入WIFI連接成功之后,APP發(fā)送數(shù)據(jù)到開發(fā)板的串口。
默認(rèn)ip:192.168.4.1 默認(rèn)端口:5000
工程代碼下載:
鏈接:https://pan.baidu.com/s/16IPzyT_Rdm2E2BgPvYe-pw?pwd=LCKF
提取碼:LCKF
審核編輯 黃宇
-
芯片
+關(guān)注
關(guān)注
456文章
51141瀏覽量
426168 -
WIFI
+關(guān)注
關(guān)注
81文章
5307瀏覽量
204423 -
CW32
+關(guān)注
關(guān)注
1文章
218瀏覽量
706
發(fā)布評論請先 登錄
相關(guān)推薦
評論