原创 如何移植使用W5500官方提供的最新Socket库

2015-6-1 17:14 922 26 26 分类: 通信 文集: TCP/IP芯片

转载自:http://www.embed-net.com/thread-55-1-1.html

官方提供了W5500的最新驱动库,下载地址如下:
http://wizwiki.net/wiki/doku.php?id=products:w5500:driver
下面简单介绍下如何使用这套库
首先下载库源码,文件目录如下所示:

我们主要用到Ethernet文件夹下面的文件,将这些文件加入到自己的工程中,然后编译,若编译出现类似于如下错误
..\User\Ethernet\wizchip_conf.c(113): error:  #29: expected an expression
.id                  = _WIZCHIP_ID_,
..\User\Ethernet\wizchip_conf.c(114): error:  #29: expected an expression
.if_mode             = _WIZCHIP_IO_MODE_,
..\User\Ethernet\wizchip_conf.c(115): error:  #29: expected an expression
.CRIS._enter         = wizchip_cris_enter,
..\User\Ethernet\wizchip_conf.c(116): error:  #29: expected an expression
.CRIS._exit          = wizchip_cris_exit,
..\User\Ethernet\wizchip_conf.c(117): error:  #29: expected an expression
.CS._select          = wizchip_cs_select,
..\User\Ethernet\wizchip_conf.c(118): error:  #29: expected an expression
.CS._deselect        = wizchip_cs_deselect,
..\User\Ethernet\wizchip_conf.c(119): error:  #29: expected an expression
.IF.BUS._read_byte   = wizchip_bus_readbyte,
..\User\Ethernet\wizchip_conf.c(120): error:  #29: expected an expression
.IF.BUS._write_byte  = wizchip_bus_writebyte
..\User\Ethernet\wizchip_conf.c(123): warning:  #12-D: parsing restarts here after previous syntax error
};
..\User\Ethernet\wizchip_conf.c: 1 warning, 8 errors
则需要根据自己的编译器做下设置,keil MDK设置如下所示:

主要原因是Keil MDK默认设置不支持按照结构体名称初始化结构体的原因导致。

W5500和MCU是通过SPI接口通信的,库是利用如下结构体中的相关函数指针实现SPI通信和其他功能。

_WIZCHIP  WIZCHIP =
      {
      .id                  = _WIZCHIP_ID_,
      .if_mode             = _WIZCHIP_IO_MODE_,
      .CRIS._enter         = wizchip_cris_enter,
      .CRIS._exit          = wizchip_cris_exit,
      .CS._select          = wizchip_cs_select,
      .CS._deselect        = wizchip_cs_deselect,
      .IF.BUS._read_byte   = wizchip_bus_readbyte,
      .IF.BUS._write_byte  = wizchip_bus_writebyte
//    .IF.SPI._read_byte   = wizchip_spi_readbyte,
//    .IF.SPI._write_byte  = wizchip_spi_writebyte
      };
 
 
根据函数名字和库中的注释,我们这里也对要实现的函数做个简单的说明
wizchip_cris_enter :进入临界区的函数,可以不管
wizchip_cris_exit :退出临界区的函数,也可以不管
wizchip_cs_select :输出有效片选信号的函数,也就是控制CS输出低电平的函数,必须实现
wizchip_cs_deselect :控制CS输出高电平的函数,必须实现
wizchip_bus_readbyte :SPI总线读取一字节数据函数,必须实现
wizchip_bus_writebyte :SPI总线写一字节数据函数,必须实现根据以上可知,只要实现了SPI的基本操作,移植基本完成,是不是很简单

 

下面我们就新建一个spi.c的文件来实现这几个函数,当然这些函数名字可以不和这个结构体里面的函数名字一样,到时候可以调用相关的函数注册下即可
 
/**
  ******************************************************************************
  * @file    spi.c
  * $Author: 飞鸿踏雪 $
  * $Revision: 17 $
  * $Date:: 2014-10-25 11:16:48 +0800 #$
  * @brief   SPI驱动函数实现.
  ******************************************************************************
  * @attention
  *
  *<h3><center>© Copyright 2009-2012, EmbedNet</center>
  *<center>http://www.embed-net.com</center>
  *<center>All Rights Reserved</center></h3>
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
 
/**
  * @brief  使能SPI时钟
  * @retval None
  */
