1、WIZnet全硬件TCP/IP協議棧
WIZnet全硬件TCP/IP協議棧,支持TCP,UDP,IPv4,ICMP,ARP,IGMP以及PPPoE協議。
以太網:支持BSD和WIZCHIP(W5500/W5300/W5200/W5100/W5100S)的SOCKET APIs驅動程序。
互聯網:
DHCP客戶端
DNS客戶端
FTP客戶端
FTP服務器
SNMP代理/陷阱
SNTP客戶端
TFTP客戶端
HTTP服務器
MQTT客戶端
其他功能將陸續添加。
ioLibrary庫下載地址: https://gitcode.com/gh_mirrors/io/ioLibrary_Driver?utm_source=csdn_github_accelerator&isLogin=1
案例:項目首頁 - MINISTM32移植W5500ioLiberary:MINISTM32 移植W5500 ioLiberary項目為開發者提供了在MINISTM32平臺上移植W5500網絡芯片的完整解決方案。該項目包含移植所需的庫文件和示例代碼,幫助開發者快速上手并實現網絡通信功能。通過詳細的移植說明和步驟,開發者可以輕松完成配置和調試,節省開發時間。無論是初學者還是有經驗的工程師,都可以利用該項目在STM32F103RCT6平臺上高效集成W5500,實現穩定的網絡連接。項目資源豐富,文檔清晰,是嵌入式網絡開發的理想選擇。 - GitCode
internet文件夾
W5500文件夾
2、W5500芯片
W5500是一款全硬件TCP/IP以太網控制器。W5500集成了TCP/IP協議棧,10/100M以太網數據鏈路
層(MAC)及物理層(PHY),使得用戶使用單芯片就能夠在他們的應用中拓展網絡連接。
支持8個獨立端口(Socket)同時通訊,每一個 Socket 的發送 緩存區都在一個 16KB 的物理發送內存中,初始化分配為 2KB。每一個 Socket 的接收緩 存區都在一個 16KB 的物理接收內存中,初始化分配為 2KB。
W5500提供了SPI接口,最大支持80MHz速率,W5500支持SPI模式0和模式3。
3、配置使能W5500驅動
添加wizchip_conf.c,w5500.c和socket.c到工程中。打開wizchip_conf.H,找到_WIZCHIP_宏定義,修改如下:
?#ifndef _WIZCHIP_
? ?// NOTE_LIHAN: Some sections of this code are not yet fully defined.
? ?#define _WIZCHIP_ ? ? ? ? ? ? ? ? ? ? ?W5500 ? // W5100, W5100S, W5200, W5300, W5500, 6300
?? ? //將_WIZCHIP_宏設置為W5500,2025年5月15日修改
?#endif
4、添加SPI1驅動程序
//函數功能:
//初始化SPI1_SCL為PA5,SPI1_MISO為PA6,SPI1_MOSI為PA7,SPI1_CS為PA3;
//設置SPI1的工作模式
void W5500_SPI_Init(void)
{
?? ?GPIO_InitTypeDef ?? ?GPIO_InitStructure;
?? ?SPI_InitTypeDef ? SPI_InitStructure;
? RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA的外設時鐘
? RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); ?//使能SPI1的外設時鐘
? GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; ? ? ? ? //選擇PIN5,是SPI1的SCL
? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;?? ? ?//選擇引腳為復用推挽輸出
? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //設置引腳的最高工作速率為50MHz
? GPIO_Init(GPIOA, &GPIO_InitStructure); ?//根據GPIO_InitStructure結構指針所指向的參數配置PA5引腳?? ?
? GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; ? ? ? ? //選擇PIN6,是SPI1的MISO
?? ?GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;?? ? ?//選擇引腳為輸入懸浮
? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //設置引腳的最高工作速率為50MHz
? GPIO_Init(GPIOA, &GPIO_InitStructure); ?//根據GPIO_InitStructure結構指針所指向的參數配置PA6引腳
? GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; ? ? ? ? //選擇PIN7,是SPI1的MOSI
?? ?GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;?? ? ?//選擇引腳為復用推挽輸出
? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //設置引腳的最高工作速率為50MHz
? GPIO_Init(GPIOA, &GPIO_InitStructure); ?//根據GPIO_InitStructure結構指針所指向的參數配置PA7引腳
? GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; ? ? ? ? //選擇PIN3,是W5500的片選腳CS
? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; ?//選擇引腳為推挽輸出
?? ?GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //設置引腳的最高工作速率為50MHz
? GPIO_Init(GPIOA, &GPIO_InitStructure); ?//根據GPIO_InitStructure結構指針所指向的參數配置PA3引腳
//設置SPI1的工作模式
? SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
?? ?//SPI設置為雙線雙向全雙工
? SPI_InitStructure.SPI_Mode = SPI_Mode_Master; ? ? //設置為主SPI
? SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //設置SPI發送接收為8位幀結構
? SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; ? ? ? ?//設置SCK空閑時鐘為低電平
? SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; ? ? ?//數據捕獲于第1個時鐘沿
?? ?//SCK空閑時鐘為低電平,數據捕獲于第1個時鐘沿,這樣就設置了SPI從機在下降沿采集數據了
?? ?//SPI從機在下降沿采集數據,這要求CPU必須在SCK上升沿輸出位值,在SCK為高電平時達到穩定,為數據采集做好準備
? SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; ?//設置NSS輸出由SSI位控制
? SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
?? ?//設置波特率預分頻值為2
? SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; ?//設置數據傳輸先從MSB位開始
? SPI_InitStructure.SPI_CRCPolynomial = 7; ? ? ? ? ? ?//使用CRC7校驗
? SPI_Init(SPI1, &SPI_InitStructure);
? SPI_Cmd(SPI1, ENABLE); //使能SPI外設
}
#define?? ?W5500_CS_high() ? GPIO_SetBits(GPIOA,GPIO_Pin_4) ? //W5500片選引腳
#define?? ?W5500_CS_low() ? ?GPIO_ResetBits(GPIOA,GPIO_Pin_4) //W5500片選引腳
//函數功能:選擇W5500
void SPI_CS_Select(void)
{
?? ?W5500_CS_low();
}
//函數功能:不選擇W5500
void SPI_CS_Deselect(void)
{
?? ?W5500_CS_high();
}
//函數功能:從W5500讀取一個字節
uint8_t SPI_ReadByte(void)
{
?? ?uint8_t byte;
?? ?byte=SPI_I2S_ReceiveData(SPI1);//虛讀一次
?? ?SPI_I2S_SendData(SPI1,0x00);//通過外設SPI1發送0x00為的是發送8個移位時鐘
?? ?while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
?? ?//檢查SPI1標志位,是否設置"發送緩存空標志位",等待數據寄存器空
?? ?byte=SPI_I2S_ReceiveData(SPI1);//讀取1個字節數據
?? ?return byte;
}
//函數功能:將byte發送給W5500
void SPI_WriteByte(uint8_t byte)
{
?? ?SPI_I2S_SendData(SPI1,byte);//通過外設SPI1發送一個數據
?? ?while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
?? ?//檢查SPI1標志位,是否設置"發送緩存空標志位",等待數據寄存器空
}
//函數功能:關閉總中斷
void SPI_CrisEnter(void)
{
?? ?__set_PRIMASK(1);//關閉總中斷
}
//函數功能:使能總中斷
void SPI_CrisExit(void)
{
?? ?__set_PRIMASK(0);//開放總中斷
}
5、TCP客戶端應用程序W5500_HD_Driver.c
#include "W5500_HD_Driver.h"
#include "stdio.h" //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "socket.h" // Just include one header for WIZCHIP
#include "SPI1.h"//下載地址: https://gitcode.com/gh_mirrors/io/ioLibrary_Driver?utm_source=csdn_github_accelerator&isLogin=1
//W5500的網絡參數
//本地物理地址:00 08 DC 11 11 11
//本地IP地址:192.168.1.199
//本地子網掩碼: 255.255.255.0
//本地網關:192.168.1.1
//DNS服務器IP地址:8.8.8.8
//通過手動配置靜態IP地址,Static IP configuration by manually.
wiz_NetInfo gWIZNETINFO = { {0x00, 0x08, 0xdc,0x11, 0x11, 0x11},{192, 168, 1, 199},{255,255,255,0},{192, 168, 1, 1},{8,8,8,8},NETINFO_STATIC };//端口0的網絡參數
uint16_t LocalPort0=5000; //端口0的本地端口號(5000)
uint8_t DstIP_Port0[4]={192,168,1,190}; //端口0的遠程IP地址:192.168.1.190
uint16_t DstPort_Port0=6000; //端口0的遠程端口號:6000uint8_t gDATABUF[DATA_BUF_SIZE];//STM32接收/發送W5500的數據緩沖區void W5500_Initialization(void);//函數功能:裝載W5500的本地網絡參數和端口0的網絡參數
void W5500_Load_Net_Parameters(void)
{
//本地物理地址:00 08 DC 11 11 11gWIZNETINFO.mac[0]=0x00;gWIZNETINFO.mac[1]=0x08;gWIZNETINFO.mac[2]=0xdc;gWIZNETINFO.mac[3]=0x11;gWIZNETINFO.mac[4]=0x11;gWIZNETINFO.mac[5]=0x11;//本地IP地址:192.168.1.199gWIZNETINFO.ip[0]=192;gWIZNETINFO.ip[1]=168;gWIZNETINFO.ip[2]=1;gWIZNETINFO.ip[3]=199;//本地子網掩碼: 255.255.255.0gWIZNETINFO.sn[0]=255;gWIZNETINFO.sn[1]=255;gWIZNETINFO.sn[2]=255;gWIZNETINFO.sn[3]=0;//本地網關:192.168.1.1gWIZNETINFO.gw[0]=192;gWIZNETINFO.gw[1]=168;gWIZNETINFO.gw[2]=1;gWIZNETINFO.gw[3]=1;//DNS服務器IP地址:8.8.8.8gWIZNETINFO.dns[0]=8;gWIZNETINFO.dns[1]=8;gWIZNETINFO.dns[2]=8;gWIZNETINFO.dns[3]=8;//DHCP模式gWIZNETINFO.dhcp=NETINFO_STATIC;//告訴ioLibrary庫,當前使用"靜態IP地址"配置//通過手動配置靜態IP地址,Static IP configuration by manually.//端口0的本地端口號LocalPort0=5000;//端口0的遠程IP地址:192.168.1.190DstIP_Port0[0]=192;DstIP_Port0[1]=168;DstIP_Port0[2]=1;DstIP_Port0[3]=190;//端口0的遠程端口號DstPort_Port0=6000;
}/*** @brief Intialize the network information to be used in WIZCHIP* @retval None*/
//函數功能:設置本地網絡參數:MAC地址,GW網關,SN子網掩碼,本地IP地址,DNS服務器IP地址,DHCP
void network_init(void)
{uint8_t tmpstr[6];ctlnetwork(CN_SET_NETINFO, (void*)&gWIZNETINFO);//設置本地網絡參數:MAC地址,GW網關,SN子網掩碼,本地IP地址,DNS服務器IP地址,DHCP//設置MAC地址,將gWIZNETINFO.mac寫入W5500;//設置網關,將gWIZNETINFO.gw寫入W5500;//設置子網掩碼,將gWIZNETINFO.sn寫入W5500//設置本地IP地址,將gWIZNETINFO.ip寫入W5500//將gWIZNETINFO.dns[]拷貝到_DNS_[]中//將gWIZNETINFO.dhcp保存到_DHCP_中ctlnetwork(CN_GET_NETINFO, (void*)&gWIZNETINFO);//讀本地網絡參數:MAC地址,GW網關,SN子網掩碼,本地IP地址,DNS服務器IP地址,DHCP//讀MAC地址,保存到gWIZNETINFO.mac//讀網關,保存到gWIZNETINFO.gw//讀子網掩碼,保存到gWIZNETINFO.sn//讀本地IP地址,保存到gWIZNETINFO.ip//將_DNS_[]拷貝到gWIZNETINFO.dns[]中//將_DHCP_保存到gWIZNETINFO.dhcp中ctlwizchip(CW_GET_ID,(void*)tmpstr);//讀W5500的ID,保存到tmpstr[6]中,"W5500\0",這是ioLibrary驅動定義的ID;//在wizchip_conf.h中定義_WIZCHIP_ID_為"W5500\0"printf("\r\n=== %s NET CONF ===\r\n",(char*)tmpstr);//串口輸出W5500的IDprintf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n",gWIZNETINFO.mac[0],gWIZNETINFO.mac[1],gWIZNETINFO.mac[2],gWIZNETINFO.mac[3],gWIZNETINFO.mac[4],gWIZNETINFO.mac[5]);//串口輸出W5500的MAC地址printf("SIP: %d.%d.%d.%d\r\n", gWIZNETINFO.ip[0],gWIZNETINFO.ip[1],gWIZNETINFO.ip[2],gWIZNETINFO.ip[3]);//串口輸出W5500的IP地址printf("GAR: %d.%d.%d.%d\r\n", gWIZNETINFO.gw[0],gWIZNETINFO.gw[1],gWIZNETINFO.gw[2],gWIZNETINFO.gw[3]);//串口輸出W5500的網關地址printf("SUB: %d.%d.%d.%d\r\n", gWIZNETINFO.sn[0],gWIZNETINFO.sn[1],gWIZNETINFO.sn[2],gWIZNETINFO.sn[3]);//串口輸出W5500的子網掩碼printf("DNS: %d.%d.%d.%d\r\n", gWIZNETINFO.dns[0],gWIZNETINFO.dns[1],gWIZNETINFO.dns[2],gWIZNETINFO.dns[3]);//串口輸出W5500的DNS服務器IP地址printf("======================\r\n");
}//函數功能:
//1.初始化SPI接口
//2.注冊相關函數
//3.設置W5500每個端口的發送緩沖區和接收緩沖區的大小均為2K字節
//4.等待"以太網"連接完成
//5.裝載本地網絡參數
//6.設置本地網絡參數:MAC地址,GW網關,SN子網掩碼,本地IP地址,DNS服務器IP地址,DHCP
void W5500_Initialization(void)
{uint8_t memsize[2][8] = {{2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2}};//W5500發送和接收各有8個端口,這里定義每個端口的發送緩沖區和接收緩沖區的大小均為2K字節uint8_t tmp;W5500_SPI_Init(); //W5500 SPI初始化配置reg_wizchip_cris_cbfunc(SPI_CrisEnter, SPI_CrisExit); //注冊臨界區函數reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);//注冊SPI片選信號函數reg_wizchip_spi_cbfunc(SPI_ReadByte, SPI_WriteByte); //注冊讀寫函數if(ctlwizchip(CW_INIT_WIZCHIP,(void*)memsize) == -1){//W5500發送和接收各有8個端口,這里初始化每個端口的發送緩沖區和接收緩沖區的大小均為2K字節printf("WIZCHIP Initialized fail.\r\n");}//等待"以太網"連接完成, PHY link status checkdo{if(ctlwizchip(CW_GET_PHYLINK, (void*)&tmp) == -1){//讀PHYCFGR寄存器bit0,若為1,則表示網絡已經連接printf("Unknown PHY Link stauts.\r\n");}}while(tmp == PHY_LINK_OFF);W5500_Load_Net_Parameters();//裝載W5500的本地網絡參數和端口0的網絡參數network_init();//設置本地網絡參數:MAC地址,GW網關,SN子網掩碼,本地IP地址,DNS服務器IP地址,DHCP
}//函數功能:端口0發送"I am W5500\r\n"
void SOCKET0_Send_Data(void)
{char buf[20];uint16_t len=0;memset(gDATABUF,'\0',sizeof(gDATABUF));strcpy(buf,"I am W5500\r\n");strcat((char*)gDATABUF,buf);len=strlen( (char*)gDATABUF );send(SOCK_TCPS,gDATABUF,len);//發送數據
}void SOCKET0_Work(void)
{uint16_t len=0;switch(getSn_SR(SOCK_TCPS))//獲取W5500端口0的狀態寄存器{case SOCK_INIT://W5500端口0已經初始化connect(SOCK_TCPS,DstIP_Port0,DstPort_Port0);//將W5500端口0連接到遠程IP地址DstIP_Port0和遠程端口DstPort_Port0上break;case SOCK_ESTABLISHED://W5500端口0已經連接成功if(getSn_IR(SOCK_TCPS) & Sn_IR_CON){//讀端口0的Sn_IR中斷標志寄存器的bit0setSn_IR(SOCK_TCPS, Sn_IR_CON);//回寫清除中斷標志}len=getSn_RX_RSR(SOCK_TCPS);//讀端口0接收緩沖區的數據長度if(len){recv(SOCK_TCPS,gDATABUF,len);//讀"W5500端口0"的數據,長度為len個字節,保存到gDATABUFprintf("%s\r\n",gDATABUF);send(SOCK_TCPS,gDATABUF,len);//將gDATABUF的前len個字節通過"W5500端口0"發送出去}SOCKET0_Send_Data();break;case SOCK_CLOSE_WAIT://W5500端口0處于等待關閉狀態disconnect(SOCK_TCPS);//關閉端口0的連接break;case SOCK_CLOSED://W5500端口0處于關閉狀態socket(SOCK_TCPS,Sn_MR_TCP,LocalPort0,0x00);//打開Socket0,打開一個本地端口break;}
}
6、TCP客戶端應用程序W5500_HD_Driver.h頭文件
#ifndef _W5500_HD_Driver_H_
#define _W5500_HD_Driver_H_#include "stm32f10x.h"//使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t
#include "wizchip_conf.h"extern wiz_NetInfo gWIZNETINFO;//W5500的網絡參數#define SOCK_TCPS 0 //端口0
extern uint16_t LocalPort0; //端口0的端口號
extern uint8_t DstIP_Port0[4]; //端口0的遠程IP地址
extern uint16_t DstPort_Port0; //端口0的遠程端口號#define DATA_BUF_SIZE 2048
extern uint8_t gDATABUF[DATA_BUF_SIZE];#define W5500_CS_high() GPIO_SetBits(GPIOA,GPIO_Pin_4) //W5500片選引腳
#define W5500_CS_low() GPIO_ResetBits(GPIOA,GPIO_Pin_4) //W5500片選引腳extern void W5500_Initialization(void);
extern void SOCKET0_Work(void);
#endif
7、main.c程序
#include "stm32f10x.h"//使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t
#include "stdio.h" //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "string.h" //使能strcpy(),strlen(),memset()
#include "delay.h"
#include "USART4.h"#include "LED.h"
#include "W5500_HD_Driver.h"//#include "W5500_Variable.h"const char CPU_Reset_REG[]="\r\nCPU reset!\r\n";
int main(void)
{// SCB->VTOR = 0x8000000;//中斷向量表重定義// SystemInit();delay_init();//延時函數初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//設置系統中斷優先級分組4USART4_Serial_Interface_Enable(115200);printf("%s",CPU_Reset_REG);//調試串口輸出"\r\nCPU reset!\r\n"W5500_Initialization();//1.初始化SPI接口//2.注冊相關函數//3.設置W5500每個端口的發送緩沖區和接收緩沖區的大小均為2K字節//4.等待"以太網"連接完成//5.裝載本地網絡參數//6.設置本地網絡參數:MAC地址,GW網關,SN子網掩碼,本地IP地址,DNS服務器IP地址,DHCPLED_Init();LED0_ON();while(1){LED0=!LED0;delay_ms(1000);SOCKET0_Work();//W5500端口0工作}
}