前期準備可以參考我的這篇文章 STM32F103+ESP8266(WiFi)模組 實現AP模式下的TCP C/S 和 UDP Client,重複部分不再贅述。
AP STA STA+AP 模式下,建立tcp/udp連線後,傳送指定命令,控制LED1和蜂鳴器的開關,讀取DHT11模組溫溼度資料。
命令如下:(每行都是一條命令,不要有換行等)具體實現在common.c
中
LED1 ON
LED1 OFF
BEEP ON
BEEP OFF
GET T&H
main.c
中呼叫atk_8266_test();
atk_8266_test(); //進入ATK_ESP8266測試
common.c
中 設定要連線wifi的資訊
//WIFI STA模式,設定要去連線的路由器無線引數,請根據你自己的路由器設定,自行修改.
const u8* wifista_ssid="ikaros"; //路由器SSID號
const u8* wifista_encryption="wpawpa2_aes"; //wpa/wpa2 aes加密方式
const u8* wifista_password="12345678"; //連線密碼
準備2個手機(有WiFi的電腦,接入路由器等都可以),一個開啟熱點,根據設定設定ssid、加密和密碼。
串列埠偵錯開啟,相關設定需要串列埠資訊協助完成。
手機也連上同一個wifi,開啟 網路偵錯工具,我用的是「網路測試」,建立tcp連線
復位,開啟串列埠
手機連線wifi,檢視分配的ip
修改程式碼wifiap.c
中的atk_8266_wifiap_test
函數中的ipbuf
u8 ipbuf[16] = "192.168.4.2"; // 改為手機分配到的ip
埠在common.c
中,我們保持不變
//連線埠號:8086,可自行修改為其他埠.
const u8* portnum="8086";
重新編譯燒錄。開啟串列埠,重複剛才的操作
手機開啟tcp server,監聽8086埠。
等待主動連線
下載:碼雲 GitHub
main.c
呼叫的atk_8266_test();
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "key.h"
#include "usmart.h"
#include "malloc.h"
#include "usart3.h"
#include "common.h"
#include "beep.h"
#include "dht11.h"
// AP模式測試
void ap_demo(void);
int main(void)
{
delay_init(); //延時函數初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設定中斷優先順序分組為組2:2位搶佔優先順序,2位響應優先順序
uart_init(115200); //串列埠初始化為115200
usmart_dev.init(72); //初始化USMART
LED_Init(); //初始化與LED連線的硬體介面
KEY_Init(); //初始化按鍵
BEEP_Init(); //初始化蜂鳴器
//LCD_Init(); //初始化LCD
usart3_init(115200); //初始化串列埠3
my_mem_init(SRAMIN); //初始化內部記憶體池
//LCD_Clear(BLACK);
while(DHT11_Init()) //DHT11初始化
{
printf("DHT11 Error\r\n");
}
delay_ms(1000);
BEEP = 0;
LED1 = 0;
// ap_demo();
atk_8266_test(); //進入ATK_ESP8266測試
}
// AP模式測試
void ap_demo(void)
{
u8 timex = 0;
u8 netpro = 0; //網路模式 0,TCP伺服器 1,TCP使用者端 2,UDP模式
u8 key;
u8 ipbuf[16] = "192.168.4.2"; //IP (根據你的裝置連上模組後分配到的IP填寫)
u8 *p;
u16 t = 999; //加速第一次獲取連結狀態
u16 rlen = 0;
u8 constate = 0; //連線狀態
while(atk_8266_send_cmd("AT","OK",20))//檢查WIFI模組是否線上
{
atk_8266_quit_trans();//退出透傳
atk_8266_send_cmd("AT+CIPMODE=0","OK",200); //關閉透傳模式
printf("未檢測到模組!!!\r\n");
delay_ms(800);
printf("嘗試連線模組...\r\n");
}
while(atk_8266_send_cmd("ATE0","OK",20));//關閉回顯
printf("ATK_ESP8266 WIFI模組測試\r\n");
printf("WIFI AP\r\n");
atk_8266_msg_show(0, 0, 0);
while(1)
{
delay_ms(10);
atk_8266_at_response(1);//檢查ATK-ESP8266模組傳送過來的資料,及時上傳給電腦
printf("ATK-ESP WIFI-AP 測試\r\n");
printf("正在設定ATK-ESP8266模組,請稍等...\r\n");
p=mymalloc(SRAMIN,32); //申請32位元組記憶體
PRESTA:
if(netpro&0X02) //UDP
{
printf("ATK-ESP WIFI-AP 測試\r\n");
printf("正在設定ATK-ESP模組,請稍等...\r\n");
sprintf((char*)p,"AT+CIPSTART=\"UDP\",\"%s\",%s",ipbuf,(u8*)portnum); //設定目標UDP伺服器
atk_8266_send_cmd("AT+CIPMUX=0","OK",100); //單連結模式
while(atk_8266_send_cmd(p,"OK",500));
}
else //TCP
{
if(netpro&0X01) //TCP Client 透傳模式測試
{
printf("ATK-ESP WIFI-AP 測試\r\n");
printf("正在設定ATK-ESP模組,請稍等...\r\n");
atk_8266_send_cmd("AT+CIPMUX=0","OK",20); //0:單連線,1:多連線
sprintf((char*)p,"AT+CIPSTART=\"TCP\",\"%s\",%s",ipbuf,(u8*)portnum); //設定目標TCP伺服器
while(atk_8266_send_cmd(p,"OK",200))
{
printf("WK_UP:返回重選");
printf("ATK-ESP 連線TCP Server失敗"); //連線失敗
key=KEY_Scan(0);
if(key==WKUP_PRES)goto PRESTA;
}
atk_8266_send_cmd("AT+CIPMODE=1","OK",200); //傳輸模式為:透傳
}
else //TCP Server
{
printf("ATK-ESP WIFI-AP 測試\r\n");
printf("正在設定ATK-ESP模組,請稍等...\r\n");
atk_8266_send_cmd("AT+CIPMUX=1","OK",20); //0:單連線,1:多連線
sprintf((char*)p,"AT+CIPSERVER=1,%s",(u8*)portnum);
atk_8266_send_cmd(p,"OK",20); //開啟Server模式,埠號為8086
}
}
printf("設定ATK-ESP模組成功!\r\n");
delay_ms(200);
printf("WK_UP:退出測試 KEY0:傳送資料\r\n");
atk_8266_get_wanip(ipbuf);//伺服器模式,獲取WAN IP
sprintf((char*)p,"IP地址:%s 埠:%s",ipbuf,(u8*)portnum);
printf("%s\r\n",p); //顯示IP地址和埠
atk_8266_wificonf_show(30,180,"請用裝置連線WIFI熱點:",(u8*)wifiap_ssid,(u8*)wifiap_encryption,(u8*)wifiap_password);
printf("狀態:%s\r\n",(u8*)ATK_ESP8266_WORKMODE_TBL[netpro]); //連線狀態
USART3_RX_STA=0;
while(1)
{
key=KEY_Scan(0);
if(key==WKUP_PRES) //WK_UP 退出測試
{
atk_8266_quit_trans(); //退出透傳
atk_8266_send_cmd("AT+CIPMODE=0","OK",20); //關閉透傳模式
myfree(SRAMIN,p); //釋放記憶體
return;
}
else if(key==KEY0_PRES) //KEY0 傳送資料
{
if((netpro==3)||(netpro==2)) //UDP
{
sprintf((char*)p,"ATK-8266%s測試%02d\r\n",ATK_ESP8266_WORKMODE_TBL[netpro],t/10);//測試資料
printf("傳送資料:%s\r\n",p);
atk_8266_send_cmd("AT+CIPSEND=25","OK",200); //傳送指定長度的資料
delay_ms(200);
atk_8266_send_data(p,"OK",100); //傳送指定長度的資料
timex=100;
}
else if((netpro==1)) //TCP Client
{
atk_8266_quit_trans();
atk_8266_send_cmd("AT+CIPSEND","OK",20); //開始透傳
sprintf((char*)p,"ATK-8266%s測試%02d\r\n",ATK_ESP8266_WORKMODE_TBL[netpro],t/10);//測試資料
printf("傳送資料:%s\r\n",p);
u3_printf("%s",p);
timex=100;
}
else //TCP Server
{
sprintf((char*)p,"ATK-8266%s測試%02d\r\n",ATK_ESP8266_WORKMODE_TBL[netpro],t/10);//測試資料
printf("傳送資料:%s\r\n",p);
atk_8266_send_cmd("AT+CIPSEND=0,25","OK",200); //傳送指定長度的資料
delay_ms(200);
atk_8266_send_data(p,"OK",100); //傳送指定長度的資料
timex=100;
}
}
if(timex)timex--;
t++;
delay_ms(5);
if(USART3_RX_STA&0X8000) //接收到一次資料了
{
rlen=USART3_RX_STA&0X7FFF; //得到本次接收到的資料長度
USART3_RX_BUF[rlen]=0; //新增結束符
sprintf((char*)p,"收到%d位元組,內容如下",rlen);//接收到的位元組數
printf("%s\r\n",p); //顯示接收到的資料長度
printf("接收資料:%s\r\n",USART3_RX_BUF);//顯示接收到的資料
USART3_RX_STA=0;
// USART3收到的資料進行解析
recv_data_analysis(netpro, USART3_RX_BUF);
if(constate!='+')t=1000; //狀態為還未連線,立即更新連線狀態
else t=0; //狀態為已經連線了,10秒後再檢查
}
if(t==1000)//連續10秒鐘沒有收到任何資料,檢查連線是不是還存在.
{
constate=atk_8266_consta_check();//得到連線狀態
if(constate=='+')printf("連線成功\r\n"); //連線狀態
else printf("連線失敗\r\n");
t=0;
}
if((t%20)==0)LED0=!LED0;
atk_8266_at_response(1);
}
}
}
在 wifiap.c wifista.c apsta.c
中,在收到USART3資料時,呼叫recv_data_analysis
函數,傳入當前模式和收到的資料,進行解析
// USART3收到的資料進行解析
recv_data_analysis(netpro, USART3_RX_BUF);
在common.c
中,recv_data_analysis
函數實現如下
// USART3收到的資料進行解析
void send_data_to_usart3(u8 netpro, char *data)
{
u8 len = 0;
u8 buf[20] = {0};
len = strlen(data);
if((netpro==3)||(netpro==2)) //UDP
{
sprintf((char*)buf, "AT+CIPSEND=%d", len);
atk_8266_send_cmd(buf,"OK",200); //傳送指定長度的資料
delay_ms(200);
atk_8266_send_data((u8 *)data,"OK",100); //傳送指定長度的資料
}
else if((netpro==1)) //TCP Client
{
atk_8266_quit_trans();
atk_8266_send_cmd("AT+CIPSEND","OK",20); //開始透傳
u3_printf("%s", data);
}
else // TCP server
{
sprintf((char*)buf, "AT+CIPSEND=0,%d", len);
atk_8266_send_cmd(buf,"OK",200); //傳送指定長度的資料
delay_ms(200);
atk_8266_send_data((u8 *)data,"OK",100); //傳送指定長度的資料
}
}
// USART3收到的資料進行解析
void recv_data_analysis(u8 netpro, u8 *USART3_RX_BUF)
{
char *ptr = NULL;
char buf[100] = {0};
u8 temperature = 0;
u8 humidity = 0;
ptr = mymalloc(SRAMIN, 600); //申請600位元組記憶體
if((netpro==1)) //TCP Client
{
sprintf(ptr, "%s", USART3_RX_BUF);
}
else //TCP Server
{
ptr = strstr((char *)USART3_RX_BUF, ":");
if(NULL != ptr)
{
// ptr指標後移一位
ptr++;
printf("解析後的命令為(<>內):<%s>\r\n", ptr);
}
}
// 接收到的資料進行處理
if(strcmp(ptr, "LED1 ON") == 0)
{
LED1 = 0;
printf("開啟LED1\r\n");
send_data_to_usart3(netpro, "開啟LED1成功\r\n");
}
else if(strcmp(ptr, "LED1 OFF") == 0)
{
LED1 = 1;
printf("關閉LED1\r\n");
send_data_to_usart3(netpro, "關閉LED1成功\r\n");
}
else if(strcmp(ptr, "BEEP OFF") == 0)
{
BEEP = 0;
printf("關閉BEEP\r\n");
send_data_to_usart3(netpro, "關閉BEEP成功\r\n");
}
else if(strcmp(ptr, "BEEP ON") == 0)
{
BEEP = 1;
printf("開啟BEEP\r\n");
send_data_to_usart3(netpro, "開啟BEEP成功\r\n");
}
else if(strcmp(ptr, "GET T&H") == 0)
{
DHT11_Read_Data(&temperature, &humidity); //讀取溫溼度值
sprintf(buf, "讀取,溫度:%d℃ 溼度:%d%%RH\r\n", temperature, humidity);
printf("%s", buf);
send_data_to_usart3(netpro, buf);
}
myfree(SRAMIN, ptr); // 釋放記憶體
}