模塊說明
W5500的廠商是韓國WIZnet, 特性如下
- 全硬件TCP/IP協議棧: TCP,UDP,ICMP,IPv4,ARP,IGMP,PPPoE -- 注意只有IPv4
- 支持SPI模式0,3, 最高80MHz SPI時鍾
- 8個獨立的硬件Socket, 各路通信互不影響
- 32K字節收發緩存, 可以靈活定義各個Socket的大小
- 集成802.3以太網MAC
- 集成10Base-T / 100Base-T以太網PHY
- 支持嵌入式操作系統:Linux & RTOS
- 支持掉電模式 & UDP網絡喚醒
- 工作電壓3.3V, I/O 5V耐壓
- 支持自動協商(全/半雙工, 10M/100M)
用起來比ENC28J60簡單多了, 不用費勁巴拉的套uIP, LWIP了.
在stm32f103c8t6上運行W5500
需要的組件
- STM32F103C8T6開發板
- W5500模塊
- USB2TTL: PL2303 or CH340 or FT232 or CP2102
- ST-Link or J-LInk
- 帶網口的路由器或交換機, 方便聯網測試
接線圖
這個示例中只需要用到SPI接口, RST和INT都是置空. PA9和PA10用來觀察log輸出
| W5500 | STM32 | USB2TTL |
|---|---|---|
| GND | GND | GND |
| VCC | 3.3V | |
| RST | ||
| INT | ||
| SCS | PA0 | |
| CLK | PA5 | |
| MISO | PA6 | |
| MOSI | PA7 | |
| PA9 | RX | |
| PA10 | TX |
運行和代碼說明
代碼地址
https://github.com/IOsetting/stm32f103-w5500
代碼說明
基於官方的代碼庫: https://github.com/Wiznet/ioLibrary_Driver
現在淘寶商家給的代碼示例, 以及網絡上搜到的W5500項目, 代碼大都是非官方的實現(或者是從官方早期某個版本修改而來), 運行在F103Vxx或者F103Rxx的板子上是正常的, 但是換到F103C8xx板子上就會有問題, 而且不好修改.
建議基於官方Github上的庫做開發.
- WIKI: https://wizwiki.net/wiki/doku.php/products:w5500:driver
- 關於讀取是使用中斷還是寄存器的討論: https://forum.wiznet.io/t/topic/4407/4
接收數據
Use getSn_RX_RSR(sn): Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer.
Some interesting reading:
uint16_t getSn_RX_RSR(uint8_t sn)
{
uint16_t val=0,val1=0;
do {
val1 = WIZCHIP_READ(Sn_RX_RSR(sn));
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
if (val1 != 0) {
val = WIZCHIP_READ(Sn_RX_RSR(sn));
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
}
} while (val != val1);
return val;
}
In this method, RX_RSR was read twice in each iteration till the values are the same. This is to avoid the problem described in UDP header seems to contain the expected size, but the RX_RSR value is much smaller
Read all data if the length exceeds your buffer size:
if((size = getSn_RX_RSR(sn)) > 0) { // Sn_RX_RSR: Socket n Received Size Register, Receiving data length
if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE; // DATA_BUF_SIZE means user defined buffer size (array)
ret = recv(sn, buf, size); // Data Receive process (H/W Rx socket buffer -> User's buffer)
if(ret <= 0) return ret; // If the received data length <= 0, receive failed and process end
size = (uint16_t) ret;
// Add code here to handle the data
}
發送數據
uint16_t sentsize = 0;
while(size != sentsize) {
ret = send(sn, buf+sentsize, size-sentsize); // Data send process (User's buffer -> Destination through H/W Tx socket buffer)
if(ret < 0) { // Send Error occurred (sent data length < 0)
close(sn); // socket close
return ret;
}
sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
}
配置 MAC, IP, Mask, Gateway and Remote Server IP
編輯 main.c, 在下面的代碼中進行修改
void Load_Net_Parameters(void)
{
gWIZNETINFO.gw[0] = 192; //Gateway
gWIZNETINFO.gw[1] = 168;
gWIZNETINFO.gw[2] = 1;
gWIZNETINFO.gw[3] = 1;
gWIZNETINFO.sn[0]=255; //Mask
gWIZNETINFO.sn[1]=255;
gWIZNETINFO.sn[2]=255;
gWIZNETINFO.sn[3]=0;
gWIZNETINFO.mac[0]=0x0c; //MAC
gWIZNETINFO.mac[1]=0x29;
gWIZNETINFO.mac[2]=0xab;
gWIZNETINFO.mac[3]=0x7c;
gWIZNETINFO.mac[4]=0x00;
gWIZNETINFO.mac[5]=0x01;
gWIZNETINFO.ip[0]=192; //IP
gWIZNETINFO.ip[1]=168;
gWIZNETINFO.ip[2]=1;
gWIZNETINFO.ip[3]=204;
gWIZNETINFO.dhcp = NETINFO_STATIC;
}
uint8_t destip[4] = {192, 168, 1, 210};
uint16_t destport = 3333;
輸出日志
在編譯參數中增加 _DHCP_DEBUG_ and _LOOPBACK_DEBUG_ 將在UART1中輸出日志.
編譯
包含路徑
..\libraries\CMSIS\CM3\CoreSupport;..\libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x;..\libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm;..\libraries\STM32F10x_StdPeriph_Driver\inc;..\hardware;..\user
產生的編譯控制字符串
--c99 --gnu -c --cpu Cortex-M3 -D__MICROLIB -g -O0 --apcs=interwork --split_sections -I ../libraries/CMSIS/CM3/CoreSupport -I ../libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x -I ../libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/arm -I ../libraries/STM32F10x_StdPeriph_Driver/inc -I ../hardware -I ../user
-I./RTE/_stm32f103c8w5500
-IC:/Keil_v5/ARM/PACK/Keil/STM32F1xx_DFP/2.3.0/Device/Include
-IC:/Keil_v5/ARM/CMSIS/Include
-D__UVISION_VERSION="525" -DSTM32F10X_MD -DUSE_STDPERIPH_DRIVER -D_DHCP_DEBUG_ -D_LOOPBACK_DEBUG_
-o .\Objects\*.o --omf_browse .\Objects\*.crf --depend .\Objects\*.d
燒錄
使用 ST-Link 將代碼寫入開發板
ST-Link 和 STM32F103C8T6 開發板的連接方式
G -- GND
CLK -- SWCLK
IO -- SWDIO
V3 -- 3.3V
測試
- Ping test: Ping the IP address you defined in main.c
- TCP client test: Run
nc -l 3333to listen port 3333 on server IP, and restart stm32 board
