工程源码下载:基于裸机和Freertos的W5500网络通信工程

目录

1. 移植W5500步骤

2. Cobemx配置步骤

2.1 时钟配置Clock Configuration

2.2 Trace and Debug配置

2.3 使能CPU ICache与DCache

2.4 USART配置

2.5 硬件SPI配置

2.6 GPIO的LED配置

2.7 烧录程序时注意

2.8 FREERTOS配置

2.9 下载程序后不能运行

2.10 提升编译速度

2.11 下载完程序自动启动

3. W5500硬件连接

3.1 初始化SPI

3.2 初始化GPIO

4. W5500程序移植

4.1 修改wizchip_conf.h文件

5. 我们要实现的函数bsp_spi_w5500.c

5.1 W5500芯片复位

5.2 将SPI函数进行与W5500进行注册

5.3 收发缓存设置

5.4 获取芯片ID

5.5 设置网络配置

5.6 读取网络配置

5.7 配置超时

5.8 打印配置信息

6. 实验现象


1. 移植W5500步骤

  1. 初始化SPI引脚
  2. 初始化SCS引脚(片选)
  3. 下载官方库文件
  4. 添加官方库到工程目录
  5. 实现SPI接口和库文件的对接
  6. 调用官方库提供的函数实现连接

2. Cobemx配置步骤

2.1 时钟配置Clock Configuration

所使用的单片机是正点原子的阿波罗底板STM32H743IIT6。

我们看原理图是再29.30引脚接的25MHz的无源晶振。

RCC 配置界面。以外部时钟为例,STM32CubeMX中外部时钟配置可选类型为

Disable

BYPASS Clock Source(旁路时钟源)

Crystal/Ceramic Resonator(石英/陶瓷 晶振)

三种类型,参考手册也将链接电路展示出来了,我们这里用的是无源晶振,故选择第三个方案。

H743凭借外部晶振的加持,最高主频可以达到480MHz。

呢么我们就通过配置时钟树使H743发挥出它最佳状态。

STM32H7 主频在 400~480MHz 下,SPI1,SPI2 和 SPI3 的最高时钟是 200MHz,而 SPI4,5,6 是 100MHz。这里特别注意一点,SPI 工作时最少选择二分频,也就是说 SPI1,2,3 实际通信时钟是100MHz

2.2 Trace and Debug配置

2.3 使能CPU ICache与DCache

STM32F7使用CubeMX生产代码时,可以在Cortex-M7设置里选择是否开启ART ACCLERATOR,ICache,DCache等,如下图

2.4 USART配置

配置调试串口,确定物理引脚PA10\PA9。

时钟配置完成以后,可以在 Connectivity 栏开启UART功能,USART1可以开启的模式有Asynchronous——异步通讯、synchronous——同步通讯、Single Wire(Half-Duplex)——单线(半双工)通讯,此处配置为异步通讯。

2.5 硬件SPI配置

 

2.6 GPIO的LED配置

PB0和PB1对应开发板LED0和LED1。

2.7 烧录程序时注意

为什么SWD烧录STM32时BOOT0脚要接高电平,否则SWD下载失败。

对配置的程序进行测试测试成功。

2.8 FREERTOS配置

2.9 下载程序后不能运行

进行软件仿真的时候寻踪按键需要执行三次程序测能启动,每次仿真程序都停留在:

解决办法:

记得将Uis Micro LIB勾选。

2.10 提升编译速度

在CobeMX生成的freertos之后,如果我们选择V6编译器会出现很多编译错误,解决办法是:

替换这两个文件,替换的路径如下:

Middlewares\Third_Party\FreeRTOS\Source\portable\RVDS\ARM_CM4F

替换之后编译就不会报错,而且在Browse information勾选的情况下快速编译。

链接在我提供的程序源文件里面:

2.11 下载完程序自动启动

3. W5500硬件连接

10个引脚中,真正使用的也就只有vcc gnd miso mosi sclk scs 这几个脚,RST和int引脚如果是引用官方的库的话,是不需要的(RST是复位引脚,INT是中断触发引脚)。我们这次也需要用到RST引脚。

3.1 初始化SPI

