本程序所用的单片机型号为:STM32F103RE
PB12端口为外接的WiFi模块电源开关,当PB12输出低电平时接通电源。WiFi模块的电源引脚VCC不可直接连接到电源上,必须要串联一组PNP三极管(或场效应管),并把基极接到PB12端口上,基极要接限流电阻。
注意:WM-G-MR-09模块的芯片组(Chip Set)就是Marvell 88W8686。
Keil5工程下载地址:
https://pan.baidu.com/s/1oRABiuKBG9m7P8E0fhc8NA
代码说明:
http://blog.csdn.net/ZLK1214/article/details/79278871
Windows下根据计算机名获取IP地址的C语言程序:
http://blog.csdn.net/ZLK1214/article/details/79595245
STM32F103RE单片机利用外部中断和DMA获取OV2640摄像头拍摄的照片,并通过串口发送到电脑上的程序:
https://blog.csdn.net/zlk1214/article/details/79559466
lwip2.0.3协议栈的无操作系统移植过程:
https://blog.csdn.net/ZLK1214/article/details/80957863
工程下载之后,请一定要将路径中的中文去掉,否则Keil5有可能错误地提示打不开stm32f10x.h头文件,但工程能正常编译。
lwip协议栈本身只包含DHCP客户端,Ad hoc模式下可以用lwDHCP创建DHCP服务器:
http://savannah.nongnu.org/projects/lwdhcp
此版本修复了上一个版本(
20180312版)存在的一些问题,主要更新如下:
1. 添加了扫描热点时显示路由器速率的功能
2. 添加了显示收到的数据帧的信噪比(SNR)、噪声基底(Noise Floor)、优先级和速率的功能(WIFI_DISPLAY_PACKET_RXRATES选项)
3. 解决了WPA/WPA2认证时多次收到第三次握手包导致多次调用WiFi_AuthenticationCompleteHandler回调函数的问题
4. 将数据帧最大发送速率改为了54Mbps, 更新了WIFI_DEFAULT_TIMEOUT_CMDACK和WIFI_DEFAULT_TIMEOUT_DATAACK的值
5. 修复了DHCP长时间获取不到IP地址的问题
6. 添加了TCP、UDP速度测试功能
7. 修复了部分路由器上Group key handshake失败导致掉线的问题(但仍有部分路由器还有此问题)
8. 增大了WiFi模块复位的时间, 避免在WiFi_ShowCIS函数中陷入死循环
10. 增加了wifi_buffer_rx缓冲溢出检查功能,溢出时自动丢弃待接收数据,不影响后续数据的接收
11. 修复了sys_now()溢出导致超时重传判断失效的问题
修改的文件:ethernetif.c, WiFi.c, WiFi.h, common.c, common.h, main.c, WiFi_LowLevel.c
【勘误】
2018年7月8日:common.c中有一个宏RTC_USELSI。请确保单片机使用的RTC时钟源和该宏定义匹配,否则程序运行时会出问题。可以用下面的代码进行检测,时钟源不匹配时自动复位RTC。该代码应该放在rtc_init函数中PWR_BackupAccessCmd的下一排。
if (RCC->BDCR & RCC_BDCR_RTCEN)
{
#ifdef RTC_USELSI
if ((RCC->BDCR & RCC_BDCR_RTCSEL) != RCC_RTCCLKSource_LSI)
#else
if ((RCC->BDCR & RCC_BDCR_RTCSEL) != RCC_RTCCLKSource_LSE)
#endif
{
printf("RTC is already running and the clock source doesn't match RTC_USELSI!
");
printf("Reset RTC!
");
RCC_BackupResetCmd(ENABLE);
RCC_BackupResetCmd(DISABLE);
}
}
2018年7月10日:WiFi.c中,WiFi_KeyMaterial函数里面for循环内给key[i].header.length赋值的那句话,key->key_len应该改为key[i].key_len才对。
key[i].header.length = sizeof(MrvlIETypes_KeyParamSet_t) - sizeof(key[i].header) - sizeof(key[i].key) + key[i].key_len;
2018年7月22日:WiFi_SendCommand函数中,memmove那一行应该改为:
memmove(wifi_buffer_command, data, (size != 0) ? size : ((WiFi_SDIOFrameHeader *)data)->length);
否则当参数data!=NULL且data!=wifi_buffer_command且size=0时,函数不能正常工作。
2018年8月1日:测速器上位机程序中,network.c里面的network_find_ip函数中,freeaddrinfo函数调用的位置不对,因为传入的参数info始终为NULL,应该传入的是getaddrinfo从第四个参数返回的值。正确的代码为(
https://blog.csdn.net/ZLK1214/article/details/79595245)中的方法二的代码
【补充说明】
程序中用netif_set_up和netif_set_down函数来通知lwip网卡是否已连上网,编写了一个set_netif函数来辅助打开/关闭DHCP,用netif_is_up函数判断网卡是否已连上网。其实这并不是很合适。因为lwip的netif_set_up/netif_set_down函数(对应NETIF_FLAG_UP标志)决定的是网卡是“已启用”还是“已禁用”,并不是用来通知网卡是否已连上网的。通知网卡是否连上网的函数是netif_set_link_up和netif_set_link_down(对应NETIF_FLAG_LINK_UP标志),这两个函数里面会自动通知DHCP网络发生了变化(dhcp_network_changed)。这时,程序中可以用netif_is_link_up函数判断是否已连上网。
具体修改:
(1) low_level_init函数中netif->flags去掉NETIF_FLAG_LINK_UP(默认情况下无线网卡是没有连上网的)
(2) mac_address_callback函数中netif_set_default后面加上netif_set_up(&wifi_88w8686);(无线网卡在lwip中始终是“启用”状态)
(3) set_netif修改为:
static void set_netif(struct netif *netif, uint8_t up)
{
if (up)
{
netif_set_link_up(netif); // 该函数会通知DHCP网络发生了变化
// DHCP需要在网卡第一次连上网的时候手动启用
#if LWIP_DHCP
if (netif_dhcp_data(netif) == NULL)
dhcp_start(netif); // 路由器中显示的DHCP客户名称在ethernetif_init函数中设置
#endif
}
else
netif_set_link_down(netif);
}
Wi-Fi模块电源引脚的连接方法:
程序支持连接无密码的热点以及WEP、WPA-PSK和WPA2-PSK认证类型的热点,加密方式支持TKIP和AES。
支持创建无密码或是带有WEP密码的ADHOC热点,ADHOC模式下不支持WPA和WPA2!
注意:虽然SDIO标准规定可以总线上可以接多张SD卡,但STM32单片机的SDIO接口只支持接一张卡,STM32F103芯片手册Datasheet(不是参考手册)中有声明:
The current version supports only one SD/SDIO/MMC4.2 card at any one time and a stack of MMC4.1 or previous.
如果想要同时使用WiFi模块和SD内存卡,建议SD内存卡采用SPI总线通信。
【程序运行截图】
连上路由器后DHCP分配得到IP地址:
下面是把WiFi模块固件写入单片机芯片Flash固定区域的程序(用于减少调试主程序时下载程序的时间)的运行结果:
’
电脑上ping IP地址和计算机名:
通过计算机名在电脑上访问开发板上的HTTP服务器(lwip自带的httpd):
TCP/UDP测速结果(测速软件位于压缩包内,附C语言源代码):
【程序运行结果(连接WPA2路由器)】
STM32F103RE SDIO 88W8686
RESPCMD63, RESP1_90ff8000
RESPCMD63, RESP1_90300000
Number of I/O Functions: 1
Memory Present: 0
Relative Card Address: 0x0001
Card selected! RESP1_00001e00
SDIO Clock: 24MHz
[CIS] func=0, ptr=0x00008000
Product Information: Marvell 802.11 SDIO ID: 0B
Manufacturer Code: 0x02df
Manufacturer Information: 0x9103
Card Function Code: 0x0c
System Initialization Bit Mask: 0x00
Maximum Block Size: 256
Maximum Transfer Rate Code: 0x32
[CIS] func=1, ptr=0x00008080
Card Function Code: 0x0c
System Initialization Bit Mask: 0x00
Maximum Block Size: 256
Firmware is successfully downloaded!
MAC Addr: 00:1A:6B:A4:AA:B4
SSID '10507', MAC B0:95:8E:04:2A:06, RSSI 51, Channel 6
Capability: 0x0431 (Security: WPA2, Mode: Infrastructure)
Rates: 1.0Mbps 2.0Mbps 5.5Mbps 11.0Mbps 6.0Mbps 9.0Mbps 12.0Mbps 18.0Mbps
SSID 'TP_LINK_PLC', MAC 30:FC:68:38:6E:2C, RSSI 71, Channel 6
Capability: 0x0031 (Security: WPA2, Mode: Infrastructure)
Rates: 1.0Mbps 2.0Mbps 5.5Mbps 11.0Mbps 6.0Mbps 9.0Mbps 12.0Mbps 18.0Mbps
SSID 'CDU', MAC D4:61:FE:71:36:D0, RSSI 78, Channel 6
Capability: 0x8421 (Security: Unsecured, Mode: Infrastructure)
Rates: 1.0Mbps 2.0Mbps 5.5Mbps 6.0Mbps 9.0Mbps 11.0Mbps 12.0Mbps 18.0Mbps
SSID 'xgxy666', MAC DC:FE:18:67:76:14, RSSI 77, Channel 6
Capability: 0x0031 (Security: WPA2, Mode: Infrastructure)
Rates: 1.0Mbps 2.0Mbps 5.5Mbps 11.0Mbps 6.0Mbps 9.0Mbps 12.0Mbps 18.0Mbps
SSID 'DWYHX', MAC 48:7D:2E:19:88:9D, RSSI 76, Channel 6
Capability: 0x0031 (Security: WPA2, Mode: Infrastructure)
Rates: 1.0Mbps 2.0Mbps 5.5Mbps 11.0Mbps 6.0Mbps 9.0Mbps 12.0Mbps 18.0Mbps
SSID 'TP-LINK_ORANGE', MAC B0:95:8E:05:82:CA, RSSI 58, Channel 11
Capability: 0x0431 (Security: WPA2, Mode: Infrastructure)
Rates: 1.0Mbps 2.0Mbps 5.5Mbps 11.0Mbps 6.0Mbps 9.0Mbps 12.0Mbps 18.0Mbps
SSID '', MAC D6:14:4B:6F:A6:0F, RSSI 68, Channel 11
Capability: 0x0621 (Security: Unsecured, Mode: Infrastructure)
Rates: 1.0Mbps 2.0Mbps 5.5Mbps 11.0Mbps 18.0Mbps 24.0Mbps 36.0Mbps 54.0Mbps
SSID 'CMCC-EDU', MAC D6:14:4B:6F:A6:0E, RSSI 68, Channel 11
Capability: 0x0621 (Security: Unsecured, Mode: Infrastructure)
Rates: 1.0Mbps 2.0Mbps 5.5Mbps 11.0Mbps 18.0Mbps 24.0Mbps 36.0Mbps 54.0Mbps
SSID 'TP-LINK_5B8E', MAC 50:FA:84:53:5B:8E, RSSI 75, Channel 12
Capability: 0x0401 (Security: Unsecured, Mode: Infrastructure)
Rates: 1.0Mbps 2.0Mbps 5.5Mbps 11.0Mbps 9.0Mbps 18.0Mbps 36.0Mbps 54.0Mbps
Scan finished!
Waiting for authentication!
Message 1 received!
Message 2 sent!
Message 3 received!
Message 4 sent!
Authenticated!
[Send] len=350
PTK & GTK set!
[Recv] len=316
[Send] len=350
[Recv] len=316
[Send] len=42
[Send] len=42
[Send] len=42
DHCP supplied address!
IP address: 192.168.1.115
Subnet mask: 255.255.255.0
Default gateway: 192.168.1.1
DNS Server: 192.168.1.1
[Send] len=42
Not in cache! err=-5
[Recv] len=42
[Send] len=76
[Recv] len=235
DNS Found IP: 106.186.126.193
Connecting to 106.186.126.193...
[Send] len=58
[Send] len=42
[Recv] len=58
Connected! err=0
Connection is successfully closed!
[Send] len=54
[Recv] len=54
[Send] len=54
[Send] len=42
[Send] len=42
[Send] len=42
[Recv] len=159
[Recv] len=92
[Send] len=42
[Send] len=42
[Recv] len=42
[Send] len=104
[Recv] len=42
[Recv] len=42
[Send] len=42
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Send] len=590
[Recv] len=54
[Send] len=304
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=54
[Recv] len=355
[Send] len=590
[Send] len=349
[Recv] len=54
[Send] len=54
[Recv] len=54
[Recv] len=54
[Recv] len=54
[Send] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Send] len=590
[Recv] len=54
[Send] len=304
[Recv] len=54
[Recv] len=54
[Recv] len=54
[Send] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=355
[Send] len=590
[Send] len=349
[Recv] len=54
[Recv] len=54
[Recv] len=54
[Send] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Send] len=590
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Recv] len=54
[Send] len=590
[Recv] len=355
[Send] len=590
[Send] len=349
[Recv] len=54
[Recv] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Send] len=590
[Recv] len=54
[Send] len=54
[Recv] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Send] len=590
[Recv] len=54
[Send] len=304
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Recv] len=54
[Send] len=590
[Recv] len=54
[Send] len=304
[Recv] len=355
[Send] len=590
[Send] len=349
[Recv] len=54
[Recv] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Send] len=590
[Recv] len=54
[Send] len=304
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Recv] len=54
[Send] len=590
[Recv] len=54
[Send] len=304
[Recv] len=355
[Send] len=590
[Send] len=349
[Recv] len=54
[Recv] len=54
[Recv] len=54
[Send] len=54
[Recv] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Send] len=590
[Recv] len=54
[Send] len=304
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=66
[Send] len=58
[Recv] len=54
[Send] len=590
[Recv] len=54
[Send] len=304
[Recv] len=54
[Recv] len=355
[Send] len=590
[Send] len=349
[Recv] len=54
[Recv] len=54
[Recv] len=54
[Recv] len=54
[Send] len=54
[Recv] len=54
[Send] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=66
[Send] len=58
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Recv] len=54
[Send] len=590
[Recv] len=54
[Send] len=304
[Recv] len=355
[Send] len=590
[Send] len=349
[Recv] len=54
[Recv] len=54
[Recv] len=54
[Send] len=54
[Recv] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Send] len=590
[Recv] len=54
[Send] len=304
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Send] len=590
[Recv] len=66
[Send] len=58
[Recv] len=54
[Send] len=304
[Recv] len=54
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Send] len=590
[Recv] len=54
[Send] len=304
[Recv] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Recv] len=54
[Send] len=54
[Recv] len=54
[Recv] len=300
[Send] len=590
[Send] len=590
[Recv] len=54
[Send] len=590
[Recv] len=66
[Send] len=58
[Recv] len=54
[Send] len=304
[Recv] len=54
[Recv] len=54
[Recv] len=355
[Send] len=590
[Send] len=349
[Recv] len=54
[Recv] len=54
[Send] len=54
[Recv] len=54
[Recv] len=54
[Recv] len=54
[Send] len=54
[Recv] len=66
[Send] len=58
[Recv] len=54
[Send] len=54
[Recv] len=54