历史上的今天
今天是: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链表
史海拾趣
|
华晨汽车继金杯品牌旗下的第六代金杯海狮推出刚刚满月后,再次掀起MPV柴油版新浪潮,于10月25日率先在上海推出了金杯阁瑞斯柴油版。此次推出的金杯阁瑞斯柴油版,分为尊领、智领两大系列总计10款,并均有欧III和欧III+OBD两类车型 环保——首款欧I ...… 查看全部问答> |
|
手机mobile6.0下程序可运行,但在模拟器上运行提示“程序损坏”之类的东西,现求一个ril.dll(版本可能不对),请发到crazy0363@126.com ,谢谢!… 查看全部问答> |
|
我的wince 5.0的开发板上没有电量显示,请问如何实现,麻烦了。 我查了点资料,但是还是没头绪。说是要硬件支持,具体是什么样的支持呢?没搞明白。 还要驱动支持,具体是什么样的支持,也没搞懂。 好像可以AP来做,但我也没查到AP的全称是什么 ...… 查看全部问答> |
|
gooogleman你好,看了你的blog中一篇关于用kitl调试驱动的问题,我现在也想用KITL来调试一个pci设备的驱动,驱动是在PB5.0下开发的,要求在wince5.0下运行,我有如下问题请教: 1.除了可以用网卡来弄KITL以外还可以用USB来弄KITL吗,用USB时硬件上 ...… 查看全部问答> |
|
差分放大电路如果,两个输出端,分别接在两个晶体管的集电极,那么他们是能够有效的抑制漂移的但是如果是单输出,只是在第一个晶体管的集电极加上一个负载电阻,那么它又是怎么抑制漂移的呢?就是通过长尾电阻的负反馈吗?请大家帮忙解答下,谢谢… 查看全部问答> |
|
用32F103CB AD测量6路电池电压,范围1-28V电压只通过电阻分压直接输入AD管脚,采用6路循环DMA自动采集方式,通过数字滤波基本可以到2mV内的跳动,现在碰到一个奇怪的现象:进行多次上电,偶尔数据会有一个恒定的测量偏移,大概8mV左右,这个 ...… 查看全部问答> |
|
本帖最后由 paulhyde 于 2014-9-15 03:33 编辑 今天背啊,同学借板子玩,就把JATG锁死了,挨。教训啊,我应该说清楚的。又要等着换芯片啊。挑战啊。换个开发板,大家有什么推荐的吗?谢谢大家了 … 查看全部问答> |




