最近项目开发需求,需要设备支持IPV6协议,用过,W5500。发现WIZnet 推出新款:W6100模组, 是一款支持 IPv4/IPv6 双核的新一代全硬件以太网 TCP/IP 协议栈控制器。W6100 在 WIZnet TCP/IP 协议栈 IPv4 的基础上增加了 IPv6,并且支持 TCP,UDP,IPv6,IPv4,ICMPv6,ICMPv4,IGMP,ARP 以及 PPPoE 等协议。同时其内部集成了 10/100M 以太网数据链路层(MAC)以及物理层(PHY),能够更加简单快速地实现嵌入式设备的联网功能。 IPv6三种转换技术当前,网站应用IPv6升级改造的技术路线主要有双栈、隧道和转换等三种技术。对嵌入式系统用单芯片解决。目前ESP32对IPV6支持。
武汉、西安、沈阳、南京、重庆、杭州、贵阳·贵安、福州8个互联网骨干直联点全部完成了IPv6升级改造,支持互联网间IPv6流量交换。加上2018年完成的北京、上海、广州、郑州、成都等5个骨干网直联点,我国全部13个骨干网直联点全部完成了IPv6改造。我国IPv6地址拥有数量稳定增加,截至2020年1月,我国已申请了47851块(/32)IPv6地址,位居世界第二。IPv6活跃用户量大幅提升。截至2020年1月,我国IPv6活跃用户数达2.7亿,占互联网网民总数的31%,相比行动计划实施前,增长了近100倍。全国已有11.93亿LTE用户、1.99亿固定网络用户,合计13.92亿用户获得了IPv6地址。
W6100 内部架构图:
STM32 SPI驱动: WIZ_SPI_Init
#include "SPI.h"
#include "w6100_init.h"
void WIZ_SPI_Init(void) //SPI 初始
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO , ENABLE);
/* Configure SPIy pins: SCK, MISO and MOSI */
GPIO_InitStructure.GPIO_Pin = WIZ_SCLK| WIZ_MISO| WIZ_MOSI;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*Init WIZ_SCS*/
GPIO_InitStructure.GPIO_Pin = WIZ_SCS;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, WIZ_SCS);
/* SPI Config -------------------------------------------------------------*/
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Cmd(SPI1, ENABLE);
}
void WIZ_CS(uint8_t val)
{
if (val == LOW)
{
GPIO_ResetBits(GPIOA, WIZ_SCS);
}
else if (val == HIGH)
{
GPIO_SetBits(GPIOA, WIZ_SCS);
}
}
uint8_t SPI1_SendByte(uint8_t byte)
{
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, byte);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPI1);
}
关键代码:
#include "w6100.h"
#include "SPI.h"
#include <stdio.h>
#include "w6100_init.h"
#define _WIZCHIP_SPI_VDM_OP_ 0x00
#define _WIZCHIP_SPI_FDM_LEN1_ 0x01
#define _WIZCHIP_SPI_FDM_LEN2_ 0x02
#define _WIZCHIP_SPI_FDM_LEN4_ 0x03
//
// If you want to use SPI FDM mode, Feel free contact to WIZnet.
// http://forum.wiznet.io
//
#if _WIZCHIP_ == 6100
#define _W6100_SPI_OP_ _WIZCHIP_SPI_VDM_OP_
/***
*@brief: send data in BUS mode
*@parame: addr: register address
* data: value write to register
*@return: none
*****/
void IINCHIP_BusSendData(uint32_t addr,uint8_t data)
{
*((volatile uint8_t*)addr) = data;
}
/***
*@brief: read data in BUS mode
*@parame: addr: register address
* data: value read from register
*@return: register value
*****/
uint8_t IINCHIP_BusReadData(uint32_t addr)
{
return *((volatile uint8_t*)addr) ;
}
/***
*@brief: pull down cs pin
*@parame: none
*@return: none
*****/
void IINCHIP_CSoff(void)
{
WIZ_CS(LOW);
}
/***
*@brief: pull up cs pin
*@parame: none
*@return: none
*****/
void IINCHIP_CSon(void)
{
WIZ_CS(HIGH);
}
/***
*@brief: send data in SPI mode
*@parame: data: value write to register
*@return: none
*****/
uint8_t IINCHIP_SpiSendData(uint8_t dat)
{
return(SPI1_SendByte(dat));
}
//
void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb )
{
uint8_t tAD[4];
tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
tAD[2] = (uint8_t)(AddrSel & 0x000000ff);
tAD[3] = wb;
//WIZCHIP_CRITICAL_ENTER();
// WIZCHIP.CS._s_e_l_e_c_t_();
IINCHIP_CSoff();
#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_))
tAD[2] |= (_W6100_SPI_WRITE_ | _W6100_SPI_OP_);
//IINCHIP_SpiSendData( 0xf0);
IINCHIP_SpiSendData(tAD[0]);// Address byte 1
IINCHIP_SpiSendData(tAD[1] );// Address byte 2
IINCHIP_SpiSendData(tAD[2]);// Address byte 1
IINCHIP_SpiSendData(tAD[3] );// Address byte 2
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
IINCHIP_BusSendData(IDM_AR0 ,tAD[0] );
IINCHIP_BusSendData(IDM_AR1 ,tAD[1] );
IINCHIP_BusSendData(IDM_BSR ,tAD[2] );
IINCHIP_BusSendData(IDM_DR, tAD[3]);
#else
#error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!"
#endif
IINCHIP_CSon();
// WIZCHIP.CS._d_e_s_e_l_e_c_t_();
// WIZCHIP_CRITICAL_EXIT();
}
#define MODE_SPI 1
#define MODE_BUS 0
uint8_t WIZCHIP_READ(uint32_t AddrSel)
{
uint8_t ret;
uint8_t tAD[3];
tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
tAD[2] = (uint8_t)(AddrSel & 0x000000ff);
// WIZCHIP_CRITICAL_ENTER();
// WIZCHIP.CS._s_e_l_e_c_t_();
IINCHIP_CSoff();
#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_))
tAD[2] |= (_W6100_SPI_READ_ | _W6100_SPI_OP_);
IINCHIP_SpiSendData( tAD[0]);
IINCHIP_SpiSendData( tAD[1]);
IINCHIP_SpiSendData( tAD[2]); // 控制段
ret = IINCHIP_SpiSendData(0x00);
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
IINCHIP_BusSendData(IDM_AR0 ,tAD[0]);
IINCHIP_BusSendData(IDM_AR1 ,tAD[1]);
IINCHIP_BusSendData(IDM_BSR ,tAD[2] );
ret = IINCHIP_BusReadData(IDM_DR);
#else
#error "Unknown _WIZCHIP_IO_MODE_ in W6100. !!!"
#endif
// WIZCHIP.CS._d_e_s_e_l_e_c_t_();
// WIZCHIP_CRITICAL_EXIT();
IINCHIP_CSon();
return ret;
}
void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, datasize_t len)
{
uint16_t idx = 0; // idx定义为正在写入的第几个数
uint8_t tAD[3];
tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
tAD[2] = (uint8_t)(AddrSel & 0x000000ff);
IINCHIP_CSoff();
// WIZCHIP_CRITICAL_ENTER();
//WIZCHIP.CS._s_e_l_e_c_t_();
#if((_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_))
tAD[2] |= (_W6100_SPI_WRITE_ | _W6100_SPI_OP_);
// printf("write\r\n");
if(len == 0) printf("Unexpected2 length 0\r\n"); // 写入数据为空;len表示写入数据的长度
IINCHIP_SpiSendData( tAD[0]); // 地址段,提供16位偏移地址(0000 0000 0000 0000)
IINCHIP_SpiSendData( tAD[1]); // 控制段,共8位(0000 0000 高5位BSB位为00000表示通用寄存器)
IINCHIP_SpiSendData( tAD[2]); // 控制段+4(0000 0100 RWB位置1表示写入,OM位为00表示SPI工作模式为VDM)
for(idx = 0; idx < len; idx++) // 数据段,写入数据值
{
IINCHIP_SpiSendData( pBuf[idx]); // MCU通过SPI发送数据
}
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
IINCHIP_BusSendData(IDM_AR0 ,tAD[0]);
IINCHIP_BusSendData(IDM_AR1 ,tAD[1]);
IINCHIP_BusSendData(IDM_BSR ,tAD[2] );
for(idx = 0; idx < len; idx++) // Write data in loop
{
IINCHIP_BusSendData(IDM_DR, pBuf[idx]);
}
#else
#error "Unknown _WIZCHIP_IO_MODE_ in W6100. !!!!"
#endif
// WIZCHIP.CS._d_e_s_e_l_e_c_t_();
// WIZCHIP_CRITICAL_EXIT();
IINCHIP_CSon();
}
void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, datasize_t len)
{
uint8_t tAD[3];
uint16_t idx = 0;
tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
tAD[2] = (uint8_t)(AddrSel & 0x000000ff);
// WIZCHIP_CRITICAL_ENTER();
// WIZCHIP.CS._s_e_l_e_c_t_();
IINCHIP_CSoff();
if(len == 0) // len定义为读取数据的长度
{
// printf("Unexpected2 length 0\r\n"); // 读取数据长度为0
}
#if((_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_))
tAD[2] |= (_W6100_SPI_READ_ | _W6100_SPI_OP_);
IINCHIP_SpiSendData(tAD[0]); // 地址段
IINCHIP_SpiSendData( tAD[1]); // 控制段
IINCHIP_SpiSendData( tAD[2]); // 控制段
for(idx = 0; idx < len; idx++) // 数据段,读取数据值
{
pBuf[idx] = IINCHIP_SpiSendData(0x00); // 将MCU通过SPI发送过来的数据存放在buf数组中
}
#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
IINCHIP_BusSendData(IDM_AR0 ,tAD[0]);
IINCHIP_BusSendData(IDM_AR1 ,tAD[1]);
IINCHIP_BusSendData(IDM_BSR ,tAD[2] );
for(idx = 0; idx < len; idx++) // Write data in loop
{
pBuf[idx] =IINCHIP_BusReadData(IDM_DR);
}
#else
#error "Unknown _WIZCHIP_IO_MODE_ in W6100. !!!!"
#endif
IINCHIP_CSon();
}
datasize_t getSn_TX_FSR(uint8_t sn)
{
datasize_t prev_val=-1,val=0;
do
{
prev_val = val;
val = WIZCHIP_READ(W6100_Sn_TX_FSR_(sn));
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(W6100_Sn_TX_FSR_(sn),1));
}while (val != prev_val);
return val;
}
datasize_t getSn_RX_RSR(uint8_t sn)
{
datasize_t prev_val=-1,val=0;
do
{
prev_val = val;
val = WIZCHIP_READ(W6100_Sn_RX_RSR_(sn));
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(W6100_Sn_RX_RSR_(sn),1));
}while (val != prev_val);
return val;
}
void wiz_send_data(uint8_t sn, uint8_t *wizdata, datasize_t len)
{
datasize_t ptr = 0;
uint32_t addrsel = 0;
ptr = getSn_TX_WR(sn);
addrsel = ((uint32_t)ptr << 8) + WIZCHIP_TXBUF_BLOCK(sn);
WIZCHIP_WRITE_BUF(addrsel,wizdata, len);
ptr += len;
setSn_TX_WR(sn,ptr);
}
void wiz_recv_data(uint8_t sn, uint8_t *wizdata, datasize_t len)
{
datasize_t ptr = 0;
uint32_t addrsel = 0;
if(len == 0) return;
ptr = getSn_RX_RD(sn);
addrsel = ((uint32_t)ptr << 8) + WIZCHIP_RXBUF_BLOCK(sn);
WIZCHIP_READ_BUF(addrsel, wizdata, len);
ptr += len;
setSn_RX_RD(sn,ptr);
}
void wiz_recv_ignore(uint8_t sn, datasize_t len)
{
setSn_RX_RD(sn,getSn_RX_RD(sn)+len);
}
/// [url=home.php?mod=space&uid=1302964]@cond[/url] DOXY_APPLY_CODE
#if (_PHY_IO_MODE_ == _PHY_IO_MODE_MII_)
/// @endcond
void wiz_mdio_write(uint8_t phyregaddr, uint16_t var)
{
setPHYRAR(phyregaddr);
setPHYDIR(var);
setPHYACR(PHYACR_WRITE);
while(getPHYACR()); //wait for command complete
}
uint16_t wiz_mdio_read(uint8_t phyregaddr)
{
setPHYRAR(phyregaddr);
setPHYACR(PHYACR_READ);
while(getPHYACR()); //wait for command complete
return getPHYDOR();
}
/// @cond DOXY_APPLY_CODE
#endif
/// @endcond
#endif
---------------------
作者:abner_ma
链接:https://bbs.21ic.com/icview-3287028-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。