因为W5500模块内部自己实现了TCP/IP协议,在外部只需要通过提供的接口利用SPI把相关的参数传递进去就行了,比如物理地址,本机IP,本机端口,目标端口,目标IP等等。

3.2 初始化GPIO

除去SPI口之外还有一个片选引脚SCS,这个引脚很重要,在官方协议实现的4个函数中,起到的很关键的作用。同时也初始化了复位引脚。

#define CSPin(n)    (n? HAL_GPIO_WritePin(SPI1_CS_GPIO_Port,SPI1_CS_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(SPI1_CS_GPIO_Port,SPI1_CS_Pin,GPIO_PIN_RESET))
#define RSTNPin(n)  (n? HAL_GPIO_WritePin(SPI1_RST_GPIO_Port,SPI1_RST_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(SPI1_RST_GPIO_Port,SPI1_RST_Pin,GPIO_PIN_RESET))

4. W5500程序移植

最新程序下载网址如下:

https://github.com/Wiznet/ioLibrary_Driver

我们解压后需要下面几个

下面介绍以下主要的功能:

application/loopback是一个回环测试的示例程序。
Internet里则是上层多种协议的驱动程序。

socket.c 文件夹里面主要是socket的一些函数,比如close connect socket等等函数,实现了一些应用层的封装
w5500.c 文件主要实现的是对W5500模块寄存器的读写和操作,包括读写那些寄存器,地址是多少等等,
wizchip_conf.c 就是一个公共文件主要包括和SPI的连接以及连接W5500读写寄存器函数和socket函数。有用户用于注册函数的几个api以及配置W5X00的一些驱动函数。
DHCP.c 主要就是初始化DHCP,启动DHCP,获取ip,端口等函数

4.1 修改wizchip_conf.h文件

5. 我们要实现的函数bsp_spi_w5500.c

首先根据提供的结构体,将我们要定义的网络配置信息进行赋值:

static wiz_NetInfo NetConf = {.mac = {0x0c, 0x29, 0xab, 0x7c, 0x04, 0x02}, //mac地址.ip = {192, 168, 0, 215},                   //本机IP地址.sn = {255, 255, 255, 0},                   //子网掩码.gw = {192, 168, 0, 1},                     //网关地址.dns = {0, 0, 0, 0},                         //DNS服务器地址.dhcp = NETINFO_STATIC                        //使用静态IP
};

这个结构体存在于wizchip_conf.c,其中NetConf是一个wiz_NetInfo类型的结构体变量,该结构体在wizchip_conf.h中定义,用于设置mac地址、IP地址等网络参数,具体如下:

typedef struct wiz_NetInfo_t
{uint8_t mac[6];  ///< Source Mac Addressuint8_t ip[4];   ///< Source IP Addressuint8_t sn[4];   ///< Subnet Mask uint8_t gw[4];   ///< Gateway IP Addressuint8_t dns[4];  ///< DNS server IP Addressdhcp_mode dhcp;  ///< 1 - Static, 2 - DHCP
}wiz_NetInfo;

接下来我们就要编写网络初始化的配置函数,先把程序贴出来,然后再慢慢分解:

