前景提要
STM32 H743确实是个好芯片,但是这个MAC只有一个真是让我觉得不太够,想整双MAC的A核芯片玩玩,奈何实在也是没得精力弄Linux,虽然imx6ull也是一个好芯片。。。。
外挂MAC的方案有很多,最后还是选了W5500… SPI口还是可以的,即是速度拉跨,但是即使10M的以太网也是很不错了,相比串口,CAN啥的 100M不指望了,这个SPI应该也跑不到那么高速吧,已经满足需求了
实际操作
芯片: STM32H743VIT6核心板 X宝买的W5500模块 自己画了个底板,不想用杜邦线,因为杜邦线不太靠谱
CubeMX设置
时钟设置
注意,我这个核心板是25M晶振
引脚与外设
我这里用的是SPI3,SPI引脚就不说了吧,额外要给模块分:
- RST复位引脚
- INT外部中断引脚【它的IO库有没有用不知道】
- 片选CS【这个一定要!!】
话不多说上外设 W5500好像SPI接口不能太快,30M可能就是最大了 我看的教程 我是看这个教程跟着搞的,时间有点跨度了,有点差异
适配H743和W5500,搭建工程
然后生成CubeMX IDE工程 然后按照那个教程说的去Github上下W5500官方的IO库,下下来,添加好引用关系之后 适配很简单就是对接几个函数指针 简单起见,我这里是裸机环境 基本上对IO库的对接集中在画绿色的两个文件上 按照要求补上操作SPI需要的函数接口,注册到它的IO库上 直接附上我的代码
wizchip_conf.c
#include <stddef.h>
#include "main.h"
#include "stm32h7xx.h"
#include "stm32h7xx_hal.h"
#include "wizchip_conf.h"
#include "spi.h"
void wizchip_cris_enter(void) {__set_PRIMASK(1);}
void wizchip_cris_exit(void) {__set_PRIMASK(0);}
void wizchip_cs_select(void) {HAL_GPIO_WritePin(W5500_CS_GPIO_Port, W5500_CS_Pin, GPIO_PIN_RESET);}
void wizchip_cs_deselect(void) {HAL_GPIO_WritePin(W5500_CS_GPIO_Port, W5500_CS_Pin, GPIO_PIN_SET);}
iodata_t wizchip_bus_readdata(uint32_t AddrSel) { return * ((volatile iodata_t *)((ptrdiff_t) AddrSel)); }
void wizchip_bus_writedata(uint32_t AddrSel, iodata_t wb) { *((volatile iodata_t*)((ptrdiff_t)AddrSel)) = wb; }
uint8_t wizchip_spi_readbyte(void)
{
uint8_t value;
if (HAL_SPI_Receive(&hspi3, &value, 1, 1000) != HAL_OK) {
value = 0;
}
return value;
}
void wizchip_spi_writebyte(uint8_t wb) {
HAL_SPI_Transmit(&hspi3, &wb, 1, 1000);
}
void wizchip_spi_readburst(uint8_t* pBuf, uint16_t len)
{
if (!pBuf) {
return;
}
HAL_SPI_Receive(&hspi3, pBuf, len, 1000);
}
void wizchip_spi_writeburst(uint8_t* pBuf, uint16_t len) {
if (!pBuf) {
return;
}
HAL_SPI_Transmit(&hspi3, pBuf, len, 1000);
}
_WIZCHIP WIZCHIP =
{
_WIZCHIP_IO_MODE_,
_WIZCHIP_ID_ ,
{
wizchip_cris_enter,
wizchip_cris_exit
},
{
wizchip_cs_select,
wizchip_cs_deselect
},
{
{
wizchip_bus_readdata,
wizchip_bus_writedata
},
}
};
void w5500_regFunc(void)
{
reg_wizchip_cris_cbfunc(wizchip_cris_enter, wizchip_cris_exit);
reg_wizchip_cs_cbfunc(wizchip_cs_select, wizchip_cs_deselect);
reg_wizchip_spi_cbfunc(wizchip_spi_readbyte, wizchip_spi_writebyte);
reg_wizchip_spiburst_cbfunc(wizchip_spi_readburst, wizchip_spi_writeburst);
}
static uint8_t _DNS_[4];
static dhcp_mode _DHCP_;
void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void))
{
if(!cris_en || !cris_ex)
{
WIZCHIP.CRIS._enter = wizchip_cris_enter;
WIZCHIP.CRIS._exit = wizchip_cris_exit;
}
else
{
WIZCHIP.CRIS._enter = cris_en;
WIZCHIP.CRIS._exit = cris_ex;
}
}
void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void))
{
if(!cs_sel || !cs_desel)
{
WIZCHIP.CS._select = wizchip_cs_select;
WIZCHIP.CS._deselect = wizchip_cs_deselect;
}
else
{
WIZCHIP.CS._select = cs_sel;
WIZCHIP.CS._deselect = cs_desel;
}
}
void reg_wizchip_bus_cbfunc(iodata_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, iodata_t wb))
{
while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_));
if(!bus_rb || !bus_wb)
{
WIZCHIP.IF.BUS._read_data = wizchip_bus_readdata;
WIZCHIP.IF.BUS._write_data = wizchip_bus_writedata;
}
else
{
WIZCHIP.IF.BUS._read_data = bus_rb;
WIZCHIP.IF.BUS._write_data = bus_wb;
}
}
void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb))
{
while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_));
if(!spi_rb || !spi_wb)
{
WIZCHIP.IF.SPI._read_byte = wizchip_spi_readbyte;
WIZCHIP.IF.SPI._write_byte = wizchip_spi_writebyte;
}
else
{
WIZCHIP.IF.SPI._read_byte = spi_rb;
WIZCHIP.IF.SPI._write_byte = spi_wb;
}
}
void reg_wizchip_spiburst_cbfunc(void (*spi_rb)(uint8_t* pBuf, uint16_t len), void (*spi_wb)(uint8_t* pBuf, uint16_t len))
{
while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_));
if(!spi_rb || !spi_wb)
{
WIZCHIP.IF.SPI._read_burst = wizchip_spi_readburst;
WIZCHIP.IF.SPI._write_burst = wizchip_spi_writeburst;
}
else
{
WIZCHIP.IF.SPI._read_burst = spi_rb;
WIZCHIP.IF.SPI._write_burst = spi_wb;
}
}
int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg)
{
#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5200 || _WIZCHIP_ == W5500
uint8_t tmp = 0;
#endif
uint8_t* ptmp[2] = {0,0};
switch(cwtype)
{
case CW_RESET_WIZCHIP:
wizchip_sw_reset();
break;
case CW_INIT_WIZCHIP:
if(arg != 0)
{
ptmp[0] = (uint8_t*)arg;
ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_;
}
return wizchip_init(ptmp[0], ptmp[1]);
case CW_CLR_INTERRUPT:
wizchip_clrinterrupt(*((intr_kind*)arg));
break;
case CW_GET_INTERRUPT:
*((intr_kind*)arg) = wizchip_getinterrupt();
break;
case CW_SET_INTRMASK:
wizchip_setinterruptmask(*((intr_kind*)arg));
break;
case CW_GET_INTRMASK:
*((intr_kind*)arg) = wizchip_getinterruptmask();
break;
#if (_WIZCHIP_ == W5200 || _WIZCHIP_ == W5500)
case CW_SET_INTRTIME:
setINTLEVEL(*(uint16_t*)arg);
break;
case CW_GET_INTRTIME:
*(uint16_t*)arg = getINTLEVEL();
break;
#endif
case CW_GET_ID:
((uint8_t*)arg)[0] = WIZCHIP.id[0];
((uint8_t*)arg)[1] = WIZCHIP.id[1];
((uint8_t*)arg)[2] = WIZCHIP.id[2];
((uint8_t*)arg)[3] = WIZCHIP.id[3];
((uint8_t*)arg)[4] = WIZCHIP.id[4];
((uint8_t*)arg)[5] = 0;
break;
#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5500
case CW_RESET_PHY:
wizphy_reset();
break;
case CW_SET_PHYCONF:
wizphy_setphyconf((wiz_PhyConf*)arg);
break;
case CW_GET_PHYCONF:
wizphy_getphyconf((wiz_PhyConf*)arg);
break;
case CW_GET_PHYSTATUS:
break;
case CW_SET_PHYPOWMODE:
return wizphy_setphypmode(*(uint8_t*)arg);
#endif
#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5200 || _WIZCHIP_ == W5500
case CW_GET_PHYPOWMODE:
tmp = wizphy_getphypmode();
if((int8_t)tmp == -1) return -1;
*(uint8_t*)arg = tmp;
break;
case CW_GET_PHYLINK:
tmp = wizphy_getphylink();
if((int8_t)tmp == -1) return -1;
*(uint8_t*)arg = tmp;
break;
#endif
default:
return -1;
}
return 0;
}
int8_t ctlnetwork(ctlnetwork_type cntype, void* arg)
{
switch(cntype)
{
case CN_SET_NETINFO:
wizchip_setnetinfo((wiz_NetInfo*)arg);
break;
case CN_GET_NETINFO:
wizchip_getnetinfo((wiz_NetInfo*)arg);
break;
case CN_SET_NETMODE:
return wizchip_setnetmode(*(netmode_type*)arg);
case CN_GET_NETMODE:
*(netmode_type*)arg = wizchip_getnetmode();
break;
case CN_SET_TIMEOUT:
wizchip_settimeout((wiz_NetTimeout*)arg);
break;
case CN_GET_TIMEOUT:
wizchip_gettimeout((wiz_NetTimeout*)arg);
break;
default:
return -1;
}
return 0;
}
void wizchip_sw_reset(void)
{
uint8_t gw[4], sn[4], sip[4];
uint8_t mac[6];
#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_
uint16_t mr = (uint16_t)getMR();
setMR(mr | MR_IND);
#endif
getSHAR(mac);
getGAR(gw); getSUBR(sn); getSIPR(sip);
setMR(MR_RST);
getMR();
#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_
setMR(mr | MR_IND);
#endif
setSHAR(mac);
setGAR(gw);
setSUBR(sn);
setSIPR(sip);
}
int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize)
{
int8_t i;
#if _WIZCHIP_ < W5200
int8_t j;
#endif
int8_t tmp = 0;
wizchip_sw_reset();
if(txsize)
{
tmp = 0;
#if _WIZCHIP_ == W5300
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
{
if(txsize[i] >= 64) return -1;
tmp += txsize[i];
if(tmp > 128) return -1;
}
if(tmp % 8) return -1;
#else
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
{
tmp += txsize[i];
#if _WIZCHIP_ < W5200
if(tmp > 8) return -1;
#else
if(tmp > 16) return -1;
#endif
}
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
{
#if _WIZCHIP_ < W5200
j = 0;
while((txsize[i] >> j != 1)&&(txsize[i] !=0)){j++;}
setSn_TXBUF_SIZE(i, j);
#else
setSn_TXBUF_SIZE(i, txsize[i]);
#endif
}
#endif
}
if(rxsize)
{
tmp = 0;
#if _WIZCHIP_ == W5300
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
{
if(rxsize[i] >= 64) return -1;
tmp += rxsize[i];
if(tmp > 128) return -1;
}
if(tmp % 8) return -1;
#else
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
{
tmp += rxsize[i];
#if _WIZCHIP_ < W5200
if(tmp > 8) return -1;
#else
if(tmp > 16) return -1;
#endif
}
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
{
#if _WIZCHIP_ < W5200
j = 0;
while((rxsize[i] >> j != 1)&&(txsize[i] !=0)){j++;}
setSn_RXBUF_SIZE(i, j);
#else
setSn_RXBUF_SIZE(i, rxsize[i]);
#endif
}
#endif
}
return 0;
}
void wizchip_clrinterrupt(intr_kind intr)
{
uint8_t ir = (uint8_t)intr;
uint8_t sir = (uint8_t)((uint16_t)intr >> 8);
#if _WIZCHIP_ < W5500
ir |= (1<<4);
#endif
#if _WIZCHIP_ == W5200
ir |= (1 << 6);
#endif
#if _WIZCHIP_ < W5200
sir &= 0x0F;
#endif
#if _WIZCHIP_ <= W5100S
ir |= sir;
setIR(ir);
#elif _WIZCHIP_ == W5300
setIR( ((((uint16_t)ir) << 8) | (((uint16_t)sir) & 0x00FF)) );
#else
setIR(ir);
for(ir=0; ir<8; ir++){
if(sir & (0x01 <<ir) ) setSn_IR(ir, 0xff);
}
#endif
}
intr_kind wizchip_getinterrupt(void)
{
uint8_t ir = 0;
uint8_t sir = 0;
uint16_t ret = 0;
#if _WIZCHIP_ <= W5100S
ir = getIR();
sir = ir & 0x0F;
#elif _WIZCHIP_ == W5300
ret = getIR();
ir = (uint8_t)(ret >> 8);
sir = (uint8_t)ret;
#else
ir = getIR();
sir = getSIR();
#endif
#if _WIZCHIP_ < W5200
ir &= ~(1<<4);
#endif
#if _WIZCHIP_ == W5200
ir &= ~(1 << 6);
#endif
ret = sir;
ret = (ret << 8) + ir;
return (intr_kind)ret;
}
void wizchip_setinterruptmask(intr_kind intr)
{
uint8_t imr = (uint8_t)intr;
uint8_t simr = (uint8_t)((uint16_t)intr >> 8);
#if _WIZCHIP_ < W5500
imr &= ~(1<<4);
#endif
#if _WIZCHIP_ == W5200
imr &= ~(1 << 6);
#endif
#if _WIZCHIP_ < W5200
simr &= 0x0F;
imr |= simr;
setIMR(imr);
#elif _WIZCHIP_ == W5300
setIMR( ((((uint16_t)imr) << 8) | (((uint16_t)simr) & 0x00FF)) );
#else
setIMR(imr);
setSIMR(simr);
#endif
}
intr_kind wizchip_getinterruptmask(void)
{
uint8_t imr = 0;
uint8_t simr = 0;
uint16_t ret = 0;
#if _WIZCHIP_ < W5200
imr = getIMR();
simr = imr & 0x0F;
#elif _WIZCHIP_ == W5300
ret = getIMR();
imr = (uint8_t)(ret >> 8);
simr = (uint8_t)ret;
#else
imr = getIMR();
simr = getSIMR();
#endif
#if _WIZCHIP_ < W5500
imr &= ~(1<<4);
#endif
#if _WIZCHIP_ == W5200
imr &= ~(1 << 6);
#endif
ret = simr;
ret = (ret << 8) + imr;
return (intr_kind)ret;
}
int8_t wizphy_getphylink(void)
{
int8_t tmp = PHY_LINK_OFF;
#if _WIZCHIP_ == W5100S
if(getPHYSR() & PHYSR_LNK)
tmp = PHY_LINK_ON;
#elif _WIZCHIP_ == W5200
if(getPHYSTATUS() & PHYSTATUS_LINK)
tmp = PHY_LINK_ON;
#elif _WIZCHIP_ == W5500
if(getPHYCFGR() & PHYCFGR_LNK_ON)
tmp = PHY_LINK_ON;
#else
tmp = -1;
#endif
return tmp;
}
#if _WIZCHIP_ > W5100
int8_t wizphy_getphypmode(void)
{
int8_t tmp = 0;
#if _WIZCHIP_ == W5200
if(getPHYSTATUS() & PHYSTATUS_POWERDOWN)
tmp = PHY_POWER_DOWN;
else
tmp = PHY_POWER_NORM;
#elif _WIZCHIP_ == 5500
if((getPHYCFGR() & PHYCFGR_OPMDC_ALLA) == PHYCFGR_OPMDC_PDOWN)
tmp = PHY_POWER_DOWN;
else
tmp = PHY_POWER_NORM;
#else
tmp = -1;
#endif
return tmp;
}
#endif
#if _WIZCHIP_ == W5100S
void wizphy_reset(void)
{
uint16_t tmp = wiz_mdio_read(PHYMDIO_BMCR);
tmp |= BMCR_RESET;
wiz_mdio_write(PHYMDIO_BMCR, tmp);
while(wiz_mdio_read(PHYMDIO_BMCR)&BMCR_RESET){}
}
void wizphy_setphyconf(wiz_PhyConf* phyconf)
{
uint16_t tmp = wiz_mdio_read(PHYMDIO_BMCR);
if(phyconf->mode == PHY_MODE_AUTONEGO)
tmp |= BMCR_AUTONEGO;
else
{
tmp &= ~BMCR_AUTONEGO;
if(phyconf->duplex == PHY_DUPLEX_FULL)
{
tmp |= BMCR_DUP;
}
else
{
tmp &= ~BMCR_DUP;
}
if(phyconf->speed == PHY_SPEED_100)
{
tmp |= BMCR_SPEED;
}
else
{
tmp &= ~BMCR_SPEED;
}
}
wiz_mdio_write(PHYMDIO_BMCR, tmp);
}
void wizphy_getphyconf(wiz_PhyConf* phyconf)
{
uint16_t tmp = 0;
tmp = wiz_mdio_read(PHYMDIO_BMCR);
phyconf->by = PHY_CONFBY_SW;
if(tmp & BMCR_AUTONEGO)
{
phyconf->mode = PHY_MODE_AUTONEGO;
}
else
{
phyconf->mode = PHY_MODE_MANUAL;
if(tmp&BMCR_DUP) phyconf->duplex = PHY_DUPLEX_FULL;
else phyconf->duplex = PHY_DUPLEX_HALF;
if(tmp&BMCR_SPEED) phyconf->speed = PHY_SPEED_100;
else phyconf->speed = PHY_SPEED_10;
}
}
int8_t wizphy_setphypmode(uint8_t pmode)
{
uint16_t tmp = 0;
tmp = wiz_mdio_read(PHYMDIO_BMCR);
if( pmode == PHY_POWER_DOWN)
{
tmp |= BMCR_PWDN;
}
else
{
tmp &= ~BMCR_PWDN;
}
wiz_mdio_write(PHYMDIO_BMCR, tmp);
tmp = wiz_mdio_read(PHYMDIO_BMCR);
if( pmode == PHY_POWER_DOWN)
{
if(tmp & BMCR_PWDN) return 0;
}
else
{
if((tmp & BMCR_PWDN) != BMCR_PWDN) return 0;
}
return -1;
}
#endif
#if _WIZCHIP_ == W5500
void wizphy_reset(void)
{
uint8_t tmp = getPHYCFGR();
tmp &= PHYCFGR_RST;
setPHYCFGR(tmp);
tmp = getPHYCFGR();
tmp |= ~PHYCFGR_RST;
setPHYCFGR(tmp);
}
void wizphy_setphyconf(wiz_PhyConf* phyconf)
{
uint8_t tmp = 0;
if(phyconf->by == PHY_CONFBY_SW)
tmp |= PHYCFGR_OPMD;
else
tmp &= ~PHYCFGR_OPMD;
if(phyconf->mode == PHY_MODE_AUTONEGO)
tmp |= PHYCFGR_OPMDC_ALLA;
else
{
if(phyconf->duplex == PHY_DUPLEX_FULL)
{
if(phyconf->speed == PHY_SPEED_100)
tmp |= PHYCFGR_OPMDC_100F;
else
tmp |= PHYCFGR_OPMDC_10F;
}
else
{
if(phyconf->speed == PHY_SPEED_100)
tmp |= PHYCFGR_OPMDC_100H;
else
tmp |= PHYCFGR_OPMDC_10H;
}
}
setPHYCFGR(tmp);
wizphy_reset();
}
void wizphy_getphyconf(wiz_PhyConf* phyconf)
{
uint8_t tmp = 0;
tmp = getPHYCFGR();
phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW;
switch(tmp & PHYCFGR_OPMDC_ALLA)
{
case PHYCFGR_OPMDC_ALLA:
case PHYCFGR_OPMDC_100FA:
phyconf->mode = PHY_MODE_AUTONEGO;
break;
default:
phyconf->mode = PHY_MODE_MANUAL;
break;
}
switch(tmp & PHYCFGR_OPMDC_ALLA)
{
case PHYCFGR_OPMDC_100FA:
case PHYCFGR_OPMDC_100F:
case PHYCFGR_OPMDC_100H:
phyconf->speed = PHY_SPEED_100;
break;
default:
phyconf->speed = PHY_SPEED_10;
break;
}
switch(tmp & PHYCFGR_OPMDC_ALLA)
{
case PHYCFGR_OPMDC_100FA:
case PHYCFGR_OPMDC_100F:
case PHYCFGR_OPMDC_10F:
phyconf->duplex = PHY_DUPLEX_FULL;
break;
default:
phyconf->duplex = PHY_DUPLEX_HALF;
break;
}
}
void wizphy_getphystat(wiz_PhyConf* phyconf)
{
uint8_t tmp = getPHYCFGR();
phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF;
phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10;
}
int8_t wizphy_setphypmode(uint8_t pmode)
{
uint8_t tmp = 0;
tmp = getPHYCFGR();
if((tmp & PHYCFGR_OPMD)== 0) return -1;
tmp &= ~PHYCFGR_OPMDC_ALLA;
if( pmode == PHY_POWER_DOWN)
tmp |= PHYCFGR_OPMDC_PDOWN;
else
tmp |= PHYCFGR_OPMDC_ALLA;
setPHYCFGR(tmp);
wizphy_reset();
tmp = getPHYCFGR();
if( pmode == PHY_POWER_DOWN)
{
if(tmp & PHYCFGR_OPMDC_PDOWN) return 0;
}
else
{
if(tmp & PHYCFGR_OPMDC_ALLA) return 0;
}
return -1;
}
#endif
void wizchip_setnetinfo(wiz_NetInfo* pnetinfo)
{
setSHAR(pnetinfo->mac);
setGAR(pnetinfo->gw);
setSUBR(pnetinfo->sn);
setSIPR(pnetinfo->ip);
_DNS_[0] = pnetinfo->dns[0];
_DNS_[1] = pnetinfo->dns[1];
_DNS_[2] = pnetinfo->dns[2];
_DNS_[3] = pnetinfo->dns[3];
_DHCP_ = pnetinfo->dhcp;
}
void wizchip_getnetinfo(wiz_NetInfo* pnetinfo)
{
getSHAR(pnetinfo->mac);
getGAR(pnetinfo->gw);
getSUBR(pnetinfo->sn);
getSIPR(pnetinfo->ip);
pnetinfo->dns[0]= _DNS_[0];
pnetinfo->dns[1]= _DNS_[1];
pnetinfo->dns[2]= _DNS_[2];
pnetinfo->dns[3]= _DNS_[3];
pnetinfo->dhcp = _DHCP_;
}
int8_t wizchip_setnetmode(netmode_type netmode)
{
uint8_t tmp = 0;
#if _WIZCHIP_ != W5500
if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK)) return -1;
#else
if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) return -1;
#endif
tmp = getMR();
tmp |= (uint8_t)netmode;
setMR(tmp);
return 0;
}
netmode_type wizchip_getnetmode(void)
{
return (netmode_type) getMR();
}
void wizchip_settimeout(wiz_NetTimeout* nettime)
{
setRCR(nettime->retry_cnt);
setRTR(nettime->time_100us);
}
void wizchip_gettimeout(wiz_NetTimeout* nettime)
{
nettime->retry_cnt = getRCR();
nettime->time_100us = getRTR();
}
wizchip_conf.h
#ifndef _WIZCHIP_CONF_H_
#define _WIZCHIP_CONF_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#define W5100 5100
#define W5100S 5100+5
#define W5200 5200
#define W5300 5300
#define W5500 5500
#ifndef _WIZCHIP_
#define _WIZCHIP_ W5500
#endif
#define _WIZCHIP_IO_MODE_NONE_ 0x0000
#define _WIZCHIP_IO_MODE_BUS_ 0x0100
#define _WIZCHIP_IO_MODE_SPI_ 0x0200
#define _WIZCHIP_IO_MODE_BUS_DIR_ (_WIZCHIP_IO_MODE_BUS_ + 1)
#define _WIZCHIP_IO_MODE_BUS_INDIR_ (_WIZCHIP_IO_MODE_BUS_ + 2)
#define _WIZCHIP_IO_MODE_SPI_VDM_ (_WIZCHIP_IO_MODE_SPI_ + 1)
#define _WIZCHIP_IO_MODE_SPI_FDM_ (_WIZCHIP_IO_MODE_SPI_ + 2)
#define _WIZCHIP_IO_MODE_SPI_5500_ (_WIZCHIP_IO_MODE_SPI_ + 3)
#if (_WIZCHIP_ == W5100)
#define _WIZCHIP_ID_ "W5100\0"
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_
typedef uint8_t iodata_t;
#include "W5100/w5100.h"
#elif (_WIZCHIP_ == W5100S)
#define _WIZCHIP_ID_ "W5100S\0"
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_
typedef uint8_t iodata_t;
#include "W5100S/w5100s.h"
#elif (_WIZCHIP_ == W5200)
#define _WIZCHIP_ID_ "W5200\0"
#ifndef _WIZCHIP_IO_MODE_
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_
#endif
typedef uint8_t iodata_t;
#include "W5200/w5200.h"
#elif (_WIZCHIP_ == W5500)
#define _WIZCHIP_ID_ "W5500\0"
#ifndef _WIZCHIP_IO_MODE_
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_VDM_
#endif
typedef uint8_t iodata_t;
#include "W5500/w5500.h"
#elif ( _WIZCHIP_ == W5300)
#define _WIZCHIP_ID_ "W5300\0"
#ifndef _WIZCHIP_IO_MODE_
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_DIR_
#endif
#ifndef _WIZCHIP_IO_BUS_WIDTH_
#define _WIZCHIP_IO_BUS_WIDTH_ 16
#endif
#if _WIZCHIP_IO_BUS_WIDTH_ == 8
typedef uint8_t iodata_t;
#elif _WIZCHIP_IO_BUS_WIDTH_ == 16
typedef uint16_t iodata_t;
#else
#error "Unknown _WIZCHIP_IO_BUS_WIDTH_. It should be 8 or 16."
#endif
#include "W5300/w5300.h"
#else
#error "Unknown defined _WIZCHIP_. You should define one of 5100, 5200, and 5500 !!!"
#endif
#ifndef _WIZCHIP_IO_MODE_
#error "Undefined _WIZCHIP_IO_MODE_. You should define it !!!"
#endif
#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_
#define _WIZCHIP_IO_BASE_ 0x68000000
#elif _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_
#define _WIZCHIP_IO_BASE_ 0x00000000
#endif
#ifndef _WIZCHIP_IO_BASE_
#define _WIZCHIP_IO_BASE_ 0x00000000
#endif
#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_
#ifndef _WIZCHIP_IO_BASE_
#error "You should be define _WIZCHIP_IO_BASE to fit your system memory map."
#endif
#endif
#if _WIZCHIP_ >= W5200
#define _WIZCHIP_SOCK_NUM_ 8
#else
#define _WIZCHIP_SOCK_NUM_ 4
#endif
typedef struct __WIZCHIP
{
uint16_t if_mode;
uint8_t id[7];
struct _CRIS
{
void (*_enter) (void);
void (*_exit) (void);
}CRIS;
struct _CS
{
void (*_select) (void);
void (*_deselect)(void);
}CS;
union _IF
{
struct
{
iodata_t (*_read_data) (uint32_t AddrSel);
void (*_write_data) (uint32_t AddrSel, iodata_t wb);
}BUS;
struct
{
uint8_t (*_read_byte) (void);
void (*_write_byte) (uint8_t wb);
void (*_read_burst) (uint8_t* pBuf, uint16_t len);
void (*_write_burst) (uint8_t* pBuf, uint16_t len);
}SPI;
}IF;
}_WIZCHIP;
extern _WIZCHIP WIZCHIP;
typedef enum
{
CW_RESET_WIZCHIP,
CW_INIT_WIZCHIP,
CW_GET_INTERRUPT,
CW_CLR_INTERRUPT,
CW_SET_INTRMASK,
CW_GET_INTRMASK,
CW_SET_INTRTIME,
CW_GET_INTRTIME,
CW_GET_ID,
CW_RESET_PHY,
CW_SET_PHYCONF,
CW_GET_PHYCONF,
CW_GET_PHYSTATUS,
CW_SET_PHYPOWMODE,
CW_GET_PHYPOWMODE,
CW_GET_PHYLINK
}ctlwizchip_type;
typedef enum
{
CN_SET_NETINFO,
CN_GET_NETINFO,
CN_SET_NETMODE,
CN_GET_NETMODE,
CN_SET_TIMEOUT,
CN_GET_TIMEOUT,
}ctlnetwork_type;
typedef enum
{
#if _WIZCHIP_ == W5500
IK_WOL = (1 << 4),
#elif _WIZCHIP_ == W5300
IK_FMTU = (1 << 4),
#endif
IK_PPPOE_TERMINATED = (1 << 5),
#if _WIZCHIP_ != W5200
IK_DEST_UNREACH = (1 << 6),
#endif
IK_IP_CONFLICT = (1 << 7),
IK_SOCK_0 = (1 << 8),
IK_SOCK_1 = (1 << 9),
IK_SOCK_2 = (1 << 10),
IK_SOCK_3 = (1 << 11),
#if _WIZCHIP_ > W5100S
IK_SOCK_4 = (1 << 12),
IK_SOCK_5 = (1 << 13),
IK_SOCK_6 = (1 << 14),
IK_SOCK_7 = (1 << 15),
#endif
#if _WIZCHIP_ > W5100S
IK_SOCK_ALL = (0xFF << 8)
#else
IK_SOCK_ALL = (0x0F << 8)
#endif
}intr_kind;
#define PHY_CONFBY_HW 0
#define PHY_CONFBY_SW 1
#define PHY_MODE_MANUAL 0
#define PHY_MODE_AUTONEGO 1
#define PHY_SPEED_10 0
#define PHY_SPEED_100 1
#define PHY_DUPLEX_HALF 0
#define PHY_DUPLEX_FULL 1
#define PHY_LINK_OFF 0
#define PHY_LINK_ON 1
#define PHY_POWER_NORM 0
#define PHY_POWER_DOWN 1
#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5500
typedef struct wiz_PhyConf_t
{
uint8_t by;
uint8_t mode;
uint8_t speed;
uint8_t duplex;
}wiz_PhyConf;
#endif
typedef enum
{
NETINFO_STATIC = 1,
NETINFO_DHCP
}dhcp_mode;
typedef struct wiz_NetInfo_t
{
uint8_t mac[6];
uint8_t ip[4];
uint8_t sn[4];
uint8_t gw[4];
uint8_t dns[4];
dhcp_mode dhcp;
}wiz_NetInfo;
typedef enum
{
#if _WIZCHIP_ == W5500
NM_FORCEARP = (1<<1),
#endif
NM_WAKEONLAN = (1<<5),
NM_PINGBLOCK = (1<<4),
NM_PPPOE = (1<<3),
}netmode_type;
typedef struct wiz_NetTimeout_t
{
uint8_t retry_cnt;
uint16_t time_100us;
}wiz_NetTimeout;
void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void));
void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void));
void reg_wizchip_bus_cbfunc(iodata_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, iodata_t wb));
void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb));
void reg_wizchip_spiburst_cbfunc(void (*spi_rb)(uint8_t* pBuf, uint16_t len), void (*spi_wb)(uint8_t* pBuf, uint16_t len));
int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg);
int8_t ctlnetwork(ctlnetwork_type cntype, void* arg);
void wizchip_sw_reset(void);
int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize);
void wizchip_clrinterrupt(intr_kind intr);
intr_kind wizchip_getinterrupt(void);
void wizchip_setinterruptmask(intr_kind intr);
intr_kind wizchip_getinterruptmask(void);
#if _WIZCHIP_ > W5100
int8_t wizphy_getphylink(void);
int8_t wizphy_getphypmode(void);
#endif
#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5500
void wizphy_reset(void);
void wizphy_setphyconf(wiz_PhyConf* phyconf);
void wizphy_getphyconf(wiz_PhyConf* phyconf);
void wizphy_getphystat(wiz_PhyConf* phyconf);
int8_t wizphy_setphypmode(uint8_t pmode);
#endif
void wizchip_setnetinfo(wiz_NetInfo* pnetinfo);
void wizchip_getnetinfo(wiz_NetInfo* pnetinfo);
int8_t wizchip_setnetmode(netmode_type netmode);
netmode_type wizchip_getnetmode(void);
void wizchip_settimeout(wiz_NetTimeout* nettime);
void wizchip_gettimeout(wiz_NetTimeout* nettime);
#ifdef __cplusplus
}
#endif
void w5500_regFunc(void);
#endif
这边IO库适配完毕 主函数还要再写写初始化W5500的代码 main.c
#include "main.h"
#include "spi.h"
#include "gpio.h"
#include "w5500.h"
#include "wizchip_conf.h"
#include "string.h"
#include "socket.h"
void SystemClock_Config(void);
static void w5500_hard_rst(void)
{
HAL_GPIO_WritePin(W5500_RST_GPIO_Port, W5500_RST_Pin, GPIO_PIN_RESET);
HAL_Delay(50);
HAL_GPIO_WritePin(W5500_RST_GPIO_Port, W5500_RST_Pin, GPIO_PIN_SET);
HAL_Delay(10);
}
static int w5500_chip_init(void)
{
return wizchip_init(NULL, NULL);
}
static void w5500_phy_init(void)
{
wiz_PhyConf conf;
conf.by = PHY_CONFBY_SW;
conf.mode = PHY_MODE_MANUAL;
conf.speed = PHY_SPEED_10;
conf.duplex = PHY_DUPLEX_FULL;
wizphy_setphyconf(&conf);
}
static void w5500_network_init(void)
{
wiz_NetInfo info;
uint8_t mac[6] = {0x02,0x00,0x00,0x01,0x02,0x03};
uint8_t ip[4] = {192,168,10,100};
uint8_t sn[4] = {255,255,255,0};
uint8_t gw[4] = {192,168,10,1};
uint8_t dns[4] = {0,0,0,0};
memcpy(info.mac, mac, 6);
memcpy(info.ip, ip, 4);
memcpy(info.sn, sn, 4);
memcpy(info.gw, gw, 4);
memcpy(info.dns, dns, 4);
info.dhcp = NETINFO_STATIC;
wizchip_setnetinfo(&info);
}
void w5500_init(void)
{
w5500_hard_rst();
w5500_regFunc();
if(w5500_chip_init()!=0)
{
while(1);
}
w5500_phy_init();
w5500_network_init();
wiz_NetInfo info;
wizchip_getnetinfo(&info);
}
uint8_t rxBuf[20]={0};
uint8_t rxBuf1[20]={0};
uint8_t rxBuf2[20]={0};
int main(void)
{
SCB_EnableICache();
SCB_EnableDCache();
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI3_Init();
w5500_init();
uint8_t remote_ip[4]={192,168,10,37};
uint16_t remote_port=6000;
uint16_t local_port=5000;
uint8_t remote_ip1[4]={192,168,10,38};
uint16_t remote_port1=6001;
uint16_t local_port1=5000;
uint16_t len=0;
uint16_t len1=0;
uint8_t buffff[]="Tx Via UDP0";
uint8_t buffff1[]="Tx Via UDP1";
while (1)
{
socket(0, Sn_MR_UDP, local_port, 0);
socket(1, Sn_MR_UDP, local_port1, 0);
sendto(0, buffff, sizeof(buffff), remote_ip, remote_port);
sendto(0, buffff1, sizeof(buffff), remote_ip1, remote_port1);
HAL_Delay(500);
switch(getSn_SR(0))
{
case SOCK_UDP:
{
if(getSn_IR(0) & Sn_IR_RECV)
{
setSn_IR(0, Sn_IR_RECV);
}
if((len=getSn_RX_RSR(0))>0)
{
memset(rxBuf,0,sizeof(rxBuf));
len = recvfrom(0,rxBuf, len, remote_ip,&remote_port);
if(remote_port==6000)
{
memset(rxBuf1,0,sizeof(rxBuf1));
memcpy(rxBuf1,rxBuf,len);
}
if(remote_port==6001)
{
memset(rxBuf2,0,sizeof(rxBuf2));
memcpy(rxBuf2,rxBuf,len);
}
}
}
}
switch(getSn_SR(1))
{
case SOCK_UDP:
{
if(getSn_IR(1) & Sn_IR_RECV)
{
setSn_IR(1, Sn_IR_RECV);
}
if((len1=getSn_RX_RSR(1))>0)
{
memset(rxBuf,0,sizeof(rxBuf));
len1 = recvfrom(1,rxBuf, len1, remote_ip1,&remote_port1);
}
}
}
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 5;
RCC_OscInitStruct.PLL.PLLN = 192;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 12;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI3;
PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
}
void Error_Handler(void)
{
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif
main.h
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32h7xx_hal.h"
void Error_Handler(void);
#define W5500_INIT_Pin GPIO_PIN_1
#define W5500_INIT_Port GPIOD
#define W5500_RST_Pin GPIO_PIN_0
#define W5500_RST_GPIO_Port GPIOD
#define W5500_CS_Pin GPIO_PIN_9
#define W5500_CS_GPIO_Port GPIOB
typedef int32_t s32;
typedef int16_t s16;
typedef int8_t s8;
typedef const int32_t sc32;
typedef const int16_t sc16;
typedef const int8_t sc8;
typedef __IO int32_t vs32;
typedef __IO int16_t vs16;
typedef __IO int8_t vs8;
typedef __I int32_t vsc32;
typedef __I int16_t vsc16;
typedef __I int8_t vsc8;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef const uint32_t uc32;
typedef const uint16_t uc16;
typedef const uint8_t uc8;
typedef __IO uint32_t vu32;
typedef __IO uint16_t vu16;
typedef __IO uint8_t vu8;
typedef __I uint32_t vuc32;
typedef __I uint16_t vuc16;
typedef __I uint8_t vuc8;
#ifdef __cplusplus
}
#endif
#endif
效果展示
ping通啦 UDP通信OK
W5500对常见UDP端口号与IP绑定的实现效果
这种场景要开两个socket
这种场景也是要开两个socket
这种开1个Socket就可以,但是对接收的UDP数据的IP端口号要判断下,分别处理,因为相同本地端口号一样,远端IP端口号不一样,可能如果远端IP不一样,端口一样,这种也是适用的
W5500的网络设置
同一局域网内,网关可以不设置,W5500对应的设置网关那个参数不管就可,DNS也是
static void w5500_network_init(void)
{
wiz_NetInfo info;
uint8_t mac[6] = {0x02,0x00,0x00,0x01,0x02,0x03};
uint8_t ip[4] = {192,168,10,100};
uint8_t sn[4] = {255,255,255,0};
memcpy(info.mac, mac, 6);
memcpy(info.ip, ip, 4);
memcpy(info.sn, sn, 4);
info.dhcp = NETINFO_STATIC;
wizchip_setnetinfo(&info);
}
|