STM32移植lwip之官方工程修改

发布者:自在逍遥最新更新时间:2018-06-27 来源: eefocus关键字:STM32  移植lwip  工程修改 手机看文章 扫描二维码
随时随地手机看文章

本篇目标:在之前的硬件基础上,修改ST官方移植lwip的工程,使PC机能ping通stm32


材料准备:


硬件基础:stm32f407+lan9303

官方资料:包含代码和移植手册(stm32官方移植lwip资料)

修改代码:包含移植后的代码(STM32官方移植lwip修改代码)

跟着文件路径打开其中一个工程,先选择不带操作系统的练习测试 

文件路径:STM32F4x7_ETH_LwIP_V1.1.1 -> Project -> Standalone -> tcp_echo_server -> MDK-ARM -> Project.uvproj


先编译一下,出现3个Warning,其中两个是变量定义未使用,不影响暂且不管,还有一个是ethernetif.c文件最后没有空白行,手动添加一行,再次编译~ 

消除所有错误警告~成功开始的第一步~


从main函数开始理解并修改(英文为官方注释,中文为修改注释):


int main(void)

{

  /*!< At this stage the microcontroller clock setting is already configured to 

       168 MHz, this is done through SystemInit() function which is called from

       startup file (startup_stm32f4xx.s) before to branch to application main.

       To reconfigure the default setting of SystemInit() function, refer to

       system_stm32f4xx.c file

     */


  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);


#ifdef SERIAL_DEBUG

  DebugComPort_Init();  

#endif


  /*Initialize LCD and Leds */ 

  //LCD_LED_Init();    //硬件没有LCD,也暂时不用LED,将函数注释掉


  /* configure ethernet (GPIOs, clocks, MAC, DMA) */

  ETH_BSP_Config();    //MAC-PHY配置函数,主要理解修改函数


  /* Initilaize the LwIP stack */

  LwIP_Init();    //lwip初始化函数


  /* tcp echo server Init */

  //tcp_echoserver_init();    //tcp服务器建立函数,暂时只建立ping工程,将函数注释掉


  /* Infinite loop */

  while (1)

  {  

    /* check if any packet received */

    if (ETH_CheckFrameReceived())

    { 

      /* process received ethernet packet*/

      LwIP_Pkt_Handle();

    }

    /* handle periodic timers for LwIP*/

    LwIP_Periodic_Handle(LocalTime);

  } 

}


main函数中有两个修改:


注释 LCD_LED_Init() 函数,暂时用不到

注释 tcp_echoserver_init() 函数,暂时用不到

其次进入主要配置函数 ETH_BSP_Config() :


这个函数中修改的内容只有一个,找到 DP83848_PHY_ADDRESS 的宏定义(在 stm32f4x7_eth_bsp.h 的第52行),修改原先的 0x01 为 0x00 地址,那么这个地址是怎么来的,等到代码解析的时候再做解剖

函数中重点关注 ETH_GPIO_Config() 函数和 ETH_MACDMA_Config() ,这两个函数分别是配置RMII接口相关GPIO口的复用,配置MAC控制器和使能DMA

接着看 ETH_GPIO_Config() 函数: 

由于官方移植lwip用的是MII接口,而之前搭建的硬件接口是RMII,所以需要修改相关宏定义和 GPIO口的复用


void ETH_GPIO_Config(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;


    /* Enable GPIOs clocks */

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|

                           RCC_AHB1Periph_GPIOB|

                           RCC_AHB1Periph_GPIOC,

                           ENABLE);     //我们只用到了A,B,C三种引脚,所以修改成只使能A,B,C三个的时钟


  /* Enable SYSCFG clock */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); //使能SYSCFG外设时钟


  /* Configure MCO (PA8) */

  //配置PA8(做为MCO功能)输出时钟信号

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;  

  GPIO_Init(GPIOA, &GPIO_InitStructure);              



  /* MII/RMII Media interface selection --------------------------------------*/

#ifdef MII_MODE

 #ifdef PHY_CLOCK_MCO


  RCC_MCO1Config(RCC_MCO1Source_HSE, RCC_MCO1Div_1); //在PA8引脚上输出25MHZ的时钟信号

 #endif /* PHY_CLOCK_MCO */


  SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_MII);  //与PHY芯片通讯选择MII模式


#elif defined RMII_MODE  //这里要修改宏定义,注释MII_MODE,取消注释RMII_MODE,选择RMII接口模式与PHY芯片进行通讯 


  RCC_MCO1Config(RCC_MCO1Source_PLLCLK,RCC_MCO1Div_2); //添加时钟函数,在PA8引脚上输出50MHZ时钟信号


  SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII); //与PHY芯片通讯选择RMII模式

#endif


