手把手在原子F407开发板上搭建TCP服务器及TFTP服务器实现IAP功能

2019-07-20 02:06发布

本帖最后由 513393302@qq.com 于 2017-7-24 10:22 编辑

声明:原贴http://www.stmcu.org/module/foru ... 1&extra=#pid2273351
也是本人写的,为了方便原子F407的朋友,所以在这里重新写了一遍,修改了部分错别字。

非常感谢STM32以太网在线培训,真的让我学到非常多,没培训前很想搞以太网但有种无从下手的感觉,经过这次培训让我从这个架构上有个从上到下的了解,再借助官方神器STM32CubeMX,开发和学习起来还是非常快的!我手上没有官方的板子,带以太网的只有原子的F407的板子,所以也是在这个平台上做的,板子上的PHY为LAN8720A,没有用到显示屏全为串口输出调试信息。
实现功能:通过STM32CubeMX在原子F407板子上搭建TCP Server 及 TFTP Server (实现IAP功能),实现这些功能非常简单。
一、功能介绍
  1、TCP Server 实现显示连接上的客户端IP及对客户端发来的数据回传
  2、TFTP Server 实现IAP功能及读取MCU内部FLASH数据。这里用到的是文件传输协议,主要是参考官方文档UM1709,及官方STM324xG_EVAL的LWIP IAP例子。
二、工程搭建
1、外设配置打开STM32CubeMX,点NEW PROJECT,在左侧的输入框中输入407ZG,在右侧会显示STM32F407ZGT6的MCU列表,选择此列表,双击。
设置时钟源为外部时钟
QQ截图20170724092452.png
开启SWD调试接口,开启ETH外设,选择RMII接口(LAN8720A为RMII接口),中间件里时能LWIP。使用RMII接口的时候软件会自动配置对应的引脚,但是一定要仔细对比软件配置的引脚是否为板子上硬件所连接的。
QQ截图20170724100521.png

原子F407板子上的LAN8720A的RMII接口引脚如下图,

而软件配置的引脚如下:

显然与实际板子上的硬件连接不同,这里需要手动调整3个引脚,分别为:
  ETH_TX_EN -> PG11
  ETH_TXD0  ->  PG13
  ETH_TXD1  ->  PG14
  PD3配置成GPIO输出(LAN8720A的硬件复位引脚)
时能串口1,用于调试

2、配置时钟
外部高速晶振选择为8M,PLL SORCE MUX 选择为HSE,在HCLK处输入168点回车,软件会自动配置好。




3、中间件配置
这里我们主要配置,ETH、LWIP、串口1、GPIO


因为PD3为PHY的输入引脚,所有我们这里直接配置它为输出高,这样就为正常工作状态

串口1我们设置它的波特率为115200,添加发送DMA,注意!如果添加了发送或者接收DMA则必须开启串口中断。

ETH设置,这里主要是注意PHY的地址,原子407的PHY地址引脚为悬空,地址为0。

ETH设置的 Advanced Parameters 选项里面,我们选择PHY为USER PHY,名字我们取 LAN7820A,其它的设置全用默认即可。要改的寄存器基本就只有ExternalPHY Configuration,但是我看了下官方的例子,基本没有用到这寄存器里面的值,只有在使用操作系统并且时能了连接状态变更回调或者其它检测的时候才用到,所有这里我们也不管,都用默认值。


LWIP设置 ,我们关闭DHCP,采用静态IP,因为我所在的网关为192.168.0.XXX,所以IP必须为192.168.0.XXX。这里我设置IP为192.168.0.120。因为要用到TCP 和 UDP(TFTP就是用的UDP),所以这两个都是时能的.其它设置选项我们先不管,直接点OK。

4、生成工程代码
点左上角的Project,选择Settings ...(不建议直接点黄 {MOD}的齿轮)


取个非中文的工程名,选择IDE为KEIL MDK V5


点击OK。再点右上方的黄 {MOD}齿轮即可生成工程代码。
三、工程代码
生成的代码的试图如下:
QQ截图20170724085618.png
1、TCP Server 的实现
在math.h中 加入
#include "stm32f4xx_hal.h"
#include "stdio.h"

用于支持printf 及 一些 HAL 定义的 数据结构

在uart.c 文件中加入如下代码,用于把printf输出到串口1
[mw_shl_code=c,true]/* USER CODE BEGIN 0 */
int fputc(int c,FILE * f)
{
HAL_UART_Transmit(&huart1,(uint8_t *)&c,1,20);
return c;
}
/* USER CODE END 0 */[/mw_shl_code]


注意一定要在 /* USER CODE BEGIN X */ 与 /* USER CODE END X */ 中间添加代码,不然重新用STM32CubeMX生成代码后就会被覆盖。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。