历史上的今天
返回首页

历史上的今天

今天是:2025年07月23日(星期三)

正在发生

2019年07月23日 | stm32以太网LWIP学习笔记之UDP通信

2019-07-23 来源:eefocus

初始化配置步骤

第一:硬件底层DMA缓存以及以太网内存初始化


if(ETH_Mem_Malloc())return 1;       //内存申请失败

    if(lwip_comm_mem_malloc())return 1; //内存申请失败


u8 ETH_Mem_Malloc(void)

    DMARxDscrTab=mymalloc(SRAMIN,ETH_RXBUFNB*sizeof(ETH_DMADESCTypeDef));//申请内存

    DMATxDscrTab=mymalloc(SRAMIN,ETH_TXBUFNB*sizeof(ETH_DMADESCTypeDef));//申请内存  

    Rx_Buff=mymalloc(SRAMIN,ETH_RX_BUF_SIZE*ETH_RXBUFNB);   //申请内存

    Tx_Buff=mymalloc(SRAMIN,ETH_TX_BUF_SIZE*ETH_TXBUFNB);   //申请内存

    if(!DMARxDscrTab||!DMATxDscrTab||!Rx_Buff||!Tx_Buff)

    {

        ETH_Mem_Free();

        return 1;   //申请失败

    }   

    return 0;       //申请成功

}


//lwip中mem和memp的内存申请

//返回值:0,成功;

//    其他,失败

u8 lwip_comm_mem_malloc(void)

{

    u32 mempsize;

    u32 ramheapsize; 

    mempsize=memp_get_memorysize();         //得到memp_memory数组大小

    memp_memory=mymalloc(SRAMIN,mempsize);  //为memp_memory申请内存

    ramheapsize=LWIP_MEM_ALIGN_SIZE(MEM_SIZE)+2*LWIP_MEM_ALIGN_SIZE(4*3)+MEM_ALIGNMENT;//得到ram heap大小

    ram_heap=mymalloc(SRAMIN,ramheapsize);  //为ram_heap申请内存 

    if(!memp_memory||!ram_heap)//有申请失败的

    {

        lwip_comm_mem_free();

        return 1;

    }

    return 0;   

 }


第二步:网卡硬件初始化


LAN8720_Init()


第三步:以太网初始化


lwip_init();


第四步:设置IP地址


//静态:

IP4_ADDR(&ipaddr,192.168.1.100);

IP4_ADDR(&netmask,192.168.1.1);

IP4_ADDR(&gw,255.255.255.0);


//动态暂时为0,待会自动获取:

IP4_ADDR(&ipaddr,0.0.0.0);

IP4_ADDR(&netmask,0.0.0.0);

IP4_ADDR(&gw,0.0.0.0);


第五步:添加网卡


Netif_Init_Flag=netif_add(&lwip_netif,&ipaddr,&netmask,&gw,NULL,ðernetif_init,ðernet_input);

1

第六步:如果为动态IP则开启动态IP服务


lwipdev.dhcpstatus=0;   //DHCP标记为0

    dhcp_start(&lwip_netif);    //开启DHCP服务


第七步:设置默认网口,并打开


netif_set_default(&lwip_netif); //设置netif为默认网口

        netif_set_up(&lwip_netif);      //打开netif网口


第八步:等待动态获取IP,如果获取失败,则使用静态IP


while((lwipdev.dhcpstatus!=2)&&(lwipdev.dhcpstatus!=0XFF))//等待DHCP获取成功/超时溢出

    {

        lwip_periodic_handle();

    }


//LWIP轮询任务

void lwip_periodic_handle()

{

#if LWIP_TCP

    //每250ms调用一次tcp_tmr()函数

  if (lwip_localtime - TCPTimer >= TCP_TMR_INTERVAL)

  {

    TCPTimer =  lwip_localtime;

    tcp_tmr();

  }

#endif

  //ARP每5s周期性调用一次

  if ((lwip_localtime - ARPTimer) >= ARP_TMR_INTERVAL)

  {

    ARPTimer =  lwip_localtime;

    etharp_tmr();

  }


#if LWIP_DHCP //如果使用DHCP的话

  //每500ms调用一次dhcp_fine_tmr()

  if (lwip_localtime - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS)

  {

    DHCPfineTimer =  lwip_localtime;

    dhcp_fine_tmr();

    if ((lwipdev.dhcpstatus != 2)&&(lwipdev.dhcpstatus != 0XFF))

    { 

      lwip_dhcp_process_handle();  //DHCP处理

    }

  }


  //每60s执行一次DHCP粗糙处理

  if (lwip_localtime - DHCPcoarseTimer >= DHCP_COARSE_TIMER_MSECS)

  {

    DHCPcoarseTimer =  lwip_localtime;

    dhcp_coarse_tmr();

  }  

#endif

}