/* Ethernet pins configuration ************************************************/

   /*

        ETH_MDIO -------------------------> PA2

        ETH_MDC --------------------------> PC1

        ETH_RMII_REF_CLK------------------> PA1

        ETH_RMII_CRS_DV ------------------> PA7

        ETH_RMII_RXD0 --------------------> PC4

        ETH_RMII_RXD1 --------------------> PC5

        ETH_RMII_TX_EN -------------------> PB11

        ETH_RMII_TXD0 --------------------> PB12

        ETH_RMII_TXD1 --------------------> PB13

                                                  */

  //修改下面所有对GPIO的初始化为对应RMII接口GPIO的初始化,而RMII所用到的引脚在上面的列表中,共9个引脚

  /* Configure PA1, PA2 and PA7 */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_7;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH);

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH);

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH);


  /* Configure PB11,PB12 and PB13 */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_ETH);   

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_ETH);

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_ETH);


  /* Configure PC1, PC4 and PC5 */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH);

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH);

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH);

}


总结修改之前,先做一下RMII接口相关引脚的功课:


ETH_MDIO ————————> PA2

ETH_MDC ————————–> PC1

ETH_RMII_REF_CLK—————> PA1

ETH_RMII_CRS_DV —————> PA7

ETH_RMII_RXD0 ——————> PC4

ETH_RMII_RXD1 ——————> PC5

ETH_RMII_TX_EN —————–> PB11

ETH_RMII_TXD0 ——————> PB12

ETH_RMII_TXD1 ——————> PB13

修改总结:


修改GPIO时钟使能函数 RCC_AHB1PeriphClockCmd() ,因为只用到了ABC三个引脚,所以修改成只对A,B,C三个引脚进行时钟使能

修改宏定义,因为用的是RMII接口,所以要注释掉MII_MODE的宏定义,取消注释RMII_MODE的宏定义,这两个宏定义在main.h文件的79行和87行

添加配置PHY时钟函数 RCC_MCO1Config() ,添加在 #elif defined RMII_MODE 的下面即可

修改GPIO口初始化成RMII接口的GPIO,这里包括了对GPIOA,GPIOB,GPIOC的初始化以及将三个GPIO口的复用成RMII接口所用

接下来要来看 ETH_MACDMA_Config() 函数中的最后一个函数 ETH_Init() ,这个函数包含了所有MAC控制器相关初始化的配置,所以定位到这个函数 

stm32f4xf_eth.c第416行开始:


    /* Reset Timeout counter */

    timeout = 0;

    /* Read the result of the auto-negotiation */

//    RegValue = ETH_ReadPHYRegister(PHYAddress, PHY_SR);

    /* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */

//    if((RegValue & PHY_DUPLEX_STATUS) != (uint32_t)RESET)

//    {

      /* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */

      //注释掉其他所有内容,只留下下面两个函数:配置为全双工

      ETH_InitStruct->ETH_Mode = ETH_Mode_FullDuplex;  

//    }

//    else

//    {

      /* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */

//      ETH_InitStruct->ETH_Mode = ETH_Mode_HalfDuplex;           

//    }

    /* Configure the MAC with the speed fixed by the auto-negotiation process */

//    if(RegValue & PHY_SPEED_STATUS)

//    {  

      /* Set Ethernet speed to 10M following the auto-negotiation */

//      ETH_InitStruct->ETH_Speed = ETH_Speed_10M; 

//    }

//    else

//    {   

      /* Set Ethernet speed to 100M following the auto-negotiation */ 

      //注释掉其他所有内容,只留下下面两个函数:配置为100M以太网

      ETH_InitStruct->ETH_Speed = ETH_Speed_100M;

//    }


修改内容:


注释掉 stm32f4xf_eth.c 第416-441行的其他内容,只留下 ETH_InitStruct->ETH_Mode = ETH_Mode_HalfDuplex; 和 ETH_InitStruct->ETH_Speed = ETH_Speed_100M;

至此为止,代码修改结束,编译下载到板子上 

如果想要修改ip地址,可以找到main.h里面的宏定义:


/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */

#define IP_ADDR0   192

#define IP_ADDR1   168

#define IP_ADDR2   0

#define IP_ADDR3   10


修改成自己想要的IP地址便可以了,接下来用pc机来ping一下


ping之前,要确定两件事:


首先确定pc机连入的网络ip地址和stm32的ip地址是不是同一个网段: 

  1. 确定网段 
    这里192.168.0.1和192.168.0.10就处于同一个网段

  2. 其次如果是将stm32用网线接入路由器,则要确定stm32所使用的ip地址没有被占用,检测方法就是接入stm32前,先ping设定的地址,看能不能ping通,不能ping通表示没有被占用;这里是直接用网线连接stm32和pc机,所以不用担心这个问题


接下来可以用pc机ping下载好程序的stm32 
win+R打开运行,输入cmd,回车 
在命令行下输入ping 192.168.0.10 
ping通成功,有图有真相 
ping


总结: 
官方移植程序帮忙做了很多事情,可以方便使用,那么修改也不外乎这么几个地方,多多测试注意就可以成功,当能ping通,搭建好硬件软件环境之后就可以安心地一步步调用lwip的API接口函数建立服务器,客户端等等了。


关键字:STM32  移植lwip  工程修改 引用地址:STM32移植lwip之官方工程修改

上一篇:STM32F407VGT6+LAN8720 调试笔记
下一篇:STM32F407 以太网 外部提供时钟源的驱动修改错误总结

推荐阅读最新更新时间:2024-03-16 16:07

