????????W5300是一款帶有硬件協議棧的網絡芯片,內部擁有128K的緩存,最大支持8路socket通信,與MCU之間通過16位數據總線通信,通信速度遠超W5500之類以SPI作為通信接口的網絡芯片,特別適合對高速網絡傳輸有需求的應用。
? ? ? ? 本次使用STM32F205ZET6作為主控MCU,通過FSMC接口與W5300連接,主機在完成配置后,就可以像訪問SRAM一樣輕松操作W5300。以下為W5300引腳介紹及參考電路
????????除FSMC接口外,還需要額外的芯片復位腳和中斷腳。芯片上電復位不太可靠,因此一般需要通過操作復位引腳來進行可靠復位,這個特性在W5500上也有,需要注意。中斷腳的話不是必須的,也可以通過查詢方式來獲取中斷信息,但這里我們還是使用了。
? ? ? ? 除此以外,硬件上還有一些配置,可以對照上面的電路圖
? ? ? ? 硬件連接沒有問題后就開始軟件編程了,首先是初始化。初始化這部分分兩塊,一個是對于FSMC的引腳初始化,另一部分是對于芯片的初始化。
????????FSMC初始化(在這里不包括復位和中斷腳的初始化,這兩個腳可以使用普通IO,而FSMC的引腳是固定的),根據接線不同,FSMC_NORSRAMInitStructure.FSMC_Bank和FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth參數也不同,具體的可以查看STM32的手冊。
void Config_FSMC(void)
{GPIO_InitTypeDef GPIO_InitStructure;FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;FSMC_NORSRAMTimingInitTypeDef p;FSMC_NORSRAMDeInit(FSMC_Bank1_NORSRAM1);/* AHB3 Peripheral Clock configuration -------------------------------------*//* FSMC clock enable */RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC , ENABLE); /* Enable GPIOs clock */RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF |RCC_AHB1Periph_GPIOG, ENABLE);/*-- GPIOs Configuration -----------------------------------------------------*//*+-------------------+--------------------+------------------+------------------+| PD0 <-> FSMC_D2 | PE0 <-> FSMC_NBL0 | PF0 <-> FSMC_A0 | PG0 <-> FSMC_A10 || PD1 <-> FSMC_D3 | PE1 <-> FSMC_NBL1 | PF1 <-> FSMC_A1 | PG1 <-> FSMC_A11 || PD4 <-> FSMC_NOE | PE2 <-> FSMC_A23 | PF2 <-> FSMC_A2 | PG2 <-> FSMC_A12 || PD5 <-> FSMC_NWE | PE3 <-> FSMC_A19 | PF3 <-> FSMC_A3 | PG3 <-> FSMC_A13 || PD8 <-> FSMC_D13 | PE4 <-> FSMC_A20 | PF4 <-> FSMC_A4 | PG4 <-> FSMC_A14 || PD9 <-> FSMC_D14 | PE5 <-> FSMC_A21 | PF5 <-> FSMC_A5 | PG5 <-> FSMC_A15 || PD10 <-> FSMC_D15 | PE6 <-> FSMC_A22 | PF12 <-> FSMC_A6 | PG9 <-> FSMC_NE2 || PD11 <-> FSMC_A16 | PE7 <-> FSMC_D4 | PF13 <-> FSMC_A7 |------------------+| PD12 <-> FSMC_A17 | PE8 <-> FSMC_D5 | PF14 <-> FSMC_A8 || PD13 <-> FSMC_A18 | PE9 <-> FSMC_D6 | PF15 <-> FSMC_A9 || PD14 <-> FSMC_D0 | PE10 <-> FSMC_D7 |------------------+| PD15 <-> FSMC_D1 | PE11 <-> FSMC_D8 |+-------------------| PE12 <-> FSMC_D9 || PE13 <-> FSMC_D10 || PE14 <-> FSMC_D11 || PE15 <-> FSMC_D12 |+--------------------+*//* GPIOD configuration */GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FSMC);//GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_FSMC); //GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_FSMC);//GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(GPIOD, &GPIO_InitStructure);/* GPIOE configuration *///GPIO_PinAFConfig(GPIOE, GPIO_PinSource0 , GPIO_AF_FSMC);//GPIO_PinAFConfig(GPIOE, GPIO_PinSource1 , GPIO_AF_FSMC);//GPIO_PinAFConfig(GPIOE, GPIO_PinSource2 , GPIO_AF_FSMC);//GPIO_PinAFConfig(GPIOE, GPIO_PinSource3 , GPIO_AF_FSMC);//GPIO_PinAFConfig(GPIOE, GPIO_PinSource4 , GPIO_AF_FSMC);//GPIO_PinAFConfig(GPIOE, GPIO_PinSource5 , GPIO_AF_FSMC);//GPIO_PinAFConfig(GPIOE, GPIO_PinSource6 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOE, GPIO_PinSource7 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOE, GPIO_PinSource8 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOE, GPIO_PinSource9 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOE, GPIO_PinSource10 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOE, GPIO_PinSource11 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOE, GPIO_PinSource12 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOE, GPIO_PinSource13 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOE, GPIO_PinSource14 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOE, GPIO_PinSource15 , GPIO_AF_FSMC);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;GPIO_Init(GPIOE, &GPIO_InitStructure);/* GPIOF configuration */GPIO_PinAFConfig(GPIOF, GPIO_PinSource0 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOF, GPIO_PinSource1 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOF, GPIO_PinSource2 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOF, GPIO_PinSource3 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOF, GPIO_PinSource4 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOF, GPIO_PinSource5 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOF, GPIO_PinSource12 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOF, GPIO_PinSource13 , GPIO_AF_FSMC);GPIO_PinAFConfig(GPIOF, GPIO_PinSource14 , GPIO_AF_FSMC);//GPIO_PinAFConfig(GPIOF, GPIO_PinSource15 , GPIO_AF_FSMC);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_12 | GPIO_Pin_13 |GPIO_Pin_14 ; GPIO_Init(GPIOF, &GPIO_InitStructure);//-- FSMC Configuration ------------------------------------------------------p.FSMC_AddressSetupTime = 0;p.FSMC_AddressHoldTime = 0;p.FSMC_DataSetupTime = 5; //2p.FSMC_BusTurnAroundDuration = 1; //0p.FSMC_CLKDivision = 0;p.FSMC_DataLatency = 0;p.FSMC_AccessMode = FSMC_AccessMode_A;FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;//FSMC_NORSRAMInitStructure.FSMC_AsyncWait = FSMC_AsyncWait_Disable; //FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); /* Enable FSMC Bank1_SRAM Bank */FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE); }
? ? ? ? 接下來就是對于芯片的初始化,前面說過對于芯片的訪問如同SRAM一樣,具體到W5300上,就是寄存器地址好比SRAM存儲地址,操作寄存器就是往不同的地址寫數據。W5300的寄存器地址都是廠商給定的相對地址,而基地址則跟FSMC接線有關。
? ? ? ? W5300的寄存器分為模式寄存器,間接模式寄存器,通用寄存器和SOCKET寄存器。不同的寄存器分管不同的功能,具體的可以查閱官方手冊,這里不作列舉了。
????????W5300的初始化分為3個步驟
- 設置主機接口(數據總線寬度,接口模式,時序)
- 設置網絡信息(MAC,本地IP,網關,子網掩碼,重發間隔次數等)
- 分配SOCKET內部TX/RX存儲空間
? ? ? ? 示例代碼如下
u8 W5300_Init(void)
{u16 i;u16 Tsum=0,Rsum=0;u16 val;u8 rMac[6];vdTimeDelay(0x00800000);// 設置主機接口:8位/直接訪問_SetMR(MR_RST);vdTimeDelay(0x02000000);//setMR(getMR()|MR_FS);// 設置主機中斷:IP沖突 | 目標端口無法到達 // | Socket0~3 _SetIMR(IR_IPCF | IR_DPUR | 0x03);// // 設置網絡參數_SetSHAR((u8 *)&(SysInfo.bMAC[0]));_SetGAR((u8 *)&(SysInfo.bGW[0]));_SetSUBR((u8 *)&(SysInfo.bSUB[0]));_SetSIPR((u8 *)&(SysInfo.bIP[0]));_GetSHAR((u8 *)rMac);for(i = 0;i<6;i++){if(SysInfo.bMAC[i] != rMac[i]) break;}if(i < 6) return 0;// 配置重復發送超時周期的值,RTR的標準單位是 100us_SetRTR(2000);// 配置重復發送的次數。當重復發送的次數達到 RCR+1時,將產生超時中斷(Sn_IR 的TIMEOUT?位置1)_SetRCR(7);// 分配Socket內存for(i=0; i < MAX_SOCKET_NUM; i++){if(TxMemSize[i] > 64) return 0;if(RxMemSize[i] > 64) return 0;Tsum += (u16)TxMemSize[i];Rsum += (u16)RxMemSize[i];dwTMSsum[i] = ((u32)TxMemSize[i]) << 10;dwRMSsum[i] = ((u32)RxMemSize[i]) << 10;}if( (Tsum % 8) || ((Tsum + Rsum) != 128)) return 0;for(i = 0;i<8;i++){_SetTMSR(i,TxMemSize[i]);_SetRMSR(i,RxMemSize[i]);}val = 0;for(i=0; i < Tsum/8; i++){val <<= 1;val |= 1;}_SetMTYPER(val);return 1;
}
? ? ? ? 之后就可以根據實際應用進行socket編程了,根據配置選擇TCP或UDP通信等,每個socket可以獨立配置互不影響。
? ? ? ? 當網絡接收到數據時,觸發中斷,通過讀取IR寄存器獲知中斷類型,然后進相應的處理函數去處理。
void ISR_W5300(void)
{u16 wPendInt;
// Close Global InterruptwPendInt = _GetIR();
// IP地址沖突if(wPendInt & IR_IPCF) // check the IP conflict interrupt{_SetIR(IR_IPCF);}
// 目標IP無法到達if(wPendInt & IR_DPUR) // check the unreachable destination interrupt{_SetIR(IR_DPUR);}if (wPendInt & 0x0001) ISR_Socket0();if (wPendInt & 0x0002) ISR_Socket1();if (wPendInt & 0x0004) ISR_Socket2();
// Open Global Interrupt
}
? ? ? ? 如果要進行發送,則操作相應的SOCKET寄存器即可
void _WrSxBuffer(u8 Sx,u8* buf,u32 len)
{u32 z,tLen;pSOCKET Sn;Sn = (pSOCKET)(SOCKET0_BASE + SOCKET_REG_SIZE * Sx);tLen = len + (len & 0x01);for(z = 0; z < tLen; z += 2){Sn->TX_FIFOR = (u16)(*(buf + z)<< 8) | (u16)(*(buf+z+1));}
}
? ? ? ? 代碼太多不便展示,具體可參考
????????https://download.csdn.net/download/u011436603/88902967?spm=1001.2014.3001.5503