void lwip_dhcp_process_handle(void)

{

    u32 ip=0,netmask=0,gw=0;

    switch(lwipdev.dhcpstatus)

    {

        case 0:     //开启DHCP

            dhcp_start(&lwip_netif);

            lwipdev.dhcpstatus = 1;     //等待通过DHCP获取到的地址

            printf("正在查找DHCP服务器,请稍等...........rn");  

            break;

        case 1:     //等待获取到IP地址

        {

            ip=lwip_netif.ip_addr.addr;     //读取新IP地址

            netmask=lwip_netif.netmask.addr;//读取子网掩码

            gw=lwip_netif.gw.addr;          //读取默认网关 


            if(ip!=0)           //正确获取到IP地址的时候

            {

                lwipdev.dhcpstatus=2;   //DHCP成功

                printf("网卡en的MAC地址为:................%d.%d.%d.%d.%d.%drn",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);

                printf("通过DHCP获取到IP地址..............%d.%d.%d.%drn",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);

                printf("通过DHCP获取到子网掩码............%d.%d.%d.%drn",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);

                printf("通过DHCP获取到的默认网关..........%d.%d.%d.%drn",lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);

            }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]);

                printf("DHCP服务超时,使用静态IP地址!rn");

                printf("网卡en的MAC地址为:................%d.%d.%d.%d.%d.%drn",lwipdev.mac[0],lwipdev.mac[1],lwipdev.mac[2],lwipdev.mac[3],lwipdev.mac[4],lwipdev.mac[5]);

                printf("静态IP地址........................%d.%d.%d.%drn",lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);

                printf("子网掩码..........................%d.%d.%d.%drn",lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]);

                printf("默认网关..........................%d.%d.%d.%drn",lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);

            }

        }

        break;

        default : break;

    }

}

#endif 


第九步:测试


udp_demo_test(); 

1

UDP协议测试的步骤

第一步:如果对方IP是动态的,则第一步为设置远程IP


udp_demo_set_remoteip();

//部分代码

/*前三一般较为固定,实际是只需设置第四部分*/

lwipdev.remoteip[0]=lwipdev.ip[0]; //192

lwipdev.remoteip[1]=lwipdev.ip[1]; //168

lwipdev.remoteip[2]=lwipdev.ip[2]; //1 


while(1)

    {

        key=KEY_Scan(0);

        if(key==WKUP_PRES)break;

        else if(key)

        {

            if(key==KEY0_PRES)lwipdev.remoteip[3]++;//IP增加

            if(key==KEY2_PRES)lwipdev.remoteip[3]--;//IP减少

            LCD_ShowxNum(xoff,150,lwipdev.remoteip[3],3,16,0X80);//显示新IP

        }

    }


第二步:创建DCP控制块


udppcb=udp_new();


第三步:连接指定IP,指定端口


err=udp_connect(udppcb,&rmtipaddr,UDP_DEMO_PORT);//UDP客户端连接到指定IP地址和端口号的服务器


第四步:绑定本地IP和端口号


err=udp_bind(udppcb,IP_ADDR_ANY,UDP_DEMO_PORT);//绑定本地IP地址与端口号

1

第五步:注册接收回调函数,只要接收到数据,这个回调函数会被lwip内核调用


udp_recv(udppcb,udp_demo_recv,NULL);//注册接收回调函数 

//回调函数的编写


void udp_demo_recv(void *arg,struct udp_pcb *upcb,struct pbuf *p,struct ip_addr *addr,u16_t port)

