stm32 lwip的DHCP

stm32f107 lwip dhcp
第一篇        DHCP自动获取功能的实现
概要
  DHCP在电脑中经常用到,因为我们并不关心我们电脑的IP是多少 只要能连上网络就行了。在嵌入式的产品设备中,DHCP用到的比较少,因为很多的操作是通过ip来进行的。除非那种有服务器的系统设备会用到。这里我们只能简单说一下流程,设计的代码太多了,具体的需要学习者自己去慢慢研究。
dhcp模块:
dhcp模块用于获取设备ip地址的相关信息。其处理入口主要有这么几个dpch的启动、dpch的接收报文处理以及定时器模块的处理。
主要的接口原型如下:
err_t dhcp_start(struct netif *netif)
该接口用于设备启动dhcp模块,主要是客户端的功能。该模块实现设备dhcp描述结构生成,并将dhcp的端口绑定到udp协议中,以及将本dhcp模块跟远端服务器端口进行绑定。最后启动dhcp申请。
static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
该接口为一个注册接口,用于dhcp报文接收。在start dhcp时,该接口通过dhcp的udp pcb注册到udp协议层。Udp进行报文处理后,根据端口调用该注册接口。该接口中,实现dhcp报文的协议处理。
Void dhcp_fine_tmr()
Void dhcp_coarse_tmr()
这两个函数接口实现了dhcp的相关超时处理监控。上面一个用于请求应答超时处理。下面一个用于地址租用情况的到期处理。
从源码分析看,上述的接口在应用lwip的协议栈时,需要重点关注。对于小内存应用的场合,该协议栈的内存管理以及pbuf应用部分需要自行改写。
打开工程《科星F107开发板网络应用篇之DHCP自动获取功能》
  进入主函数
int main(void)
{
  System_Setup();
  LwIP_Init();
  while (1)
  {    
        /* Periodic tasks */
        System_Periodic_Handle();
    
  }
}
   主要看一下 DHCP和静态的时候配置有哪些不同
      进入函数LwIP_Init();
     void LwIP_Init(void)
{
  struct ip_addr ipaddr;
  struct ip_addr netmask;
  struct ip_addr gw;

uint8_t macaddress[6]={0,0,0,0,0,1};
    mem_init();
    memp_init();
ipaddr.addr = 0;
    netmask.addr = 0;
    gw.addr = 0;
  IP 网关 子网掩码 我们设置为0,就是没有值。需要我们自动获取到。

  Set_MAC_Address(macaddress);设置MAC地址,这个不管任何时候都要设置。


//创建一个网络接口

  netif_add(&netif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input);

  netif_set_default(&netif);

  dhcp_start(&netif);主要是这句,这一句就开始了自动获取的进程,以2,4,8,16秒为间隔,加上1-1000毫秒之间随机长度的时间 
  
  netif_set_up(&netif);

}
DHCP获取IP的简单过程
  当DHCP客户机第一次登录网络的时候(也就是客户机上没有任何IP地址数据时),它会通过UDP 67端口向网络上发出一个DHCPDISCOVER数据包(包中包含客户机的MAC地址和计算机名等信息)。因为客户机还不知道自己属于哪一个网络,所以封包的源地址为0.0.0.0,目标地址为255.255.255.255,然后再附上DHCP discover的信息,向网络进行广播。
DHCP discover的等待时间预设为1秒,也就是当客户机将第一个DHCP discover封包送出去之后,在1秒之内没有得到回应的话,就会进行第二次DHCP discover广播。若一直没有得到回应,客户机会将这一广播包重新发送四次(以2,4,8,16秒为间隔,加上1-1000毫秒之间随机长度的时间)。
执行完dhcp_start(&netif);这个函数,开发板就开始和所接的路由器获取IP的进程。
那么我们程序怎么知道是否获取到了没有呢 接着看函数
System_Periodic_Handle();
进入
void System_Periodic_Handle(void)
{
  GET_DHCP_IP(LocalTime);
   LwIP_Periodic_Handle(LocalTime);
}
进入函数GET_DHCP_IP(LocalTime);
void GET_DHCP_IP(__IO uint32_t localtime)

  
  struct ip_addr ipaddr;
  struct ip_addr netmask;
  struct ip_addr gw;

  /* 250 ms */
  if (localtime - DisplayTimer >= GET_DHCP_MSECS) 每250ms检测一次是否得到IP
  {
    DisplayTimer = localtime;

    /* We have got a new IP address so update the display */
    if (IPaddress != netif.ip_addr.addr)
    {
      __IO uint8_t iptab[4];
     

      /* Read the new IP address */
     IPaddress = netif.ip_addr.addr;
      iptab[0] = (uint8_t)(IPaddress >> 24);
      iptab[1] = (uint8_t)(IPaddress >> 16);
      iptab[2] = (uint8_t)(IPaddress >> 8);
      iptab[3] = (uint8_t)(IPaddress);
      if (netif.flags & NETIF_FLAG_DHCP)如果得到IP的话 建立端口连接
      {   
            iptab[0] = (uint8_t)(IPaddress >> 24);
        iptab[1] = (uint8_t)(IPaddress >> 16);
        iptab[2] = (uint8_t)(IPaddress >> 8);
        iptab[3] = (uint8_t)(IPaddress);
             server_init();初始化UDP端口,其实到这里DHCP已经成功了 这里初始化这个端口 是为了增加UDP扫描,以便我们能知道得到的ip是什么。这个函数 还有扫描的功能就不在讲了 前面刚刚讲过。可以自己点进去看一下程序。
}
         
      }
    else if (IPaddress == 0)
    {
               if (netif.dhcp->tries > MAX_DHCP_TRIES) 如果是超时进入超时处理
      {
        struct ip_addr ipaddr;
        struct ip_addr netmask;
        struct ip_addr gw
        dhcp_stop(&netif);
        IP4_ADDR(&ipaddr, 192, 168, 1, 8);
        IP4_ADDR(&netmask, 255, 255, 255, 0);
        IP4_ADDR(&gw, 192, 168, 1, 1);
      netif_set_addr(&netif, &ipaddr , &netmask, &gw);
    }
  } 
}
上面的函数主要是检测是不是获取到IP
再看另一个主函数LwIP_Periodic_Handle(LocalTime);
进入 主要看和DHCP有关的两个函数
void LwIP_Periodic_Handle(__IO uint32_t localtime)
{

  /* TCP periodic process every 250 ms */
  if (localtime - TCPTimer >= TCP_TMR_INTERVAL)
  {
    TCPTimer =  localtime;
    tcp_tmr();
  }
  /* ARP periodic process every 5s */
  if (localtime - ARPTimer >= ARP_TMR_INTERVAL)
  {
    ARPTimer =  localtime;
    etharp_tmr();
  }

#if LWIP_DHCP
  /* Fine DHCP periodic process every 500ms */
  if (localtime - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS)
  {
    DHCPfineTimer =  localtime;
    dhcp_fine_tmr();请求应答超时处理
  }。

  /* DHCP Coarse periodic process every 60s */
  if (localtime - DHCPcoarseTimer >= DHCP_COARSE_TIMER_MSECS)
  {
    DHCPcoarseTimer =  localtime;
    dhcp_coarse_tmr();地址租用情况的到期处理
  }
#endif

}

你可能感兴趣的:(TCP/IP)