如何移植使用W5500官方提供的最新Socket庫
文章來源:http://www.embed-net.com/thread-55-1-1.html
(此論壇為一個WIZnet使用者開設的,論壇積累了大量的W5500相關應用及例程,具有很大的參考價值。)
官方提供了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><a
href="http:\\[url]www.embed-net.com[/url]">[url]http://www.embed-net.com[/url]</a></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);
//註冊讀寫函式
/**
*
@brief Intialize the network information to be used in WIZCHIP
*
@retval None
*/
void
network_init(
void
)
{
uint8_t
tmpstr[6];
ctlnetwork(CN_SET_NETINFO,
(
void
*)&gWIZNETINFO);
ctlnetwork(CN_GET_NETINFO,
(
void
*)&gWIZNETINFO);
//
Display Network Information
ctlwizchip(CW_GET_ID,(
void
*)tmpstr);
printf
(
"\r\n===
%s NET CONF ===\r\n"
,(
char
*)tmpstr);
printf
(
"MAC:
%02X:%02X:%02X:%02X:%02X:%02X\r\n"
,gWIZNETINFO.mac[0],gWIZNETINFO.mac[1],gWIZNETINFO.mac[2],
gWIZNETINFO.mac[3],gWIZNETINFO.mac[4],gWIZNETINFO.mac[5]);
printf
(
"SIP:
%d.%d.%d.%d\r\n"
,
gWIZNETINFO.ip[0],gWIZNETINFO.ip[1],gWIZNETINFO.ip[2],gWIZNETINFO.ip[3]);
printf
(
"GAR:
%d.%d.%d.%d\r\n"
,
gWIZNETINFO.gw[0],gWIZNETINFO.gw[1],gWIZNETINFO.gw[2],gWIZNETINFO.gw[3]);
printf
(
"SUB:
%d.%d.%d.%d\r\n"
,
gWIZNETINFO.sn[0],gWIZNETINFO.sn[1],gWIZNETINFO.sn[2],gWIZNETINFO.sn[3]);
printf
(
"DNS:
%d.%d.%d.%d\r\n"
,
gWIZNETINFO.dns[0],gWIZNETINFO.dns[1],gWIZNETINFO.dns[2],gWIZNETINFO.dns[3]);
printf
(
"======================\r\n"
);
}
/**
*
@brief Loopback Test Example Code using ioLibrary_BSD
*
@retval None
*/
int32_t
loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port)
{
int32_t
ret;
uint16_t
size = 0, sentsize=0;
switch
(getSn_SR(sn))
{
case
SOCK_ESTABLISHED
:
if
(getSn_IR(sn)
& Sn_IR_CON)
{
printf
(
"%d:Connected\r\n"
,sn);
setSn_IR(sn,Sn_IR_CON);
}
if
((size
= getSn_RX_RSR(sn)) > 0)
{
if
(size
> DATA_BUF_SIZE) size = DATA_BUF_SIZE;
ret
= recv(sn,buf,size);
if
(ret
<= 0)
return
ret;
sentsize
= 0;
while
(size
!= sentsize)
{
ret
= send(sn,buf+sentsize,size-sentsize);
if
(ret
< 0)
{
close(sn);
return
ret;
}
sentsize
+= ret;
//
Don't care SOCKERR_BUSY, because it is zero.
}
}
break
;
case
SOCK_CLOSE_WAIT
:
printf
(
"%d:CloseWait\r\n"
,sn);
if
((ret=disconnect(sn))
!= SOCK_OK)
return
ret;
printf
(
"%d:Closed\r\n"
,sn);
break
;
case
SOCK_INIT
:
printf
(
"%d:Listen,
port [%d]\r\n"
,sn,
port);
if
(
(ret = listen(sn)) != SOCK_OK)
return
ret;
break
;
case
SOCK_CLOSED:
printf
(
"%d:LBTStart\r\n"
,sn);
if
((ret=socket(sn,Sn_MR_TCP,port,0x00))
!= sn)
return
ret;
printf
(
"%d:Opened\r\n"
,sn);
break
;
default
:
break
;
}
return
1;
}
/**
*
@brief Loopback Test Example Code using ioLibrary_BSD
*
@retval None
*/
int32_t
loopback_udps(uint8_t sn, uint8_t* buf, uint16_t port)
{
int32_t
ret;
uint16_t
size, sentsize;
uint8_t
destip[4];
uint16_t
destport;
//uint8_t
packinfo = 0;
switch
(getSn_SR(sn))
{
case
SOCK_UDP
:
if
((size
= getSn_RX_RSR(sn)) > 0)
{
if
(size
> DATA_BUF_SIZE) size = DATA_BUF_SIZE;
ret
= recvfrom(sn,buf,size,destip,(uint16_t*)&destport);
if
(ret
<= 0)
{
printf
(
"%d:
recvfrom error. %ld\r\n"
,sn,ret);
return
ret;
}
size
= (uint16_t) ret;
sentsize
= 0;
while
(sentsize
!= size)
{
ret
= sendto(sn,buf+sentsize,size-sentsize,destip,destport);
if
(ret
< 0)
{
printf
(
"%d:
sendto error. %ld\r\n"
,sn,ret);
return
ret;
}
sentsize
+= ret;
//
Don't care SOCKERR_BUSY, because it is zero.
}
}
break
;
case
SOCK_CLOSED:
printf
(
"%d:LBUStart\r\n"
,sn);
if
((ret=socket(sn,Sn_MR_UDP,port,0x00))
!= sn)
return
ret;
printf
(
"%d:Opened,
port [%d]\r\n"
,sn,
port);
break
;
default
:
break
;
}
return
1;
}
/**
*
@brief Loopback Test Example Code using ioLibrary_BSD
*
@retval None
*/
void
platform_init(
void
)
{
SystemInit();
//系統時鐘初始化
USART_Configuration();
//串列埠1初始化
printf
(
"\x0c"
);
printf
(
"\x0c"
);
//超級終端清屏
printf
(
"\033[1;40;32m"
);
//設定超級終端背景為黑色,字元為綠色
printf
(
"\r\n*******************************************************************************"
);
printf
(
"\r\n************************
Copyright 2009-2014, EmbedNet ************************"
);
printf
(
"\r\n***************************
[url]http://www.embed-net.com[/url] **************************"
);
printf
(
"\r\n*****************************
All Rights Reserved *****************************"
);
printf
(
"\r\n*******************************************************************************"
);
printf
(
"\r\n"
);
//Config
SPI
SPI_Configuration();
//延時初始化
delay_init();
}
能ping通,看來沒什麼大問題了
程式原始碼下載:請參考文章上方原文連結。
相關文章
- 2.12.uboot的移植2-從uboot官方標準uboot開始移植boot
- ncurses庫移植
- Socket相關程式:從Windows移植到LinuxWindowsLinux
- 最新MT6739移植資料下載
- Matlab最新的官方文件中文翻譯Matlab
- SAP官方提供的人臉識別APIAPI
- Web Socket在Chrome最新版引入WebChrome
- Docker官方私有倉庫registry的安裝和使用Docker
- socket基本的API使用API
- Python HOWTOs 官方文件:Socket 程式設計Python程式設計
- MT6739 Sensor最新移植資料下載
- 聊聊如何解決官方提供的onpremise專案安裝sentry速度過慢問題REM
- YAHOO工具庫提供的方法
- 教你如何閱讀Oracle資料庫官方文件Oracle資料庫
- 虹軟人臉識別——官方 Qt Demo 移植到 LinuxQTLinux
- Vue-Socket.io的使用Vue
- 最新的官方底部導航輪子——BottomNavigationViewNavigationView
- 使用 ISAR 資料庫提供離線 Flutter 支援資料庫Flutter
- IBM 官方宣佈提供 INFORMIX 免費版本IBMORM
- Vue入門指南-03 vue官方提供的指令 (快速上手vue)Vue
- 移植了ortp庫之後的初體驗
- 如何優雅的移植JavaScript元件到BlazorJavaScript元件Blazor
- 如何講CMAndroid移植到你的裝置?Android
- WIFI wpa_supplicant的移植和使用(3)WiFi
- socket在python下的使用Python
- W5500多節點連線
- 安裝微軟官方提供的win 10 PE 系統到U盤微軟
- 最快的演算法alphablend彙編原始碼,Intel官方提供(轉)演算法原始碼Intel
- 【MCU】移植AT32庫&FreeRTOS教程
- socket動態庫專案
- 使用 SSH 移植 Conda 環境
- 解決 CentOS 7 官方 yum 倉庫無法使用的最佳實踐CentOS
- WebBits庫如何使用Web
- 如何使用htmltab庫HTML
- 如何使用grequests庫
- 如何使用Guzzle庫
- 如何使用RCurl庫
- 資料移植到Oracle資料庫(一)Oracle資料庫