{

    u32 data_len = 0;

    struct pbuf *q;

    if(p!=NULL) //接收到不为空的数据时

    {

        memset(udp_demo_recvbuf,0,UDP_DEMO_RX_BUFSIZE);  //数据接收缓冲区清零

        for(q=p;q!=NULL;q=q->next)  //遍历完整个pbuf链表

推荐阅读

史海拾趣

Avic公司的发展小趣事

Avic公司积极参与中国民用飞机项目的研发和生产。通过与国内外合作伙伴的紧密合作,公司成功研制出了多款具有市场竞争力的民用飞机。这些飞机的成功研制和生产,不仅提升了中国民用航空工业的水平,也为国内外航空公司提供了更多优质的航空产品选择。

亿宝科技(CNIBAO)公司的发展小趣事

品质是亿宝科技的生命线。公司始终坚持严格的质量管理体系,从原材料采购到生产流程,再到成品检验,每一个环节都严格把控。在一次客户反馈中,亿宝科技发现某批次产品存在细微的质量问题。公司立即启动紧急预案,召回所有相关产品并进行全面检查。经过一系列的改进措施,亿宝科技成功解决了问题,并赢得了客户的信任和好评。

EVERLIGHT公司的发展小趣事

随着全球环保意识的不断提高,EVERLIGHT也积极响应环保号召,致力于研发和生产环保型LED产品。公司采用环保材料和节能技术,不断降低产品的能耗和废弃物排放。同时,公司还积极推广绿色照明理念,为客户提供环保、节能的照明解决方案。这种对环保的关注和实践让EVERLIGHT在电子行业中树立了良好的形象。

BERGQUIST公司的发展小趣事

随着产品技术的不断成熟和市场的逐步认可,BERGQUIST公司开始积极拓展市场。公司不仅在国内市场取得了显著成绩,还积极开拓国际市场,与众多知名电子企业建立了长期合作关系。通过不断提升产品质量和服务水平,BERGQUIST成功树立起了自己的品牌形象,成为热管理领域的佼佼者。

CONTRINEX公司的发展小趣事

2015年,Contrinex正式进入中国市场,成立了全新的中国子公司。这一重要举措不仅进一步拓宽了公司的业务范围,也为中国客户提供了更加便捷和高效的服务。在中国市场,Contrinex凭借其电感式、光电式、安全光幕和RFID系统的工业级传感器产品,赢得了众多客户的青睐和信赖。

Alpha Semiconductor公司的发展小趣事

Alpha Semiconductor位于美国加州硅谷的研发与生产基地是公司发展的重要支撑。在这里,公司拥有一流的研发团队和先进的生产设备,能够为客户提供高质量的产品和服务。硅谷作为全球科技创新的中心之一,为Alpha Semiconductor提供了丰富的技术资源和人才支持,使得公司能够不断推陈出新,保持在半导体行业的领先地位。

通过以上五个故事,我们可以看到Alpha Semiconductor公司在电子行业中的发展历程。从初创时期的代工服务起步,到后来的OEM定制产品、自主研发电源管理产品,再到高性能标准模拟和混合信号IC的制造实力,以及在美国硅谷的研发与生产基地的建立,每一个阶段都见证了公司的成长和进步。Alpha Semiconductor凭借着不断的技术创新和市场拓展,已经成为了半导体行业中的佼佼者。

问答坊 | AI 解惑

金杯阁瑞斯柴油版动力澎湃

华晨汽车继金杯品牌旗下的第六代金杯海狮推出刚刚满月后,再次掀起MPV柴油版新浪潮,于10月25日率先在上海推出了金杯阁瑞斯柴油版。此次推出的金杯阁瑞斯柴油版,分为尊领、智领两大系列总计10款,并均有欧III和欧III+OBD两类车型 环保——首款欧I ...…

查看全部问答>

求ril.dll(或别的名字).

手机mobile6.0下程序可运行,但在模拟器上运行提示“程序损坏”之类的东西,现求一个ril.dll(版本可能不对),请发到crazy0363@126.com ,谢谢!…

查看全部问答>

wince 5.0电量显示

我的wince 5.0的开发板上没有电量显示,请问如何实现,麻烦了。 我查了点资料,但是还是没头绪。说是要硬件支持,具体是什么样的支持呢?没搞明白。 还要驱动支持,具体是什么样的支持,也没搞懂。 好像可以AP来做,但我也没查到AP的全称是什么 ...…

查看全部问答>

向gooogleman请问用KITL调试驱动的问题

gooogleman你好,看了你的blog中一篇关于用kitl调试驱动的问题,我现在也想用KITL来调试一个pci设备的驱动,驱动是在PB5.0下开发的,要求在wince5.0下运行,我有如下问题请教: 1.除了可以用网卡来弄KITL以外还可以用USB来弄KITL吗,用USB时硬件上 ...…

查看全部问答>

请教关于单输出差分放大电路的抑制漂移原理?

差分放大电路如果,两个输出端,分别接在两个晶体管的集电极,那么他们是能够有效的抑制漂移的但是如果是单输出,只是在第一个晶体管的集电极加上一个负载电阻,那么它又是怎么抑制漂移的呢?就是通过长尾电阻的负反馈吗?请大家帮忙解答下,谢谢…

查看全部问答>

武汉力源提供KEIL原版的STM32启动开发套件

                                 STM3210B-KEIL/SK…

查看全部问答>

STM32F103CBADC自效准有bug吗?

用32F103CB AD测量6路电池电压,范围1-28V电压只通过电阻分压直接输入AD管脚,采用6路循环DMA自动采集方式,通过数字滤波基本可以到2mV内的跳动,现在碰到一个奇怪的现象:进行多次上电,偶尔数据会有一个恒定的测量偏移,大概8mV左右,这个 ...…

查看全部问答>

lm3s 811 被弄得锁死了

本帖最后由 paulhyde 于 2014-9-15 03:33 编辑 今天背啊,同学借板子玩,就把JATG锁死了,挨。教训啊,我应该说清楚的。又要等着换芯片啊。挑战啊。换个开发板,大家有什么推荐的吗?谢谢大家了  …

查看全部问答>