void set_w5500_conf(void)
{reset();//芯片复位//注册函数,用户通过实现SPI注册回调函数来访问WIZCHPreg_wizchip_cris_cbfunc(SPI_CrisEnter, SPI_CrisExit);   //注册临界区函数 reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);  //注册SPI片选信号函数reg_wizchip_spi_cbfunc(SPI_ReadByte, SPI_WriteByte);    //注册读写函数
/***********************物理层配置*************************///初始化芯片参数ctlwizchip(CW_RESET_WIZCHIP,(void *)0);//软件重置uint8_t memsize[16] = {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};uint8_t tmp;//WIZCHIP SOCKET缓存区初始化 ctlwizchip(CW_INIT_WIZCHIP, &memsize);//PHY物理层连接状态检查ctlwizchip(CW_GET_PHYLINK, (void*)&tmp);
/*******************获取芯片ID********************/uint8_t id[6];//获取芯片IDctlwizchip(CW_GET_ID,(void*)id);//获取ID/*******************设置网络配置********************/    ctlnetwork(CN_SET_NETINFO, (void*)&NetConf);/*******************读取网络配置********************/wiz_NetInfo conf;ctlnetwork(CN_GET_NETINFO, (void*)&conf); //读取设置网络状态  if(memcmp(&conf,&NetConf,sizeof(wiz_NetInfo)) == 0){printf("set network parameters success");// 配置成功}else{printf("set network parameters fail"); // 配置失败}
/*******************配置超时********************/   wiz_NetTimeout timeout;timeout.retry_cnt = 8;   // 重试次数,默认8次timeout.time_100us = 2000; // 超时时间,默认2000*100us = 200mswizchip_settimeout(&timeout);/*******************打印配置信息********************/     printf("w5500 network infomation:\r\n");printf("w5500 -mac:%d:%d:%d:%d:%d:%d\r\n", conf.mac[0], conf.mac[1], conf.mac[2], conf.mac[3], conf.mac[4], conf.mac[5]);printf("w5500 -ip:%d.%d.%d.%d\r\n", conf.ip[0], conf.ip[1], conf.ip[2], conf.ip[3]);printf("w5500 -sn:%d.%d.%d.%d\r\n", conf.sn[0], conf.sn[1], conf.sn[2], conf.sn[3]);printf("w5500 -gw:%d.%d.%d.%d\r\n", conf.gw[0], conf.gw[1], conf.gw[2], conf.gw[3]);printf("w5500 -dns:%d.%d.%d.%d\r\n", conf.dns[0], conf.dns[1], conf.dns[2], conf.dns[3]);}  

5.1 W5500芯片复位

   reset();//芯片复位
void reset()
{RSTNPin(0);HAL_Delay(100);RSTNPin(1);HAL_Delay(1500);
}

5.2 将SPI函数进行与W5500进行注册

   //注册函数,用户通过实现SPI注册回调函数来访问WIZCHPreg_wizchip_cris_cbfunc(SPI_CrisEnter, SPI_CrisExit);   //注册临界区函数 reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);  //注册SPI片选信号函数reg_wizchip_spi_cbfunc(SPI_ReadByte, SPI_WriteByte);    //注册读写函数

在spi里实现一些函数,然后把函数名赋值给wizchip_conf.c里面的一些函数指针,这样W5500.c里面的函数实现读写的时候,就能够直接使用SPI接口了,具体实现的函数有以下6个。

void SPI1_WriteByte(u8 TxData)
uint8_t  SPI1_ReadByte()
void SPI_CrisEnter(void)
void SPI_CrisExit(void)
void SPI_CS_Select(void)
void SPI_CS_Deselect(void)

/*** @brief  写1字节数据到SPI总线* @param  TxData 写到总线的数据* @retval None*/
void SPI_WriteByte(uint8_t TxData)
{               HAL_SPI_Transmit(&SPI_HANDLE, &TxData, 1, 0xFF);
}
/*** @brief  从SPI总线读取1字节数据* @retval 读到的数据*/
uint8_t SPI_ReadByte(void)
{           uint8_t send = 0xff;uint8_t recv;HAL_SPI_TransmitReceive(&SPI_HANDLE, &send, &recv, 1, 0xff);return recv;
}
/*** @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)
{CSPin(0); //低电平有效
}
/*** @brief  片选信号输出高电平* @retval None*/
void SPI_CS_Deselect(void)
{CSPin(1);
}

实现了这几个函数之后,需要把他们注册到库函数里面,利用函数指针对上述函数进行调用。

前面说了库文件wizchip_conf.c 里面就包括了和SPI口的对接实现指针函数。例如:

void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb))
{while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_));if(!spi_rb || !spi_wb){WIZCHIP.IF.SPI._read_byte   = wizchip_spi_readbyte;WIZCHIP.IF.SPI._write_byte  = wizchip_spi_writebyte;}else{WIZCHIP.IF.SPI._read_byte   = spi_rb;WIZCHIP.IF.SPI._write_byte  = spi_wb;}
}

5.3 收发缓存设置

分别指定16个端口上收和发缓冲区的大小(KB),收和发分别加起来不能超过16K。默认每个端口的收发端口分别为2K。

/***********************物理层配置*************************///初始化芯片参数ctlwizchip(CW_RESET_WIZCHIP,(void *)0);//软件重置uint8_t memsize[16] = {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};uint8_t tmp;//WIZCHIP SOCKET缓存区初始化 ctlwizchip(CW_INIT_WIZCHIP, &memsize);//PHY物理层连接状态检查ctlwizchip(CW_GET_PHYLINK, (void*)&tmp);

5.4 获取芯片ID

id里是固定的 “W5500”。

/*******************获取芯片ID********************/uint8_t id[6];//获取芯片IDctlwizchip(CW_GET_ID,(void*)id);//获取ID

5.5 设置网络配置

/*******************设置网络配置********************/    ctlnetwork(CN_SET_NETINFO, (void*)&NetConf);

5.6 读取网络配置

/*******************读取网络配置********************/wiz_NetInfo conf;ctlnetwork(CN_GET_NETINFO, (void*)&conf); //读取设置网络状态  if(memcmp(&conf,&NetConf,sizeof(wiz_NetInfo)) == 0){printf("set network parameters success");// 配置成功}else{printf("set network parameters fail"); // 配置失败}

配置成功会串口打印

5.7 配置超时

如发起tcp链接、发送数据等的时候,如果一段时间没有答复(即超过超时时间),W5500会重发,直到超过重试次数还没有得到答复,就会触发超时中断。

/*******************配置超时********************/   wiz_NetTimeout timeout;timeout.retry_cnt = 8;   // 重试次数,默认8次timeout.time_100us = 2000; // 超时时间,默认2000*100us = 200mswizchip_settimeout(&timeout);

5.8 打印配置信息

加在配置网络函数内void set_w5500_ip(void),配置完成即可通过串口进行打印。

/*******************打印配置信息********************/     printf("w5500 network infomation:\r\n");printf("  -mac:%d:%d:%d:%d:%d:%d\r\n", conf.mac[0], conf.mac[1], conf.mac[2], conf.mac[3], conf.mac[4], conf.mac[5]);printf("  -ip:%d.%d.%d.%d\r\n", conf.ip[0], conf.ip[1], conf.ip[2], conf.ip[3]);printf("  -sn:%d.%d.%d.%d\r\n", conf.sn[0], conf.sn[1], conf.sn[2], conf.sn[3]);printf("  -gw:%d.%d.%d.%d\r\n", conf.gw[0], conf.gw[1], conf.gw[2], conf.gw[3]);printf("  -dns:%d.%d.%d.%d\r\n", conf.dns[0], conf.dns[1], conf.dns[2], conf.dns[3]);

6. 实验现象

网络配置到这里就算完成了,将这个函数进行初始化后就可以ping通了。

