返回列表 发新帖我要提问本帖赏金: 20.00元(功能说明)

[通信技术资料] 基于STM32的IPv4/IPv6 网关设计

[复制链接]
 楼主| abner_ma 发表于 2023-2-27 19:13 | 显示全部楼层 |阅读模式
<
#申请原创#
    最近项目开发需求,需要设备支持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


  1. #include "SPI.h"
  2. #include "w6100_init.h"
  3. void WIZ_SPI_Init(void)      //SPI 初始
  4. {
  5.         SPI_InitTypeDef   SPI_InitStructure;
  6.         GPIO_InitTypeDef GPIO_InitStructure;
  7.   RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE);
  8.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO , ENABLE);

  9.         /* Configure SPIy pins: SCK, MISO and MOSI */
  10.   GPIO_InitStructure.GPIO_Pin = WIZ_SCLK|  WIZ_MISO| WIZ_MOSI;
  11.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  13.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  14.        
  15.         /*Init WIZ_SCS*/
  16.   GPIO_InitStructure.GPIO_Pin =  WIZ_SCS;
  17.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  18.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  19.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  20.   GPIO_SetBits(GPIOA, WIZ_SCS);
  21.                 
  22.         /* SPI Config -------------------------------------------------------------*/
  23.                  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  24.           SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  25.           SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  26.           SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  27.           SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
  28.           SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  29.           SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  30.           SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  31.           SPI_InitStructure.SPI_CRCPolynomial = 7;

  32.           SPI_Init(SPI1, &SPI_InitStructure);
  33.           SPI_Cmd(SPI1, ENABLE);
  34. }

  35. void WIZ_CS(uint8_t val)
  36. {
  37.         if (val == LOW)
  38.         {
  39.                    GPIO_ResetBits(GPIOA, WIZ_SCS);
  40.         }
  41.         else if (val == HIGH)
  42.         {
  43.                    GPIO_SetBits(GPIOA, WIZ_SCS);
  44.         }
  45. }

  46. uint8_t SPI1_SendByte(uint8_t byte)
  47. {
  48.           while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
  49.          
  50.           SPI_I2S_SendData(SPI1, byte);
  51.          
  52.           while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
  53.          
  54.           return SPI_I2S_ReceiveData(SPI1);
  55. }