stm32使用三片74HC595级联程序代码
/************************************************************************ Function: Read_74HC595 Description: 读取n片74HC595的输入数据 Calls: HC595_delay;GPIO_ResetBits;GPIO_SetBits; Data Accessed: 无 Data Updated: 无 Input: HC595x:用户使用的595端口,类型定义在74HC595.h中 ChipNum: 用户使用的595端口上连接的芯片个数 Outp
[单片机]
STM32的内部Flash
说到STM32的FLSAH,我们的第一反应是用来装程序的,实际上,STM32的片内FLASH不仅用来装程序,还用来装芯片配置、芯片ID、自举程序等等。当然, FLASH还可以用来装数据。 自己收集了一些资料,现将这些资料总结了一下,不想看的可以直接调到后面看怎么操作就可以了。 FLASH分类 根据用途,STM32片内的FLASH分成两部分:主存储块、信息块。 主存储块用于存储程序,我们写的程序一般存储在这里。 信息块又分成两部分:系统存储器、选项字节。 系统存储器存储用于存放在系统存储器自举模式下的启动程序(BootLoader),当使用ISP方式加载程序时,就是由这个程序执行。这个区域由芯片厂写入BootL
[单片机]
STM32之高级定时器互补输出
#include stm32f10x.h /* RCC时钟配置 */ void RCC_config(void) { ErrorStatus HSEStartUpStatus; /* RCC寄存器设置为默认配置 */ RCC_DeInit(); /* 打开外部高速时钟 */ RCC_HSEConfig(RCC_HSE_ON); /* 等待外部高速时钟稳定 */ HSEStartUpStatus = RCC_WaitForHSEStartUp(); if(HSEStartUpStatus == SUCCESS) { /* 设置HCLK = SYSCLK */ RCC_HCLKConfig(RCC_SYSCLK_D
[单片机]
STM32(Cortex-M3)中有两个优先级的概念
STM32(Cortex-M3)中有两个优先级的概念 抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。 当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断
[单片机]
STM32开发笔记57: 复位电路设计
本篇文章针对所有的STM32芯片,网上有不少文章叙述了有关STM32复位电路的相关内容,也有很多推荐电路,例如ALIENTEK给出的复位电路,如下图所示。 不过还有一些推荐电路,不需加上拉电阻,或者电容也不加,那到底应该如何设计呢?还需看一下官方手册的推荐电路,如下图所示。 可看到,复位电路具有内部上拉电阻,外部只需接0.1uf电容即可,不需在外部电路上拉10K电阻,上拉后只会使上拉电阻变小,减小复位时间,或会导致复位不正常。内部上拉电阻阻值和其它参数如下表所示,供参考。
[单片机]
<font color='red'>STM32</font>开发笔记57: 复位电路设计
STM32之JTAG、SWD模式
说在前面的话 最近YKY项目做了新的硬件设计,其中键盘接口采用矩阵式键盘(4*4),有两个接口使用了STM32 (PB3、PB4), 调试中发现,这两个接口对应的两行均不能正常扫描到按键值,查看数据手册才知道这是系统接口,需要进行设置才可以 作为普通IO口使用。如图是数据手册对这两个接口的介绍: 解决方法 寄存器版本: 1 //JTAG模式设置,用于设置JTAG的模式 2 //mode:jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭; 3 //#define JTAG_SWD_DISABLE 0X02 4 //#define SWD_ENABLE 0X01
[单片机]
STM32备忘——GPIO的几种模式
GPIO的模式学习 GPIO的综合描述 讲述的内容比较详细 输出模式通常使用推挽输出模式:GPIO_Mode_Out_PP 只有使用输出模式时才能设置频率:GPIO_Speed 使用串口通常使用复用模式: 选择IO接口工作方式: GPIO_Mode_AIN 模拟输入 GPIO_Mode_IN_FLOATING 浮空输入 //USART串口通信输入模式 GPIO_Mode_IPD 下拉输入 //按键的输入 GPIO_Mode_IPU 上拉输入 //按键的输入 GPIO_Mode_Out_PP 推挽输出 //GPIO引脚输出模式 GPIO_Mode_Out_OD 开漏输出 GPIO_Mode_AF_PP 复用推
[单片机]
Event Recoder调试组件在stm32上的使用
本文目标:Event_Recoder调试组件在stm32上的使用 按照本文的描述,应该可以在你所处的硬件上跑通代码。 先决条件:装有编译和集成的开发环境,比如:Keil uVision5。 板子硬件要求:无,属于调试功能。 起源 因为做产品开发,设计东西有时候考虑得多,mcu的并没有多余的串口供使用调试,在调试一些初期进行验证时,必要的调试的打印信息是需要的。 Event Recoder调试组件简介 嵌入式的Event_Recoder调试组件是一种可以在MDK开发环境下使用的高级调试工具,它可以记录软件运行的一些标志信息,并以图形化的形式显示出来。它可以帮助你了解和分析内部操作,支持Keil RTX操作系统调试以及MDK自带的
[单片机]
Event Recoder调试组件在<font color='red'>stm32</font>上的使用
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved