RT-Thread Studio环境下lwIP+ENC28J60的启用与调试

  手边有一块正点原子的MiniSTM32开发板,为了学习lwIP协议栈,网购了一块配套的ENC28J60模块,正点原子的ENC28J60模块有8只引出脚,而网上普通ENC28J60模块一般有10只引出脚,所以虽然贵些,但为了调试方便,也只好买原子家的了(和其开发板接口配套)。因为初接触lwIP,对其原理和配置还没完全搞明白,加上MiniSTM32开发板上使用的STM32F103RC内存只有48K,相对比较小,折腾了好几天(网上也查了不少资料,也没找到说明的很透彻)才调通,现把过程记录下来,以供刚接触lwIP和ENC28J60的人员参考。

  硬件连接说明,其连接如图1所示:
在这里插入图片描述

图1 硬件连接示意图

  “1”为ENC28J60模块,连接时注意方向不要弄错,“2”为USB供电开关,模块通过USB供电时必须按下,否则调试时会出现慕名奇妙的错误,只插上J-Link或ST-LINK插头时,板子上的电源指示灯也会亮,但debug时,因供电不足,会出错。“3”为USB转串口,MiniSTM32开发板有两个USB接口,此处的USB接头通过CH340G接STM32F103RC的UART1,用FinSH控制台调试时,通过此端口进行。“4”为J-Link或ST-LINK接口。

  工程的建立。打开RT-Thread Studio,选择“文件”–>“新建”–>“RT-Thread 项目”,在“Project name”中填入自己定义的工程名,然后按照下图对参数进行更改:
在这里插入图片描述

图2 工程配置

  芯片选择STM32F103RC,调试器按照自己的需求选择J-Link或ST-LINK,其他保持默认配置,选择好后点“完成”创建工程。

  接下来在工程中进行相关的软件包配置。在“项目资源管理器”中,双击“RT-Thread Settings”,打开软件配置中心。因ENC28J60和STM32的通信是基于SPI总线的,所以先进行SPI的配置,双击软件配置中心的“SPI”,在出来的选项中使能SPI总线和ENC28J60 SPI以太网接口,操作如图3所示:
在这里插入图片描述

图3 SPI总线及ENC28J60驱动使能

  配置完SPI总线后,再回到软件包中心配置lwIP协议栈,在SPI中选择“使用ENC28J60 SPI以太网接口”后,lwIP协议栈自动被选中,因两者存在依赖关系。因为STM32F103RCT6的内存只有48KB,所以在在lwIP中要尽量减少内存的占用,否自系统无法正常运行,重点需要修改以下几个选项,第一个为“PBUF的数量”,系统默认为16个,修改为8个,一个PBUF要占用1576个字节,而且是静态分配的,PBUF数量越多,接收速度就越快,但也越耗内存。第二个是“TCP发送窗口的大小”和“发送缓冲区的大小”,都由原来的8196字节修改为4096字节,这两项都是动态分配的,修改后能减少一半的内存占用。第三个是IP地址的配置,因本实验采用的ENC29J60模块通过普通网线和PC网口直连的方式进行测试的,没有DHCP服务器,所以要关闭“通过DHCP分配IP地址”而采用静态配置地址的方式,静态IP地址配置如下:
在这里插入图片描述

图4 静态IP地址的配置

  再次,要打开“使能ping功能”,还要在“网络接口设备”中选中"使能网络接口设备",以便启用ping和ifconfig调试功能。最后要说明下,在lwIP配置中,lwIP默认的版本是v2.0.2,还有两个版本可供选择:v1.4.1和v2.1.0,选择更新的v2.1.0版本也能正常工作,但不要选择v1.4.1版本,因为其和2.0版的lwIP接口变动较大,会导致ENC28J60驱动不能正常工作。至此,驱动的配置阶段完成,点击IDE中“保存”以完成工程配置的更改,其整个工程目录结构如下:
在这里插入图片描述

图5 工程目录结构

  图5中,标红的几个文件需要进行修改。首先修改SPI总线相关的宏定义,因在MiniSTM32的开发板上,ENC28J60模块是挂载在SPI1总线上的,所以在board.h中,要定义“#define BSP_USING_SPI1”,在 stm32xxxx_hal_config.h中,要定义“#define HAL_SPI_MODULE_ENABLED”(这两个宏在原文件中是存在的,只是被注释掉了,没启用,只要把注释去掉就行),这样才能启用SPI1总线。

  另外还需要增加SPI1总线的初始化函数,这要使用STM32CubeMX或STM32CubeIDE来生成,在STM32CubeMX中选择“STM32F103RC”,并使能SPI1,即可生成代码,我们只需要其中的HAL_SPI_MspInit()函数,其代码如下,如不熟悉STM32CubeMX,可直接拷贝下面的代码即可。

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
    
    
  GPIO_InitTypeDef GPIO_InitStruct = {
    
    0};
  if(hspi->Instance==SPI1)
  {
    
    
    /* 外设时钟使能 */
    __HAL_RCC_SPI1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**SPI1 GPIO 配置
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }
}

把上面的代码拷贝到board.c文件的末尾。

  在main.c中,把LOG_D(“Hello RT-Thread!”),移到while循环的上面,免得调试时在控制台不停出现"Hello RT-Thread!"而影响调试,至此代码的修改全部完成。

  接下来要编写ENC28J60的驱动接口函数,并注册到系统初始化流程中。首先对STM32F103RC和ENC28J60模块的引脚连接关系做个说明,ENC28J60模块有8个引脚,接在开发板的无线模块NRF24L01的接口上,其对应关系如下图所示:
在这里插入图片描述

图6 引脚对应关系
  SPI1的引脚,经过前面的配置,系统已完成对应pin的初始化,现在要关注ENC28J60的中断INT引脚(对接PA1)和片选引脚(对接PC4),因在RT-Thread的ENC28J60驱动中,采用软件复位,所以其硬件复位引脚(对接PA4)可不做配置。在工程的drivers目录中新建drv_enc28j60.c文件,把以下代码拷贝进去。
#include <drivers/pin.h>
#include <enc28j60.h>
#include <drv_spi.h>
#define ENC28J60_INT    1//PA1 ENC28J60中断
static int rt_hw_enc28j60_init(void)
{
    
    
        rt_hw_spi_device_attach("spi1", "spi10", GPIOC, GPIO_PIN_4);//PC4 ENC28J60片选CS
        enc28j60_attach("spi10");
        rt_pin_mode(ENC28J60_INT, PIN_MODE_INPUT_PULLUP);
        rt_pin_attach_irq(ENC28J60_INT, PIN_IRQ_MODE_FALLING, (void(*)(void*))enc28j60_isr, RT_NULL);
        rt_pin_irq_enable(ENC28J60_INT, PIN_IRQ_ENABLE);
}
INIT_COMPONENT_EXPORT(rt_hw_enc28j60_init);

  PA1对应的引脚号为1,可在driver目录下的drv_gpio.c的结构体pin_index中查询得到。rt_hw_spi_device_attach()函数在SPI1总线上注册一个名称为“spi10”的SPI设备,函数中的参数GPIOC、GPIO_PIN_4指定“spi10”设备的片选信号为PC4引脚。 enc28j60_attach(“spi10”)函数把ENC28J60模块挂载到“spi10”设备上,rt_pin_mode()、rt_pin_attach_irq()、rt_pin_irq_enable()三个函数分别用来设定中断引脚PA1的中断模式、中断处理函数和使能PA1引脚的中断。INIT_COMPONENT_EXPORT宏用来把rt_hw_enc28j60_init()加到初始化过程中,以便系统在启动后能自动进行lwIP和ENC28J60驱动的初始化。

  编译工程,结果显示Flash占用149KB,RAM占用33.8KB,没有超过STM32F103RC的FLASH和RAM的大小,并保留了约14.2KB(48-33.8)堆空间给系统动态分配使用。

  通过J-Link或ST-LINK下载至开发板,并用网线连接ENC28J60模块和PC的网口,PC网卡设置地址为:192.168.1.20,掩码:255.255.255.0,网关:192.168.1.1,注意要关闭Windows的防火墙,否则会出现ping不通的现象。最后用RT-Thread Studio自带的串行终端或其他的串口调试工具连接开发板,波特率设置为115200,在出现的"msh>"提示符下输入:ifconfig,可见如下结果:

msh >ifconfig
network interface device: e0 (Default)
MTU: 1500
MAC: 00 04 a3 12 34 56 
FLAGS: UP LINK_UP INTERNET_DOWN DHCP_DISABLE ETHARP BROADCAST IGMP
ip address: 192.168.1.100
gw address: 192.168.1.1
net mask  : 255.255.255.0
dns server #0: 0.0.0.0
dns server #1: 0.0.0.0

  在"msh>"提示符下输入:ping192.168.1.20,结果如下:

msh >ping 192.168.1.20
60 bytes from 192.168.1.20 icmp_seq=0 ttl=64 time=0 ms
60 bytes from 192.168.1.20 icmp_seq=1 ttl=64 time=3 ms
60 bytes from 192.168.1.20 icmp_seq=2 ttl=64 time=3 ms
60 bytes from 192.168.1.20 icmp_seq=3 ttl=64 time=2 ms

  至此,说明lwIP协议栈和ENC28J60模块的运行正常,使用和调试已完成,可进行更高级的网络应用学习了。

猜你喜欢

转载自blog.csdn.net/weixin_49364907/article/details/114273808