【嵌入式实战】STM32+Lwip 实现 DHCP+HostName(超详细)

文章目录

  • 原创声明
  • 前言
  • 一、DHCP 是什么?
  • 二、Cube 快速配置
    • 2.1 STM32 ETH 设置
    • 2.2 修改 PHY 地址
    • 2.3 配置 LWIP 的 DHCP 为 Enable
    • 2.4 开启 Host Name 选项
    • 2.5 HostName 必备文件——netbiosns.c 文件
  • 三、实现 DHCP 功能
    • 3.1 加入 Host Name 必要文件
    • 3.2 重写DHCP初始化
    • 3.3 开启 DHCP LOG 打印
    • 3.4 效果
  • 总结
  • 授权须知


原创声明

本文为 HinGwenWoong 原创,如果这篇文章对您有帮助,欢迎转载,转载请阅读文末的【授权须知】,感谢您对 HinGwenWoong 文章的认可!


前言

随着物联网设备的增加,在一般场景中,使用 DHCP 可以更加快捷方便的让设备可以做到不同局域网都插上网线可以立刻使用。

我是 HinGwenWoong ,一个有着清晰目标不停奋斗的程序猿,热爱技术,喜欢分享,码字不易,如果帮到您,请帮我在屏幕下方点赞 ,您的点赞可以让技术传播得更远更广,谢谢!


一、DHCP 是什么?

DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)通常被应用在大型的局域网络环境中,主要作用是集中的管理、分配IP地址,使网络环境中的主机动态的获得IP地址、Gateway地址、DNS服务器地址等信息,并能够提升地址的使用率。

DHCP协议采用客户端/服务器模型,主机地址的动态分配任务由网络主机驱动。当DHCP服务器接收到来自网络主机申请地址的信息时,才会向网络主机发送相关的地址配置等信息,以实现网络主机地址信息的动态配置。DHCP具有以下功能:

  1. 保证任何IP地址在同一时刻只能由一台DHCP客户机所使用。
  2. DHCP应当可以给用户分配永久固定的IP地址。
  3. DHCP应当可以同用其他方法获得IP地址的主机共存(如手工配置IP地址的主机)。
  4. DHCP服务器应当向现有的BOOTP客户端提供服务。

DHCP有三种机制分配IP地址:

  1. 自动分配方式(Automatic Allocation)DHCP服务器为主机指定一个永久性的IP地址,一旦DHCP客户端第一次成功从DHCP服务器端租用到IP地址后,就可以永久性的使用该地址。

  2. 动态分配方式(Dynamic Allocation)DHCP服务器给主机指定一个具有时间限制的IP地址,时间到期或主机明确表示放弃该地址时,该地址可以被其他主机使用。

  3. 手工分配方式(Manual Allocation),客户端的IP地址是由网络管理员指定的,DHCP服务器只是将指定的IP地址告诉客户端主机。

三种地址分配方式中,只有动态分配可以重复使用客户端不再需要的地址。

DHCP消息的格式是基于BOOTP(Bootstrap Protocol)消息格式的,这就要求设备具有BOOTP中继代理的功能,并能够与BOOTP客户端和DHCP服务器实现交互。BOOTP中继代理的功能,使得没有必要在每个物理网络都部署一个DHCP服务器。RFC 951RFC 1542BOOTP协议进行了详细描述。


二、Cube 快速配置

2.1 STM32 ETH 设置

在这里插入图片描述

2.2 修改 PHY 地址

本项目使用的是 LAN8720 芯片,需要修改 PHY Address0
在这里插入图片描述

2.3 配置 LWIP 的 DHCP 为 Enable

【嵌入式实战】STM32+Lwip 实现 DHCP+HostName(超详细)_第1张图片

2.4 开启 Host Name 选项

为什么需要使用 Host Name 呢?

是因为真正的生产环境中,我们不使用 log 很难知道我们的设备到底是获取到哪个 IP,我们将设备固定一个 Host Name(我自己使用的是一个固定的开头加上芯片唯一ID),使用 Ping 这个 Host Name 的方式就可以立刻知道设备的 IP 了,下面是开启 Host Name 的方式:
【嵌入式实战】STM32+Lwip 实现 DHCP+HostName(超详细)_第2张图片

2.5 HostName 必备文件——netbiosns.c 文件

如果生成的工程中找不到 netbiosns.c 文件
需要下载 LWIP 的官方 SDK:lwIP - A Lightweight TCP/IP stack

【嵌入式实战】STM32+Lwip 实现 DHCP+HostName(超详细)_第3张图片
我这里是 lwip 2.1.2 版本,选择你需要的版本进行下载

【嵌入式实战】STM32+Lwip 实现 DHCP+HostName(超详细)_第4张图片
下载完成后,解压,里面可以看到这个文件夹 netbiosns

【嵌入式实战】STM32+Lwip 实现 DHCP+HostName(超详细)_第5张图片
将其复制到工程下
【嵌入式实战】STM32+Lwip 实现 DHCP+HostName(超详细)_第6张图片


三、实现 DHCP 功能

3.1 加入 Host Name 必要文件

加入 netbiosns 文件到工程里面:
【嵌入式实战】STM32+Lwip 实现 DHCP+HostName(超详细)_第7张图片

3.2 重写DHCP初始化

在外部完善一个 DHCP 初始化的函数:

/* bsp includes. */
#include "FreeRTOS.h"
#include "timers.h"

/* bsp includes. */
#include "lwip/dhcp.h"
#include "lwip/dns.h"
#include "lwip/apps/netbiosns.h"

