前言
因为暂时缺少焊接工具的原因,不能焊接STM32F407的开发板,为了实现LWIP的功能,在某宝买了一块STM32F407ZG最小系统开发板+一个LAN8720A模块。(购买的Lan8720A模块与其他教程有一点点需要注意的地方,那就是器件地址的选择以及模块没有引出RST引脚,内部上拉至了高电平)。
模块接线:
LAN8720 | STM32F407VGT6 |
---|---|
VCC | 3.3V |
GND | GND |
MDIO | PA2 |
MDC | PC1 |
NINT | PA1 |
CRS | PA7 |
RXD0 | PC4 |
RXD1 | PC5 |
TX_EN | PB11或PG11 |
TXD0 | PB12或PG13 |
TXD1 | PB13或PG14 |
一、实验目的
使用DHCP功能动态获取IP地址
二、使用步骤
1.创建工程,配置一般必要步骤(例如打开串口,设置为异步通信方式)
2.开启ETH,Mode选择为RMII,并配置以下选项,其余默认
尤其需要注意的就是以下器件地址的选择,这里选择为1,若选择错误,lan8720A模块不会正常工作。
3.打开LWIP,其余配置默认即可
4.时钟树的配置
5.生成代码,用Clion打开
6.在usart.c文件底部输入代码,以及在usart.h文件中引入头文件
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t *) &ch, 1, 0xFFFF);
return ch;
}
#include "stdio.h"
截图
截图
7.main.c文件中main函数下引入变量
extern struct netif gnetif;
struct dhcp *dhcp;
8.main函数while(1)中输入测试代码
MX_LWIP_Process();
dhcp = netif_dhcp_data(&gnetif);
printf("DHCP IP 地址: %s\r\n", ip4addr_ntoa(&dhcp->offered_ip_addr));
HAL_Delay(500);
截图
9.编译下载程序到开发板,DHCP获取成功
10.实现网线插拔
开启接口状态变化回调函数,开启GPIOG13、GPIOG14输出做LED显示
11.新建一对.C/.H文件源文件 ,命名为Display_ip_address
.c
#include "Display_ip_address.h"
#include <string.h>
#include "lwip.h"
uint8_t Display_IP_address() {
uint16_t time_out = 0, response_time = 0;
extern struct netif gnetif;
struct dhcp *dhcp;
while (1) {
MX_LWIP_Process();
dhcp = netif_dhcp_data(&gnetif);
if (strlen(ip4addr_ntoa(&dhcp->offered_ip_addr)) > 7 && strlen(ip4addr_ntoa(&dhcp->offered_sn_mask)) > 7 &&
strlen(ip4addr_ntoa(&dhcp->offered_gw_addr)) > 0) {
printf("DHCP IP 地址获取成功\r\n");
printf("DHCP IP地址: %s\r\n", ip4addr_ntoa(&dhcp->offered_ip_addr));
printf("DHCP 子网掩码: %s\r\n", ip4addr_ntoa(&dhcp->offered_sn_mask));
printf("DHCP 默认网关: %s\r\n", ip4addr_ntoa(&dhcp->offered_gw_addr));
break;
} else {
HAL_Delay(100);
time_out++;
response_time++;
if (response_time == 10) {
response_time = 0;
printf("...\r\n");
}
if (time_out == 100) {
printf("DHCP IP 地址未获取\r\n");
}
if (time_out == 200) {
printf("DHCP IP 地址未获取建议检查设备或重启\r\n");
break;
}
}
}
}
.h
#ifndef F407_LWIP_PING_DISPLAY_IP_ADDRESS_H
#define F407_LWIP_PING_DISPLAY_IP_ADDRESS_H
#include "stm32f4xx_hal.h"
uint8_t Display_IP_address();
#endif
ethernetif.c文件底部有一弱函数__weak void ethernetif_notify_conn_changed(struct netif *netif),在里输入
extern err_t dhcp_start(struct netif *netif);
#include "Display_ip_address.h"
__weak void ethernetif_notify_conn_changed(struct netif *netif) {
/* NOTE : This is function could be implemented in user file
when the callback is needed,
*/
if (netif_is_link_up(netif)) {
netif_set_up(netif);
printf("网线插入\r\n");
dhcp_start(netif);
Display_IP_address();
} else
printf("网线拔出\r\n");
}
lwip.c文件中void MX_LWIP_Process(void){}函数内加入
ethernetif_set_link(&gnetif);
main.c文件中引入头文件
#include "Display_ip_address.h"
main函数中输入
int main(void) {
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_LWIP_Init();
/* USER CODE BEGIN 2 */
printf("LWIP测试\r\n");
Display_IP_address();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
MX_LWIP_Process();
HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_13);
HAL_Delay(500);
}
/* USER CODE END 3 */
}
结果
总结
使用LAN8720A模块时,尤其需要注意的就是器件地址的选择
资源下载