實(shí)驗(yàn)內(nèi)容
本示例將演示如何在小凌派-RK2206開發(fā)板上使用WiFi-AP模式(即將RK2206作為WiFi路由器),實(shí)現(xiàn)與PC端進(jìn)行TCP通信。
程序設(shè)計(jì)
API設(shè)計(jì)
FlashInit()
頭文件:
//device/rockchip/rk2206/adapter/include/lz_hadware.h
函數(shù)描述:
unsigned int FlashInit(void);
作用描述:
初始化RK2206的Flash。
參數(shù)描述:
無
返回值:
LZ_HARDWARE_SUCCESS為成功,反之為失敗。
VendorSet()
頭文件:
//device/rockchip/rk2206/adapter/include/lz_hadware.h
實(shí)際定義在:
//device/rockchip/rk2206/adapter/include/lz_hardware/vendor.h
函數(shù)描述:
unsigned int VendorSet(VendorID id, unsigned char *buf, int len);
作用描述:
在Flash區(qū)域中設(shè)置WiFi相關(guān)參數(shù)。
參數(shù)描述:
名字 | 描述 |
---|---|
id | 配置的參數(shù),例如:VENDOR_ID_WIFI_SSID:設(shè)備作為終端,連接WiFi路由器的SSID,32字節(jié) + '\0'VENDOR_ID_WIFI_PASSWD:設(shè)備作為終端,連接WiFi路由器的密鑰,64字節(jié) + '\0'VENDOR_ID_WIFI_ROUTE_SSID:設(shè)備作為WiFi路由器,配置SSID,32字節(jié) + '\0'VENDOR_ID_WIFI_ROUTE_PASSWD:設(shè)備作為WiFi路由器,配置密鑰,64字節(jié) + '\0'VENDOR_ID_WIFI_MODE:配置設(shè)備作為終端或WiFi路由器,3字節(jié) + '\0' |
buf | 配置內(nèi)容字符串 |
len | 配置內(nèi)容字符串長度 |
返回值:
LZ_HARDWARE_SUCCESS為成功,反之為失敗。
SetApModeOff()
頭文件:
/device/rockchip/rk2206/sdk_liteos/board/include/config_network.h
函數(shù)描述:
WifiErrorCode SetApModeOff();
作用描述:
關(guān)閉WiFi-AP模式。
參數(shù)描述:
無
返回值:
0為成功,反之為失敗。
SetApModeOn()
頭文件:
/device/rockchip/rk2206/sdk_liteos/board/include/config_network.h
函數(shù)描述:
WifiErrorCode SetApModeOn();
作用描述:
開啟WiFi-AP模式。
參數(shù)描述:
無
返回值:
0為成功,反之為失敗。
軟件設(shè)計(jì)
整個(gè)例程主要分為2個(gè)部分:
配置RK2206為WiFi-AP模式
創(chuàng)建TCP服務(wù)端,監(jiān)聽并等待TCP客戶端
配置WiFi-AP模式
該任務(wù)主要分為如下幾個(gè)步驟:
(1)配置WiFi相關(guān)參數(shù)
首先,定義幾個(gè)WiFi相關(guān)參數(shù),并予以賦值。
void wifi_process(void *args){ unsigned int threadID_client, threadID_server; unsigned int ret = LOS_OK; WifiLinkedInfo info; uint8_t wifi_mode[4]; // 注意:wifi_mode字符串長度為4, 不能超過4 uint8_t mac_address[6]; // 注意:mac_address字符串長度為6, 不能超過6 uint8_t route_ssid[WIFI_MAX_SSID_LEN]; // config_network.h有定義該宏定義 uint8_t route_passwd[WIFI_MAX_KEY_LEN]; // config_network.h有定義該宏定義
// 配置WiFi模式字符串 memset(wifi_mode, 0, sizeof(wifi_mode)); snprintf(wifi_mode, sizeof(wifi_mode), "AP"); // 配置MAC地址字符串 memset(mac_address, 0, sizeof(mac_address)); mac_address[0] = 0x00; mac_address[1] = 0xdc; mac_address[2] = 0xb6; mac_address[3] = 0x90; mac_address[4] = 0x11; mac_address[5] = 0x00; // 配置route_ssid和route_passwd memset(route_ssid, 0, WIFI_MAX_SSID_LEN); snprintf(route_ssid, sizeof(route_ssid), WIFI_SSID); memset(route_passwd, 0, WIFI_MAX_KEY_LEN); snprintf(route_passwd, sizeof(route_passwd), WIFI_PASSWORD); ......}
注意:上述wifi_mode、mac_address、route_ssid和route_passwd都有嚴(yán)格的字符串長度定義。
(2)寫入Flash
將之前定義好的WiFi相關(guān)參數(shù)寫入到Flash。
void wifi_process(void *args){ ........ // Flash初始化 FlashInit(); // 配置RK2206為WiFi-AP模式,并設(shè)置WiFi路由器的SSID和密碼 VendorSet(VENDOR_ID_WIFI_MODE, wifi_mode, sizeof(wifi_mode)); // 配置為Wifi AP模式 VendorSet(VENDOR_ID_MAC, mac_address, sizeof(mac_address)); // 配置MAC地址 VendorSet(VENDOR_ID_WIFI_SSID, route_ssid, sizeof(route_ssid)); // 配置WiFi路由器的SSID VendorSet(VENDOR_ID_WIFI_PASSWD, route_passwd, sizeof(route_passwd)); // 配置WiFi路由器的密碼 ......}
注意:
在調(diào)用VendorSet()之前必須調(diào)用FlashInit(),初始化Flash相關(guān)操作,否則VendorSet()無效。
VendorSet()第1個(gè)參數(shù)在vendor.h有定義。
(3)重啟WiFi-AP模式
void wifi_process(void *args){ ........ // 開啟WiFi-AP模式 SetApModeOff(); SetApModeOn(); ......}
TCP服務(wù)端
首先,在wifi_process()調(diào)用CreateThread()創(chuàng)建1個(gè)線程,運(yùn)行wifi_tcp_server()
void wifi_process(void *args){ ........ // 創(chuàng)建TCP服務(wù)端線程 CreateThread(&threadID_server, wifi_tcp_server, NULL, "tcp_server");}
其次,運(yùn)行TCP服務(wù)端,綁定IP地址和端口號,監(jiān)聽端口,等待TCP客戶端連接
int wifi_tcp_server(void *arg){ int server_fd, ret;
while (1) { server_fd = socket(AF_INET, SOCK_STREAM, 0); // AF_INET:IPV4;SOCK_STREAM:TCP // server_fd = lwip_socket(AF_INET, SOCK_STREAM, 0); //AF_INET:IPV4;SOCK_STREAM:TCP if (server_fd < 0) { printf("create socket fail!\n"); return -1; }
/*設(shè)置調(diào)用close(socket)后,仍可繼續(xù)重用該socket。調(diào)用close(socket)一般不會(huì)立即關(guān)閉socket,而經(jīng)歷TIME_WAIT的過程。*/ int flag = 1; ret = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int)); if (ret != 0) { printf("[CommInitTcpServer]setsockopt fail, ret[%d]!\n", ret); }
struct sockaddr_in serv_addr = {0}; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); // IP地址,需要進(jìn)行網(wǎng)絡(luò)序轉(zhuǎn)換,INADDR_ANY:本地地址 // serv_addr.sin_addr.s_addr = inet_addr(OC_SERVER_IP); //IP地址,需要進(jìn)行網(wǎng)絡(luò)序轉(zhuǎn)換,INADDR_ANY:本地地址 serv_addr.sin_port = htons(SERVER_PORT); // 端口號,需要網(wǎng)絡(luò)序轉(zhuǎn)換 /* 綁定服務(wù)器地址結(jié)構(gòu) */ ret = bind(server_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); // ret = lwip_bind(server_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); if (ret < 0) { printf("socket bind fail!\n"); lwip_close(server_fd); return -1; } /* 監(jiān)聽socket 此處不阻塞 */ ret = listen(server_fd, 64); // ret = lwip_listen(server_fd, 64); if (ret != 0) { printf("socket listen fail!\n"); lwip_close(server_fd); return -1; } printf("[tcp server] listen:%d<%s:%d>\n", server_fd, inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port)); tcp_server_msg_handle(server_fd); // 處理接收到的數(shù)據(jù) LOS_Msleep(1000); }}
最后,tcp_server_msg_handle()負(fù)責(zé)與TCP客戶端進(jìn)行實(shí)際通信。
void tcp_server_msg_handle(int fd){ char buf[BUFF_LEN]; socklen_t client_addr_len; int cnt = 0, count; int client_fd; struct sockaddr_in client_addr = {0};
printf("waitting for client connect...\n"); /* 監(jiān)聽socket 此處會(huì)阻塞 */ client_fd = accept(fd, (struct sockaddr *)&client_addr, &client_addr_len); // client_fd = lwip_accept(fd, (struct sockaddr*)&client_addr, &client_addr_len); printf("[tcp server] accept <%s:%d>\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); while (1) { memset(buf, 0, BUFF_LEN); printf("-------------------------------------------------------\n"); printf("[tcp server] waitting client msg\n"); count = recv(client_fd, buf, BUFF_LEN, 0); // read是阻塞函數(shù),沒有數(shù)據(jù)就一直阻塞 // count = lwip_read(client_fd, buf, BUFF_LEN); //read是阻塞函數(shù),沒有數(shù)據(jù)就一直阻塞 if (count == -1) { printf("[tcp server] recieve data fail!\n"); LOS_Msleep(3000); break; } printf("[tcp server] rev client msg:%s\n", buf); memset(buf, 0, BUFF_LEN); sprintf(buf, "I have recieved %d bytes data! recieved cnt:%d", count, ++cnt); printf("[tcp server] send msg:%s\n", buf); send(client_fd, buf, strlen(buf), 0); // 發(fā)送信息給client // lwip_write(client_fd, buf, strlen(buf)); //發(fā)送信息給client } lwip_close(client_fd); lwip_close(fd);}
編譯調(diào)試
修改BUILD.gn文件
修改 vendor/lockzhiner/rk2206/sample 路徑下 BUILD.gn 文件,指定 wifi_ap_example 參與編譯。
"./b14_wifi_ap:wifi_ap_example",
修改 device/lockzhiner/rk2206/sdk_liteos 路徑下 Makefile 文件,添加 -lwifi_ap_example 參與編譯。
app_LIBS = -lwifi_ap_example
運(yùn)行結(jié)果
示例代碼編譯燒錄代碼后,按下開發(fā)板的RESET按鍵,通過串口助手查看日志,顯示如下:
entering kernel init...hilog will init.[IOT:D]IotInit: start ....[MAIN:D]Main: LOS_Start ...Entering scheduler[IOT:D]IotProcess: start ....wifi_ap_example start ....[FLASH:I]FlashInit: blockSize 4096, blockStart 0, blockEnd 8388608[config_network:D]rknetwork SetApModeOff start ...
[config_network:D]rknetwork AP is inactive
[config_network:D]rknetwork SetApModeOff end ...
[config_network:D]rknetwork SetApModeOn start ...
[FLASH:E]FlashInit: id 0, controller has already been initialized[config_network:D]rknetwork EnableHotspot ...
[wifi_api:D]ip=192.168.2.10 gw=192.168.2.1 mask=255.255.255.0[wifi_api:D]HWADDR (00b611:00)[bcore_device:E]start bb ...[bcore_device:E]start bb done[wifi_api:D]netif setup ...[wifi_api_internal:D]Start AP (SSID=rk2206_nano channel=1)[wifi_api_internal:D]derive psk ...[wifi_api_internal:D]derive psk done[wifi_dhcp:D]lann_ipaddr:192.168.2.1[wifi_dhcp:D]lann_mask:255.255.255.0[config_network:D]rknetwork EnableHotspot done[tcp server] listen:50<0.0.0.0:6666>waitting for client connect...
注意:設(shè)備WiFi路由器IP地址為192.168.2.10。
-
通信
+關(guān)注
關(guān)注
18文章
5969瀏覽量
135850 -
操作系統(tǒng)
+關(guān)注
關(guān)注
37文章
6737瀏覽量
123190 -
OpenHarmony
+關(guān)注
關(guān)注
25文章
3658瀏覽量
16144
發(fā)布評論請先 登錄
相關(guān)推薦
評論