关键代码:

  1. #include "w6100.h"
  2. #include "SPI.h"
  3. #include <stdio.h>
  4. #include "w6100_init.h"

  5. #define _WIZCHIP_SPI_VDM_OP_    0x00
  6. #define _WIZCHIP_SPI_FDM_LEN1_  0x01
  7. #define _WIZCHIP_SPI_FDM_LEN2_  0x02
  8. #define _WIZCHIP_SPI_FDM_LEN4_  0x03
  9. //
  10. // If you want to use SPI FDM mode, Feel free contact to WIZnet.
  11. // http://forum.wiznet.io
  12. //

  13. #if _WIZCHIP_ == 6100
  14. ////////////////////////////////////////////////////////////////////////////////////////


  15. #define _W6100_SPI_OP_          _WIZCHIP_SPI_VDM_OP_

  16. /***
  17. *@brief: send data in BUS mode
  18. *@parame: addr: register address
  19. *         data: value write to register
  20. *@return: none
  21. *****/
  22. void IINCHIP_BusSendData(uint32_t addr,uint8_t data)
  23. {
  24.          *((volatile uint8_t*)addr) = data;

  25. }
  26. /***
  27. *@brief: read data in BUS mode
  28. *@parame: addr: register address
  29. *         data: value read from register
  30. *@return: register value
  31. *****/
  32. uint8_t IINCHIP_BusReadData(uint32_t addr)
  33. {
  34.          return *((volatile uint8_t*)addr) ;

  35. }

  36. /***
  37. *@brief:  pull down cs pin
  38. *@parame: none
  39. *@return: none
  40. *****/
  41. void IINCHIP_CSoff(void)
  42. {
  43.   WIZ_CS(LOW);
  44. }

  45. /***
  46. *@brief: pull up cs pin
  47. *@parame: none
  48. *@return: none
  49. *****/
  50. void IINCHIP_CSon(void)
  51. {
  52.    WIZ_CS(HIGH);
  53. }

  54. /***
  55. *@brief: send data in SPI mode
  56. *@parame: data: value write to register
  57. *@return: none
  58. *****/
  59. uint8_t IINCHIP_SpiSendData(uint8_t dat)
  60. {
  61.    return(SPI1_SendByte(dat));
  62. }


  63. //////////////////////////////////////////////////
  64. void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb )
  65. {
  66.    uint8_t tAD[4];
  67.    tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
  68.    tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
  69.    tAD[2] = (uint8_t)(AddrSel & 0x000000ff);
  70.    tAD[3] = wb;

  71.    //WIZCHIP_CRITICAL_ENTER();
  72.   // WIZCHIP.CS._s_e_l_e_c_t_();
  73.      IINCHIP_CSoff();
  74.        
  75. #if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_))
  76.     tAD[2] |= (_W6100_SPI_WRITE_ | _W6100_SPI_OP_);
  77.     //IINCHIP_SpiSendData( 0xf0);
  78.           IINCHIP_SpiSendData(tAD[0]);// Address byte 1
  79.     IINCHIP_SpiSendData(tAD[1] );// Address byte 2
  80.     IINCHIP_SpiSendData(tAD[2]);// Address byte 1
  81.     IINCHIP_SpiSendData(tAD[3] );// Address byte 2
  82.    

  83. #elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
  84.    IINCHIP_BusSendData(IDM_AR0 ,tAD[0] );
  85.          IINCHIP_BusSendData(IDM_AR1 ,tAD[1] );
  86.          IINCHIP_BusSendData(IDM_BSR ,tAD[2] );
  87.          IINCHIP_BusSendData(IDM_DR, tAD[3]);
  88. #else
  89.    #error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!"
  90. #endif
  91.    IINCHIP_CSon();
  92.   // WIZCHIP.CS._d_e_s_e_l_e_c_t_();
  93.   // WIZCHIP_CRITICAL_EXIT();
  94. }

  95. #define MODE_SPI  1
  96. #define MODE_BUS  0


  97. uint8_t  WIZCHIP_READ(uint32_t AddrSel)
  98. {
  99.    uint8_t ret;
  100.    uint8_t tAD[3];
  101.    tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
  102.    tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
  103.    tAD[2] = (uint8_t)(AddrSel & 0x000000ff);

  104.   // WIZCHIP_CRITICAL_ENTER();
  105.   // WIZCHIP.CS._s_e_l_e_c_t_();
  106. IINCHIP_CSoff();
  107. #if( (_WIZCHIP_IO_MODE_ ==  _WIZCHIP_IO_MODE_SPI_VDM_))
  108.    tAD[2] |= (_W6100_SPI_READ_ | _W6100_SPI_OP_);
  109.    IINCHIP_SpiSendData( tAD[0]);       
  110.    IINCHIP_SpiSendData( tAD[1]);
  111.    IINCHIP_SpiSendData( tAD[2]);        // 控制段
  112.    ret = IINCHIP_SpiSendData(0x00);      
  113. #elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
  114.    IINCHIP_BusSendData(IDM_AR0 ,tAD[0]);
  115.          IINCHIP_BusSendData(IDM_AR1 ,tAD[1]);
  116.          IINCHIP_BusSendData(IDM_BSR ,tAD[2] );
  117.          ret = IINCHIP_BusReadData(IDM_DR);
  118. #else
  119.    #error "Unknown _WIZCHIP_IO_MODE_ in W6100. !!!"   
  120. #endif

  121.   // WIZCHIP.CS._d_e_s_e_l_e_c_t_();
  122.   // WIZCHIP_CRITICAL_EXIT();
  123.          IINCHIP_CSon();
  124.    return ret;
  125. }

  126. void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, datasize_t len)
  127. {
  128.          uint16_t idx = 0;                // idx定义为正在写入的第几个数
  129.    uint8_t tAD[3];
  130.    tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
  131.    tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
  132.    tAD[2] = (uint8_t)(AddrSel & 0x000000ff);

  133.    IINCHIP_CSoff();  
  134.    // WIZCHIP_CRITICAL_ENTER();
  135.    //WIZCHIP.CS._s_e_l_e_c_t_();

  136. #if((_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_))
  137.    tAD[2] |= (_W6100_SPI_WRITE_ | _W6100_SPI_OP_);
  138.    //        printf("write\r\n");                                                                                                                               
  139.    if(len == 0) printf("Unexpected2 length 0\r\n");                        // 写入数据为空;len表示写入数据的长度
  140.    IINCHIP_SpiSendData( tAD[0]);                // 地址段,提供16位偏移地址(0000 0000 0000 0000)
  141.    IINCHIP_SpiSendData( tAD[1]);                // 控制段,共8位(0000 0000 高5位BSB位为00000表示通用寄存器)
  142.    IINCHIP_SpiSendData( tAD[2]);    // 控制段+4(0000 0100 RWB位置1表示写入,OM位为00表示SPI工作模式为VDM)
  143.    for(idx = 0; idx < len; idx++)                                                // 数据段,写入数据值
  144.    {
  145.      IINCHIP_SpiSendData( pBuf[idx]);                                                                                        // MCU通过SPI发送数据
  146.    }

  147. #elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
  148.    IINCHIP_BusSendData(IDM_AR0 ,tAD[0]);
  149.          IINCHIP_BusSendData(IDM_AR1 ,tAD[1]);
  150.                   IINCHIP_BusSendData(IDM_BSR ,tAD[2] );
  151.          for(idx = 0; idx < len; idx++)                // Write data in loop
  152.    {
  153.                  IINCHIP_BusSendData(IDM_DR, pBuf[idx]);
  154.          }
  155. #else
  156.    #error "Unknown _WIZCHIP_IO_MODE_ in W6100. !!!!"
  157. #endif

  158.   // WIZCHIP.CS._d_e_s_e_l_e_c_t_();
  159.   // WIZCHIP_CRITICAL_EXIT();
  160.         IINCHIP_CSon();
  161. }

  162. void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, datasize_t len)
  163. {
  164.    uint8_t tAD[3];
  165.          uint16_t idx = 0;               
  166.    tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16);
  167.    tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8);
  168.    tAD[2] = (uint8_t)(AddrSel & 0x000000ff);

  169.   // WIZCHIP_CRITICAL_ENTER();
  170.   // WIZCHIP.CS._s_e_l_e_c_t_();
  171.         IINCHIP_CSoff();        
  172. if(len == 0)                                                                                                                                                                // len定义为读取数据的长度
  173.   {       
  174.    // printf("Unexpected2 length 0\r\n");                                                                // 读取数据长度为0
  175.   }
  176. #if((_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_))
  177.    tAD[2] |= (_W6100_SPI_READ_ | _W6100_SPI_OP_);
  178.    IINCHIP_SpiSendData(tAD[0]);                // 地址段
  179.   IINCHIP_SpiSendData( tAD[1]);                // 控制段
  180.   IINCHIP_SpiSendData( tAD[2]);                    // 控制段
  181.   for(idx = 0; idx < len; idx++)                            // 数据段,读取数据值
  182.   {
  183.     pBuf[idx] = IINCHIP_SpiSendData(0x00);                                                        // 将MCU通过SPI发送过来的数据存放在buf数组中
  184.   }
  185. #elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
  186.    IINCHIP_BusSendData(IDM_AR0 ,tAD[0]);
  187.          IINCHIP_BusSendData(IDM_AR1 ,tAD[1]);
  188.                   IINCHIP_BusSendData(IDM_BSR ,tAD[2] );
  189.          for(idx = 0; idx < len; idx++)                // Write data in loop
  190.    {
  191.                  pBuf[idx] =IINCHIP_BusReadData(IDM_DR);
  192.          }
  193.        
  194. #else
  195.    #error "Unknown _WIZCHIP_IO_MODE_ in W6100. !!!!"
  196. #endif
  197.          IINCHIP_CSon();  
  198. }

  199. datasize_t getSn_TX_FSR(uint8_t sn)
  200. {
  201.    datasize_t prev_val=-1,val=0;
  202.    do
  203.    {
  204.       prev_val = val;
  205.       val = WIZCHIP_READ(W6100_Sn_TX_FSR_(sn));
  206.       val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(W6100_Sn_TX_FSR_(sn),1));
  207.    }while (val != prev_val);
  208.    return val;
  209. }

  210. datasize_t getSn_RX_RSR(uint8_t sn)
  211. {
  212.    datasize_t prev_val=-1,val=0;
  213.    do
  214.    {
  215.       prev_val = val;
  216.       val = WIZCHIP_READ(W6100_Sn_RX_RSR_(sn));
  217.       val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(W6100_Sn_RX_RSR_(sn),1));
  218.    }while (val != prev_val);
  219.    return val;
  220. }

  221. void wiz_send_data(uint8_t sn, uint8_t *wizdata, datasize_t len)
  222. {
  223.    datasize_t ptr = 0;
  224.    uint32_t addrsel = 0;
  225.    ptr = getSn_TX_WR(sn);
  226.    addrsel = ((uint32_t)ptr << 8) + WIZCHIP_TXBUF_BLOCK(sn);
  227.    WIZCHIP_WRITE_BUF(addrsel,wizdata, len);
  228.    ptr += len;
  229.    setSn_TX_WR(sn,ptr);
  230. }

  231. void wiz_recv_data(uint8_t sn, uint8_t *wizdata, datasize_t len)
  232. {
  233.    datasize_t ptr = 0;
  234.    uint32_t addrsel = 0;
  235.    if(len == 0) return;
  236.    ptr = getSn_RX_RD(sn);
  237.    addrsel = ((uint32_t)ptr << 8) + WIZCHIP_RXBUF_BLOCK(sn);
  238.    WIZCHIP_READ_BUF(addrsel, wizdata, len);
  239.    ptr += len;
  240.    setSn_RX_RD(sn,ptr);
  241. }

  242. void wiz_recv_ignore(uint8_t sn, datasize_t len)
  243. {
  244.    setSn_RX_RD(sn,getSn_RX_RD(sn)+len);
  245. }


  246. /// [url=home.php?mod=space&uid=1302964]@cond[/url] DOXY_APPLY_CODE
  247. #if (_PHY_IO_MODE_ == _PHY_IO_MODE_MII_)
  248. /// @endcond
  249. void wiz_mdio_write(uint8_t phyregaddr, uint16_t var)
  250. {
  251.    setPHYRAR(phyregaddr);
  252.    setPHYDIR(var);
  253.    setPHYACR(PHYACR_WRITE);
  254.    while(getPHYACR());  //wait for command complete
  255. }

  256. uint16_t wiz_mdio_read(uint8_t phyregaddr)
  257. {
  258.    setPHYRAR(phyregaddr);
  259.    setPHYACR(PHYACR_READ);
  260.    while(getPHYACR());  //wait for command complete
  261.    return getPHYDOR();
  262. }
  263. /// @cond DOXY_APPLY_CODE
  264. #endif
  265. /// @endcond

  266. ////////////////////////////////////////////////////////////////////////////////////////
  267. #endif
需要完成版程序可以跟我索取


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

打赏榜单

21ic小管家 打赏了 20.00 元 2023-03-13
理由:签约作者奖励

您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:项目经理
简介:资深嵌入式开发工程师

95

主题

181

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部