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