/* bsp includes. */
#include "bsp_printlog.h"

// 最大 DHCP 次数,设置一个 大点的值
#define MAX_DHCP_COUNT (50000)

/*!
* @brief 封装 dhcp 接口
*        执行条件:无
*
* @retval: 无
*/
err_t bsp_dhcp(void)
{
    struct dhcp *dhcp;
	uint32_t over_time = 0;
	
	struct netif *netif_p = netif_default;
	
	if(netif_p == NULL)
	{
		return ERR_VAL;
	}

    /* Start DHCP negotiation for a network interface (IPv4) */
//    dhcp_start(netif);  //可以在这里写,将该函数 bsp_dhcp() 代替掉 lwip.c 原本已经存在的 dhcp_start() 函数

	//设置计算机名 (测试方法: (1)ping 计算机名 (2)用浏览器访问 http://计算机名/)
    
	netif_p->hostname = "THOSTP"; //设置 Host Name
	
	netbiosns_init();
	netbiosns_set_name(netif_p->hostname);

	// 外部定义了 netif_default
    while(!dhcp_supplied_address(netif_p))
    {
		over_time++;
        print_log("dhcp_connect: DHCP discovering... for %d times\r\n", over_time);
		
		if(over_time > MAX_DHCP_COUNT)
		{
			print_log("dhcp_connect: overtime, not doing dhcp\r\n");
			return ERR_TIMEOUT;
		}
        vTaskDelay(pdMS_TO_TICKS(500));
    }

    dhcp = netif_dhcp_data(netif_p);
    print_log("DHCP IP address: %s\n", ip4addr_ntoa(&dhcp->offered_ip_addr));
    print_log("DHCP Subnet mask: %s\n", ip4addr_ntoa(&dhcp->offered_sn_mask));
    print_log("DHCP Default gateway: %s\n", ip4addr_ntoa(&dhcp->offered_gw_addr));

#if LWIP_DNS
    print_log("DHCP DNS Server: %s\n", ip4addr_ntoa(dns_getserver(0)));

	#ifdef DNS_SERVER_ADDRESS
	  /* initialize default DNS server address */
	  ip_addr_t dnsserver;
	  DNS_SERVER_ADDRESS(&dnsserver);
	  dns_setserver(0, &dnsserver);
	#endif /* DNS_SERVER_ADDRESS */

    print_log("after set DHCP DNS Server: %s\n", ip4addr_ntoa(dns_getserver(0)));
#endif

    print_log("dhcp_connect: DHCP success\r\n");

	return ERR_OK;
}

3.3 开启 DHCP LOG 打印

如果想看 LWIPLOG 信息,在 lwipopts.h 中 定义宏 LWIP DEBUG,这个操作有可能会导致一些打印打不出来,我就是 dhcp_bind() 信息打不出来导致我一直以为失败,结果是没有打印,先不使用打印看看是否可以获取到 IP,可以获取到就不用打开了

//开启 LWIP DEBUG
#define LWIP_DEBUG
#include "bsp_printlog.h"
#undef LWIP_PLATFORM_DIAG
#define LWIP_PLATFORM_DIAG(x) do {print_log x;} while(0)
  
//开启 lwip DHCP DEBUG
#define DHCP_DEBUG                  LWIP_DBG_ON

3.4 效果

打印信息打印 DHCP 获取的 IP 信息:
【嵌入式实战】STM32+Lwip 实现 DHCP+HostName(超详细)_第8张图片
使用同一局域网的电脑进入 cmdping 命令测试,可以使用 hostnameIP 分别测试,host name 我在上面的 DHCP初始化 函数中修改的:

【嵌入式实战】STM32+Lwip 实现 DHCP+HostName(超详细)_第9张图片
成功!!!!


总结

以上是 STM32 + LWIP 如何 使用 DHCP 动态获取 IP 的全部内容,本文介绍了如何动态获取 IP 的一个方法,让嵌入式物联网设备能够在不同的局域网都可使用。


更多阅读推荐
  • 【嵌入式实战】STM32+Lwip 实现 SNTP 网络授时(超详细)
  • 【嵌入式实战】STM32+FreeRTOS+LWIP+WolfSSL 实现 HTTPS(超详细)
  • 【嵌入式小技巧】stm32 实现 Segger RTT 打印(超详细)

我是 HinGwenWoong ,一个有着清晰目标不停奋斗的程序猿,热爱技术,喜欢分享,码字不易,如果帮到您,请帮我在屏幕下方点赞 ,您的点赞可以让技术传播得更远更广,谢谢!


授权须知

  1. 原创文章在推送两天后才可进行转载
  2. 转载文章,禁止声明原创
  3. 不允许直接二次转载,转载请根据原文链接联系作者
  4. 若无需改版,在文首清楚标注作者及来源/原文链接,并删除【原创声明】,即可直接转载。
    但对于未注明转载来源/原文链接的文章,我将保留追述的权利。

作者:HinGwenWoong
一个有着清晰目标不停奋斗的程序猿,热爱技术,喜欢分享,共同进步!
CSDN: HinGwenWoong
原文链接:【嵌入式实战】STM32+Lwip 实现 DHCP+HostName(超详细)

  1. 若需要修改文章的排版,请根据原文链接联系作者
  2. 再次感谢您的认可,转载请遵守如上转载须知!

你可能感兴趣的:(嵌入式SMT32,嵌入式,stm32,dhcp,物联网,网络)