基于STM32F103RCT6 移植W5500 最新ioLibrary_Driver
1. ioLibrary_Driver
1.1 概述
The ioLibrary means “Internet Offload Library” for WIZnet chip. It includes drivers and application protocols. The driver (ioLibrary) can be used for the application design of WIZnet TCP/IP chips as W5500, W5300, W5200, W5100 W5100S.
1.2 ioLibrary下载
官方GitHub下载地址:https://github.com/Wiznet/ioLibrary_Driver
2. 如何将ioLibrary_Driver添加到你的项目中
下面我将介绍如何将ioLiberary移植到STM32F103项目中
2.1 硬件准备
- 正点原子MiniSTM32开发板(可以可以使用其他开发板),芯片为STM32F103RCT6。
- W5500模块(X宝卖的很多)。
- 下载ioLiberary_Driver源码,如图:
- 在正点原子MiniSTM32资料中拷贝一个 串口实验的源码(可以自己创建,拷贝目的是节省时间)。
2.2 代码移植
2.2.1 拷贝ioLiberary_Driver源码到项目目录中
2.2.2 将socket.c、wizchip_conf.c、w5500.c 3个文件添加到项目中
按照如图所示新建 组(Group) “W5500” 添加3个 C文件socket.c、wizchip_conf.c、w5500.c 。
添加相应的头文件目录到 Include Paths。
2.2.3 然后打开wizchip_conf.h 找到第75行(版本不一样可能有所差别,直接搜索也可以)
修改
#define _WIZCHIP_ W5100S // W5100, W5100S, W5200, W5300, W5500
为
#define _WIZCHIP_ W5500 // W5100, W5100S, W5200, W5300, W5500
如图:
编译代码,0错误0警告即可进行下一步。如果有错误先解决错误。
2.2.4 配置底层SPI 相关代码,实现读写等基础代码
W5500和STM32F103是通过SPI接口通信的,所以要配置底层SPI管脚功能及SPI工作模式。
硬件连接如下:
PA3 -> W5500_RST
PA4 -> W5500_SCS
PA5 -> W5500_SCK
PA6 -> W5500_MISO
PA7 -> W5500_MOSI
PA8 -> W5500_INT(非中断模式不用,如果使用中断模式,建议改用其他端口,mini板中被用作LED灯了)
增加spi初始化代码:
static void W5500_SPI_Init ( void )
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO, ENABLE );
/* 初始化CS引脚 */
GPIO_InitStructure.GPIO_Pin = W5500_SCS;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init ( W5500_SCS_PORT, &GPIO_InitStructure );
GPIO_SetBits ( W5500_SCS_PORT, W5500_SCS );
/* W5500_RST引脚初始化配置 */
GPIO_InitStructure.GPIO_Pin = W5500_RST;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init ( W5500_RST_PORT, &GPIO_InitStructure );
GPIO_SetBits ( W5500_RST_PORT, W5500_RST );
/* 初始化SCK、MISO、MOSI引脚 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init ( GPIOA, &GPIO_InitStructure );
GPIO_SetBits ( GPIOA, GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 );
/* 初始化配置STM32 SPI1 */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟悬空低
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //数据捕获于第1个时钟沿
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS由外部管脚管理
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; //波特率预分频值为2
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC多项式为7
SPI_Init ( SPI1, &SPI_InitStructure ); //根据SPI_InitStruct中指定的参数初始化外设SPI1寄存器
SPI_Cmd ( SPI1, ENABLE ); //STM32使能SPI1
}
2.2.5 注册回调函数
wizchip_conf.h 文件中,有几个回调注册函数,用于注册底层数据处理方法
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));
我们需要实现并注册
//SPI写入函数
void SPI1WriteByte ( 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;
}
//SPI读取函数
uint8_t SPI1ReadByte ( void )
{
while ( ( SPI1->SR & SPI_I2S_FLAG_TXE ) == 0 ); //等待发送区空
SPI1->DR = 0xFF; //发送一个空数据产生输入数据的时钟
while ( ( SPI1->SR & SPI_I2S_FLAG_RXNE ) == 0 ); //等待接收完一个byte
return SPI1->DR;
}
//片选函数
void SPI1_CS_Select ( void )
{
GPIO_ResetBits ( W5500_SCS_PORT, W5500_SCS );
}
//片选取消函数
void SPI1_CS_Deselect ( void )
{
GPIO_SetBits ( W5500_SCS_PORT, W5500_SCS );
}
//进入临界区函数
void SPI_CrisEnter ( void )
{
__set_PRIMASK ( 1 );
}
//退出临界区函数
void SPI_CrisExit ( void )
{
__set_PRIMASK ( 0 );
}
2.2.6 初始化网络配置
MAC、IP、Netmask、Gateway、DNS
//配置网络参数
void W5500_Network_Init ( void )
{
uint8_t chipid[6];
wiz_NetInfo gWIZNETINFO;
wiz_NetTimeout w_NetTimeout;
uint8_t mac[6] = {0x00, 0x08, 0xdc, 0x11, 0x11, 0x11}; ///< Source Mac Address
uint8_t ip[4] = {192, 168, 86, 150}; ///< Source IP Address
uint8_t sn[4] = {255, 255, 255, 0}; ///< Subnet Mask
uint8_t gw[4] = {192, 168, 86, 1}; ///< Gateway IP Address
uint8_t dns[4] = {8, 8, 8, 8}; ///< DNS server IP Address
memcpy ( gWIZNETINFO.ip, ip, 4 );
memcpy ( gWIZNETINFO.sn, sn, 4 );
memcpy ( gWIZNETINFO.gw, gw, 4 );
memcpy ( gWIZNETINFO.mac, mac, 6 );
memcpy ( gWIZNETINFO.dns, dns, 4 );
gWIZNETINFO.dhcp = NETINFO_STATIC; //< 1 - Static, 2 - DHCP
ctlnetwork ( CN_SET_NETINFO, ( void* ) &gWIZNETINFO );
ctlnetwork ( CN_GET_NETINFO, ( void* ) &gWIZNETINFO );
// Display Network Information
ctlwizchip ( CW_GET_ID, ( void* ) chipid );
printf ( "\r\n=== %s NET CONF ===\r\n", ( char* ) chipid );
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" );
wizchip_init ( NULL, NULL );
w_NetTimeout.retry_cnt = 50;
w_NetTimeout.time_100us = 1000;
wizchip_settimeout ( &w_NetTimeout );
}
到这里,主要的移植程序已经完成了。
2.3 测试
2.3.1 添加测试文件 loopback
将ioLibrary_Driver\Application文件夹中的loopback.c文件添加到工程
并将头文件目录添加到 Include Paths
2.3.2 添加主程序代码
主程序中添加如下代码
int main ( void )
{
uint8_t dest_ip[4] = {192, 168, 86, 99};
uint16_t dest_port = 8080;
uint8_t dataBuffer[DATA_BUF_SIZE] = {0x0};
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig ( NVIC_PriorityGroup_2 ); // 设置中断优先级分组2
uart_init ( 115200 ); //串口初始化为115200
printf ( "usart inited ......" );
LED_Init(); //初始化与LED连接的硬件接口
printf ( "LED inited ......" );
W5500_Init();
printf ( "W5500 inited ......" );
W5500_Init();
/* Infinite loop */
while ( 1 )
{
loopback_tcpc ( 0x0, dataBuffer, dest_ip, dest_port );
LED0 = 0;
delay_ms ( 50 );
LED0 = 1;
delay_ms ( 50 );
}
}
2.3.3 编译程序并下载到开发板中
编译过程中可能会缺少标准库,一般原子的工程都会放入完整的库,按需添加。所以,如果这里缺少标准库添加上即可。
下载程序到开发板中,连接好W5500模块,将电脑ip配置成192.168.86.99,用网线直连(通过路由连接也可以)。
2.3.4 测试网络通断情况:
打开命令窗口,执行命令 ping 192.168.86.150 -t
这样就说明W5500已经正常启动。
2.3.5 测试socket 连接
loopback 的代码中是将w5500设置为socket 客户端,并不断尝试连接服务器 192.168.86.99:8080
在电脑端打开网络助手,开启socketServer 端口8080,如果一切正常socket会自动连接
到这里移植包括测试就完成了
源码下载:https://download.csdn.net/download/aliuguangjin/12197757
下期博客我会继续讲在此基础上添加httpServer。