上一節說的是ESP8266的station模式,但這個模式講的比較枯燥,既沒有實作什麼酷炫的應用,也沒有引申出什麼好玩的功能。别急,我想想…
這一節先看看ESP8266的UDP通訊,主要看它的廣播模式。說這個,需要先了解UDP通訊是什麼?
說到UDP,伴随而來的還有另一個東西,就是TCP。這裡不說定義,隻說應用。簡單來說,這兩者都是網絡通信中常用的通信協定。
最主要的差別,TCP通訊比較穩定,它和接收端要進行三次握手,接收端有沒有收到資料,都能知道。優點是安全,缺點是和UDP相比,速度慢。
UDP在發送時,不管有沒有接收方,也不管接收方有沒有收到,隻要把資料發出去,就完了。是以,相比TCP,安全性差一些,速度要快一些。
但并不是說安全性差,就不能用,像視訊、音頻等一些無關緊要的資料,都可以用UDP來進行傳輸。
UDP包的最大長度是多少?
65535個位元組。但是除掉IP頭(20位元組)和UDP頭(8位元組)之後,剩餘65507個位元組。
UDP如何廣播?
IP 255.255.255.255 為廣播位址,往這個位址發資料,區域網路中的所有機器都可以收到。
對UDP有一個基本了解之後,咱們來進行ESP8266的UDP廣播。本節程式是在上一節程式基礎上修改的,是以如果你上一節看懂了,這一節是很簡單的。使用步驟多一點,但是并不麻煩,分為6步。
1包含頭檔案
#include "espconn.h"
#include "mem.h"
主要是"espconn.h",涉及到UDP通訊所需的各種資料結構。
2設定工作模式及相關參數
wifi_set_opmode(0x03); // station+ soft-ap模式
struct softap_config config; //定義AP參數結構體,
wifi_softap_get_config(&config); //擷取目前AP模式的參數
os_memcpy(config.ssid,"ESP8266",strlen("ESP8266")); //修改AP名稱
os_memcpy(config.password,"123456789",strlen("123456789")); //修改AP密碼
config.ssid_len=strlen("ESP8266"); //修改 AP名稱的長度
wifi_softap_set_config(&config); //使修改後的參數生效
此時,如果把程式燒錄進去,可以看到目前環境下有一個ESP8266的wifi,輸入密碼“123456789”可以連接配接。
3掃描并連接配接目前環境下的wifi
跟上一節一樣,掃描目前環境下的wifi,并進行連接配接。我這裡連接配接我家裡的“shatanliu”,你要改成你自己的。
4連接配接成功後,設定UDP相關參數
跟上一節相比,這裡要對Wifi_conned();進行修改。
首先頭檔案中定義一個結構體形式的ESPCONN描述符:
struct espconn user_udp_espconn;
關于espconn,SDK中給出的定義如下:
struct espconn {
enum espconn_type type;
enum espconn_state state;
union {
esp_tcp *tcp;
esp_udp *udp;
} proto;
espconn_recv_callback recv_callback;
espconn_sent_callback sent_callback;
uint8 link_cnt;
void *reverse;
};
可以看到,無論是TCP通訊還是UDP通訊,都要用到這個結構體,同時,要在結構體内設定相應的發送、接收回調函數。
接下來就是一個UDP參數的設定過程:
wifi_set_broadcast_if(STATIONAP_MODE);
設定UDP廣播包的發送接口,預設soft-ap。這裡選擇的是station和soft-ap。
參數:1、station 2、soft-ap 3、station和soft-ap
user_udp_espconn.type=ESPCONN_UDP; //設定為UDP通信 //開辟UDP參數需要的空間 user_udp_espconn.proto.udp=(esp_udp *)os_zalloc(sizeof(esp_udp)); //設定本地端口和遠端端口 user_udp_espconn.proto.udp->local_port=2525; user_udp_espconn.proto.udp->remote_port=1024; //設定遠端IP const char udp_remote_ip[4]={255,255,255,255}; os_memcpy(user_udp_espconn.proto.udp->remote_ip,udp_remote_ip,4); //設定發送完成和接收完成的回調函數 espconn_regist_recvcb(&user_udp_espconn,user_udp_recv_cb); espconn_regist_sentcb(&user_udp_espconn,user_udp_sent_cb); //使UDP參數生效 espconn_create(&user_udp_espconn); //UDP發送函數 user_udp_send();5定義發送完成和接收完成的回調函數
void ICACHE_FLASH_ATTR user_udp_sent_cb(void *arg)
{
os_printf("SEND SUCCESS!\r\n"); os_timer_disarm(&test_timer); os_timer_setfn(&test_timer,(os_timer_func_t *)user_udp_send,0); os_timer_arm(&test_timer,1000,0);
}
序列槽列印:SEND SUCCESS! 然後延時1秒,調用UDP發送函數。
為什麼序列槽不發送中文?SDK3.0的版本,序列槽對中文的支援好像不太好,有興趣的自己試一下。
void ICACHE_FLASH_ATTR user_udp_recv_cb(void *arg,
char *pdata,
unsigned short len)
{
os_printf("udp have received data:%s\r\n",pdata);
}
把收到的資料,序列槽列印出來。
6定義UDP發送函數
void ICACHE_FLASH_ATTR user_udp_send(void)
{
char hwaddr[6];
char DeviceBuffer[40]={0};
wifi_get_macaddr(STATION_IF,hwaddr);
os_sprintf(DeviceBuffer,"DEVICE MAC ADDRESS IS:"MACSTR"!!\r\n
ESP8266 IOT!\r\n",MAC2STR(hwaddr));
espconn_send(&user_udp_espconn,DeviceBuffer,os_strlen(DeviceBuffer));
}
通過wifi_get_macaddr函數擷取station模式下的MAC位址,并通過espconn_sent函數列印出來。
函數定義
sint8 espconn_send(
struct espconn *espconn,
uint8 *psent,
uint16 length
)
參數:
struct espconn *espconn : 對應網絡傳輸的結構體
uint8 *psent : 發送的資料
uint16 length : 資料長度
程式修改完成,儲存、清理、編譯、下載下傳一條龍,然後重新上電。這裡,需要借助序列槽助手和網絡調試助手兩個工具來檢視效果。效果如下所示:

打開網絡調試助手:
如圖,依次設定相關的參數。
怎麼知道顯示的MAC位址對不對?打開路由器的管理界面,看目前連接配接裝置的MAC位址:
如此,說明發送端(路由下的8266)和接收端(路由下的PC)成功進行通信。
如果這時候網絡調試助手發送資料:hello。
序列槽助手會收到如下資訊:
至此,UDP廣播說完了。你們可以試一下讓目前電腦連接配接8266,看網絡調試助手裡的參數如何修改。
連結:https://pan.baidu.com/s/1ABs7hPbQuL8wWbAXX_fFqg
提取碼:psoz
ESP8266_前言
ESP8266_01搭建開發環境
ESP8266_02程式的編譯與下載下傳
ESP8266_03 SDK與Makefile的基本用法
ESP8266_04管腳控制與軟體定時器
ESP8266_05 ESP8266有幾個序列槽?
ESP8266_06硬體定時器與IO中斷
ESP8266_07基于PWM的呼吸燈
ESP8266_08基于flash的資料掉電保護
ESP8266_09基于IIC控制的OLED螢幕
ESP8266_10 ESP8266的STATION模式