【STM32CubeMX】STM32H7-RTOS-SPI-W5500相关推荐

  1. 【stm32CubeMX】STM32F103c8t6串口通信

    [stm32CubeMX]STM32F103c8t6串口通信发送'hello windows' 一.串口通信协议 1.UART协议 2.RS-232 3.RS-485 二.USB转TTL 三.配置Cu ...

  2. 【STM32CubeMX】教程二_IIC驱动0.96oled屏幕(SSD1306)

    [STM32CubeMX]教程二_IIC驱动0.96oled屏幕(SSD1306) 文章目录 [STM32CubeMX]教程二_IIC驱动0.96oled屏幕(SSD1306) 前言 一.IIC通讯 ...

  3. 【嵌入式】STM32实现SPI双机通信的一些细节(2)片选总结

    [嵌入式]STM32实现SPI双机通信的一些细节(2)SPI软硬件片选总结 SPI片选总结 坑爹的手册示意图 理想中的硬件片选 主机软件片选就对了 从机硬件片选 从机软件片选 代码 主机软件片选SPI ...

  4. 【STM32】基于STM32CubeIDE SPI+DMA驱动WS2812

    [STM32]基于STM32CubeIDE SPI+DMA驱动WS2812 ✨申明:本文章仅发表在CSDN网站,任何其他网见此内容均为盗链和爬取,请多多尊重和支持原创!

  5. 【嵌入式】MCU(HC32F460)+SPI接口LCD液晶屏ILI9341 移植emWin记录1----点亮LCD屏

    目录 一 SPI屏的接线 二 SPI屏驱动初始化 三 SPI屏点亮 四 附录 一 SPI屏的接线 SPI屏的特点在于接线简单,只需要四根SPI线以及几个GPIO口即可驱动工作,但是由于非并口的,所以当 ...

  6. 【STM32】HAL库 SPI DMA UART驱动开发

    零.瞎BB一些 最近真的是.....过得...些许艰难... 从实习到正式入职,在公司的项目组待了3个月左右了,同事.项目.代码.逻辑.架构都熟悉了,毕业后入职1个月的时间里,能给项目组改了几个bug ...

  7. 【stm32cubeMX】使用HAL库点亮LED流水灯

    stm32cubeMX使用HAL库点亮LED流水灯 1.安装STM32CubeMX 2.安装HAL库 3.新建项目 4.keil仿真调试 五.实现 六.参考资料 1.安装STM32CubeMX 官网下 ...

  8. 【STM32Cube_17】使用硬件SPI驱动TFT-LCD(ST7789)

    上一篇:[STM32Cube_16]使用硬件CRC校验数据(以SHT30为例) 寻求更好的阅读体验,请移步:Mculover666的个人博客. 本篇详细的记录了如何使用STM32CubeMX配置STM ...

  9. 【Esp32】Esp32+sx1268 Spi接口驱动SX1268模块

    [Esp32]Spi接口驱动SX1268模块 0. 实验结果 1.原理解析 2.硬件接线 3. SX1268 模块的 SPI 时序分析 4. 基于 ESP32 实现函数封装 4.1 读寄存器 4.2 ...

  10. 【STM32CubeMX】NRF24L01模块实现“1对1“及“1对多“无线通信

      大家好,我是小政.本篇文章我将针对NRF24L01模块实现"1对1"及"1对多"无线通信的STM32CubeMX配置过程进行详细的讲解,让准备学习HAL库的 ...

最新文章

  1. liunx php redis扩展,CentOS 7下安装php-redis扩展及简单使用
  2. 百度地图 点聚合_强强联合聚能网约车场景 首汽约车为百度地图“站台”
  3. OPatch cannot find a valid oraInst.loc file to locate Central Inventory
  4. cloud-init 工作原理 - 每天5分钟玩转 OpenStack(171)
  5. 利达主机联网接线端子_门禁主机接门锁和开门按钮方法
  6. 有限覆盖定理证明区间套_圆内整点问题的开普勒猜想证明,关于圆内整点问题误差项的估值E(r)=1-x,x=sin(nx)...
  7. clob类型字段最大存储长度_请教oracle的CLOB字段的最大长度?
  8. OCR识别之图像预处理
  9. azw3转换为pdf_干货:如何Java 将 Word 文档转换为 PDF
  10. java迷宫实训报告_Java综合实训报告-迷宫.doc
  11. 【DVRP】基于matlab蚁群算法求解带距离的VRP问题【含Matlab源码 1040期】
  12. OpenSSL常用命令总结
  13. 使用select2 宽度自适应
  14. Android心电图动画效果,手把手教你打造一个心电图效果View Android自定义View
  15. Pgadmin4转圈圈无法进入到界面(pgadmin v4一直卡在loading页面)
  16. 如何用sql profile 找出执行慢的sql
  17. Kaggle泰坦尼克号-决策树Top 3%-0基础代码详解
  18. USB-C(TYPE-C)接口安卓手机直播方案/同时直播跟充电的方案
  19. 浅谈《网络数据安全标准体系建设指南》(征求意见稿)的意见(附全文)
  20. ios项目传到github_使用GitHub Actions将iOS应用程序部署到TestFlight或App Store

热门文章

  1. javascript解析json格式的数据
  2. sonos one和play1对比哪个好?评测sonos one和play1区别是什么?
  3. php 开源 内容管理,RQCMS - 内容管理CMS - PHP开源项目 - 开源吧
  4. 关于kendo.ui父页面调用子页面的方法问题
  5. 【自动化测试经验谈】字节8年自动化测试工程师成长之路
  6. 线性表的链式存储结构及代码实现(单链表,双链表,循环链表)
  7. 编译原理3 - 词法分析
  8. matlab - patch 画渐变色的曲线图
  9. 第一次前后端联合开发项目总结
  10. HYSBZ3110-K大数查询