static void SPI_RCC_Configuration(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1,ENABLE);
}
/**
  * @brief  配置指定SPI的引脚
  * @retval None
  */
static void SPI_GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    //PA4->CS,PA5->SCK,PA6->MISO,PA7->MOSI                          
    GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_5 | GPIO_Pin_6|GPIO_Pin_7;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    //初始化片选输出引脚
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    GPIO_SetBits(GPIOA,GPIO_Pin_4);
}
/**
  * @brief  根据外部SPI设备配置SPI相关参数
  * @retval None
  */
void SPI_Configuration(void)
{
    SPI_InitTypeDef SPI_InitStruct;
 
    SPI_RCC_Configuration();
 
    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
    SPI_InitStruct.SPI_Direction= SPI_Direction_2Lines_FullDuplex;
    SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
    SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStruct.SPI_CRCPolynomial = 7;
    SPI_Init(SPI1,&SPI_InitStruct);
    
    SPI_GPIO_Configuration();
 
    SPI_SSOutputCmd(SPI1, ENABLE);
    SPI_Cmd(SPI1, ENABLE);
}
/**
  * @brief  写1字节数据到SPI总线
  * @param  TxData 写到总线的数据
  * @retval None
  */
void SPI_WriteByte(uint8_t TxData)
{               
    while((SPI1->SR&SPI_I2S_FLAG_TXE)==0);   //等待发送区空         
    SPI1->DR=TxData;                                         //发送一个byte
    while((SPI1->SR&SPI_I2S_FLAG_RXNE)==0); //等待接收完一个byte 
    SPI1->DR;       
}
/**
  * @brief  从SPI总线读取1字节数据
  * @retval 读到的数据
  */
uint8_t SPI_ReadByte(void)
{           
    while((SPI1->SR&SPI_I2S_FLAG_TXE)==0);   //等待发送区空             
    SPI1->DR=0xFF;                                               //发送一个空数据产生输入数据的时钟
    while((SPI1->SR&SPI_I2S_FLAG_RXNE)==0); //等待接收完一个byte 
    return SPI1->DR;                            
}
/**
  * @brief  进入临界区
  * @retval None
  */
void SPI_CrisEnter(void)
{
    __set_PRIMASK(1);
}
/**
  * @brief  退出临界区
  * @retval None
  */
void SPI_CrisExit(void)
{
    __set_PRIMASK(0);
}
 
/**
  * @brief  片选信号输出低电平
  * @retval None
  */
void SPI_CS_Select(void)
{
    GPIO_ResetBits(GPIOA,GPIO_Pin_4);
}
/**
  * @brief  片选信号输出高电平
  * @retval None
  */
void SPI_CS_Deselect(void)
{
    GPIO_SetBits(GPIOA,GPIO_Pin_4);
}
/*********************************END OF FILE**********************************/
 
到这里,移植基本上完成。
但是这些SPI的接口函数如何跟这套库衔接呢?不用怕,库提供有这样的函数来注册,只要在主函数中调用下就可以了,具体程序如下
// First of all, Should register SPI callback functions implemented by user for accessing WIZCHIP

 

    /* Critical section callback */
    reg_wizchip_cris_cbfunc(SPI_CrisEnter, SPI_CrisExit);   //注册临界区函数
    /* Chip selection call back */
#if   _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_
    reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);//注册SPI片选信号函数
#elif _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_FDM_
    reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);  // CS must be tried with LOW.
#else
   #if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SIP_) != _WIZCHIP_IO_MODE_SIP_
      #error "Unknown _WIZCHIP_IO_MODE_"
   #else
      reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect);
   #endif
#endif
    /* SPI Read & Write callback function */
    reg_wizchip_spi_cbfunc(SPI_ReadByte, SPI_WriteByte);    //注册读写函数
 
 
到这里,移植工程基本完成,下面我们就将官方提供的一个loopback的测试程序移植到我们自己的工程中来,基本上也没做什么修改,下面是测试工程用到的几个测试函数
 
 
继续阅读:http://www.embed-net.com/thread-55-1-1.html

文章评论0条评论)

登录后参与讨论
我要评论
0
26
关闭 站长推荐上一条 /2 下一条