目录

银杏科技有限公司旗下技术文档发布平台
技术支持电话0379-69926675-801
技术支持邮件Gingko@vip.163.com
版本 日期 作者 修改内容
V1.0 2020-07-09 gingko 初次建立

实验二十五:LWIP_DNS实验——域名解析

一、 实验目的与意义

  1. 了解STM32 SPI和DHCP结构。
  2. 了解STM32 SPI和DHCP特征。
  3. 掌握SPI和DHCP的使用方法。
  4. 掌握KEIL MDK 集成开发环境使用方法。

二、 实验设备及平台

  1. iCore4 双核心板点击购买
  2. JLINK(或相同功能)仿真器点击购买
  3. Micro USB线缆。
  4. 网线。
  5. Keil MDK 开发平台。
  6. 装有WIN XP(及更高版本)系统的计算机。

三、 实验原理

1、DNS简介

2、域名解析简介

3、LWIP简介

4、LAN8720A简介

5、原理图

四、 实验程序

1、主函数

int main(void)
{   
    system_clock.initialize();       //系统时钟初始化
    led.initialize();                //LED初始化
    adc.initialize();                //ADC初始化
    delay.initialize(216);           //延时初始化
    my_malloc.initialize(SRAMIN);    //动态内存初始化
    usart6.initialize(115200);       //串口波特设置
    usart6.printf("\033[1;32;40m");  //设置字体终端为绿色
    usart6.printf("\r\nHello, I am iCore4!\r\n\r\n");    //串口信息输出 
 
    OSInit();                         //UCOS初始化
 
    while(lwip.initialize())          //lwip初始化
    {
     LED_RED_ON;
         usart6.printf("\r\nETH initialize error!\r\n\r\n");//ETH初始化失败
    }
    OSTaskCreate(start_task,(void*)0,(OS_STK*)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO);
    OSStart();                        //开启UCOS   
}
 

2、开始任务

void start_task(void *pdata)
{
    OS_CPU_SR cpu_sr;
    pdata = pdata ;
 
    OSStatInit();              //初始化统计任务
    OS_ENTER_CRITICAL();      //关中断
 
#if LWIP_DHCP
    lwip_comm_dhcp_creat();   //创建DHCP任务    
#if LWIP_DNS   
    my_dns.initialize();       //创建DNS任务
#endif
#endif
 
    OSTaskCreate(led_task,(void*)0,(OS_STK*)&LED_TASK_STK[LED_STK_SIZE-1],LED_TASK_PRIO);                  //创建LED任务
    OSTaskCreate(display_task,(void*)0,(OS_STK*)&DISPLAY_TASK_STK[DISPLAY_STK_SIZE-1],DISPLAY_TASK_PRIO); //显示任务
    OSTaskSuspend(OS_PRIO_SELF); //挂起start_task任务
 
    OS_EXIT_CRITICAL();          //开中断
}

3、创建删除DHCP任务

//创建DHCP任务
void lwip_comm_dhcp_creat(void)
{
    OS_CPU_SR cpu_sr;
    OS_ENTER_CRITICAL();  //进入临界区
    OSTaskCreate(lwip_dhcp_task,(void*)0,(OS_STK*)&LWIP_DHCP_TASK_STK[LWIP_DHCP_STK_SIZE-1],LWIP_DHCP_TASK_PRIO);//创建DHCP任务 
    OS_EXIT_CRITICAL();  //退出临界区
}
//删除DHCP任务
void lwip_comm_dhcp_delete(void)
{
    dhcp_stop(&lwip_netif);     //关闭DHCP
    OSTaskDel(LWIP_DHCP_TASK_PRIO); //删除DHCP任务
}
 

4、DHCP处理任务

void lwip_dhcp_task(void *pdata)
{
    OS_CPU_SR cpu_sr;
    u32 ip=0,netmask=0,gw=0;
    dhcp_start(&lwip_netif);//开启DHCP 
    lwipdev.dhcpstatus=0;   //正在DHCP
    usart6.printf("开启 DHCP 中...\r\n");
 
    while(1)
    { 
        usart6.printf("正在获取地址...\r\n");
 
        OS_ENTER_CRITICAL();             //关中断
        ip=lwip_netif.ip_addr.addr;     //读取新IP地址
        netmask=lwip_netif.netmask.addr;//读取子网掩码
        gw=lwip_netif.gw.addr;           //读取默认网关 
        OS_EXIT_CRITICAL();               //开中断
 
        OSTimeDlyHMSM(0,0,0,500);
        if(ip!=0)            //当正确读取到IP地址的时候
        {
            lwipdev.dhcpstatus=2;   //DHCP成功
       usart6.printf("网卡en的MAC地址为:................%d.%d.%d.%d.%d.%d\r\n",lwipdev.mac[0],lwipdev.mac[1],lwipdev.mac[2],lwipdev.mac[3],lwipdev.mac[4],lwipdev.mac[5]); //解析出通过DHCP获取到的IP地址
            lwipdev.ip[3]=(uint8_t)(ip>>24); 
            lwipdev.ip[2]=(uint8_t)(ip>>16);
            lwipdev.ip[1]=(uint8_t)(ip>>8);
            lwipdev.ip[0]=(uint8_t)(ip);
            usart6.printf("通过DHCP获取到IP地址..............%d.%d.%d.%d\r\n",lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
            //解析通过DHCP获取到的子网掩码地址
            lwipdev.netmask[3]=(uint8_t)(netmask>>24);
            lwipdev.netmask[2]=(uint8_t)(netmask>>16);
            lwipdev.netmask[1]=(uint8_t)(netmask>>8);
            lwipdev.netmask[0]=(uint8_t)(netmask);
            usart6.printf("通过DHCP获取到子网掩码............%d.%d.%d.%d\r\n",lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]);      //解析出通过DHCP获取到的默认网关
            lwipdev.gateway[3]=(uint8_t)(gw>>24);
            lwipdev.gateway[2]=(uint8_t)(gw>>16);
            lwipdev.gateway[1]=(uint8_t)(gw>>8);
            lwipdev.gateway[0]=(uint8_t)(gw);
            usart6.printf("通过DHCP获取到的默认网关..........%d.%d.%d.%d\r\n",lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
            break;
        }else if(lwip_netif.dhcp->tries>LWIP_MAX_DHCP_TRIES) //通过DHCP服务获取IP地址失败,且超过最大尝试次数
        {  
            lwipdev.dhcpstatus=0XFF;//DHCP失败.
            //使用静态IP地址
            IP4_ADDR(&(lwip_netif.ip_addr),lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
            IP4_ADDR(&(lwip_netif.netmask),lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]);
            IP4_ADDR(&(lwip_netif.gw),lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
            usart6.printf("DHCP服务超时,使用静态IP地址!\r\n");
            usart6.printf("网卡en的MAC地址为:................%d.%d.%d.%d.%d.%d\r\n",lwipdev.mac[0],lwipdev.mac[1],lwipdev.mac[2],lwipdev.mac[3],lwipdev.mac[4],lwipdev.mac[5]);
            usart6.printf("静态IP地址........................%d.%d.%d.%d\r\n",lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
            usart6.printf("子网掩码..........................%d.%d.%d.%d\r\n",lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]);
            usart6.printf("默认网关..........................%d.%d.%d.%d\r\n",lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
            break;
        }  
        delay_ms(250); //延时250ms
    }
    lwip_comm_dhcp_delete();//删除DHCP任务 
}

5、创建DNS任务

static INT8U my_dns_init(void)//创建TCP服务器线程
{
    INT8U res;
    OS_CPU_SR cpu_sr;
    OS_ENTER_CRITICAL();    //关中断
    res = OSTaskCreate(dns_test,(void*)0,(OS_STK*)&DNS_TASK_STK[DNS_STK_SIZE-1],DNS_PRIO); //创建TCP服务器线程
    OS_EXIT_CRITICAL();    //开中断
    return res;//返回值:0 TCP服务器创建成功
}

五、 实验步骤

  1. 把仿真器与iCore4的SWD调试口相连(直接相连或者通过转接器相连);
  2. 将跳线冒插在USB UART;
  3. 把iCore4(USB UART)通过Micro USB线与计算机相连,为iCore4供电;
  4. 把iCore4网口通过网线与计算机网口相连;
  5. 打开PuTTY;
  6. 打开Keil MDK 开发环境,并打开本实验工程;
  7. 烧写程序到iCore4上;
  8. 也可以进入Debug模式,单步运行或设置断点验证程序逻辑。

六、 实验现象