迅维网

查看: 3296|回复: 0
打印 上一主题 下一主题

【NUCLEO-F412ZG试用体验】移植LWIP,进行ping实现

[复制链接]
跳转到指定楼层
1#
发表于 2016-12-13 15:39:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式 来自: 山东青岛 来自 山东青岛

马上注册,获取阅读精华内容及下载权限

您需要 登录 才可以下载或查看,没有帐号?注册

x
不知不觉都试用了这么久,发到了第六弹,只可惜发的质量都不怎么样,基本都是贴代码。不管那么多了,这次是移植了LWIP,简单测试了一下ping,最长时间7ms,最短时间4ms,时间是有那么点长哈,之前在F407上外接phy的网返时间基本都是1ms,这差别是有那么点大。不管时间长短,功能是实现了。


                               
登录/注册后看高清大图


在工程中添加lwip库,本人用的是IAR,工程目录如下。keil能用,不过还是习惯用IAR,后续打算迁移到eclipse上,毕竟keil和IAR目前用的都是pojie版的,对于一个爱折腾的人来说,还是要折腾一下,毕竟之前也用过eclipse玩过java,用着还是不错的。闲话少说,网络相关的代码都在lwip这个group里。

                               
登录/注册后看高清大图

首先是介绍初始化代码,又是粘贴party,哎,没办法。理论性的东西自己还在摸索。
  • void net_init(void){
  •         struct ip_addr ipaddr, netmask, gw;
  •         UINT8_T tm;
  •         lwip_init();//lwip协议栈初始化
  • #if LWIP_DHCP==1//是否启用DHCP功能自动获取IP,这个需要接到路由上,直接和电脑连接需要使用固定ip
  •         IP4_ADDR(&gw, 0, 0, 0, 0);
  •         IP4_ADDR(&ipaddr, 0, 0, 0, 0);
  •         IP4_ADDR(&netmask, 0, 0, 0, 0);
  • #else
  •         IP4_ADDR(&gw, 192, 168, 0, 1);
  •         IP4_ADDR(&ipaddr, 192, 168, 0, 105);
  •         IP4_ADDR(&netmask, 255, 255, 255, 0);
  • #endif
  •         netif_add(&dm_netif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input);
  •         netif_set_default(&dm_netif);
  •         netif_set_up(&dm_netif);
  • #if LWIP_DHCP==1
  •         dhcp_start(&dm_netif);
  •         tm = 50;
  •         while(tm!=0){
  •                 dhcp_fine_tmr();
  •                 delay_ms(200);
  •                 tm--;
  •         }
  •         if(dm_netif.dhcp!=NULL&&(dm_netif.dhcp->offered_ip_addr.addr!=0)&&(dm_netif.dhcp->offered_sn_mask.addr!=0)&&(dm_netif.dhcp->offered_gw_addr.addr!=0)){
  •                 netif_set_addr(&dm_netif, &(dm_netif.dhcp->offered_ip_addr), &(dm_netif.dhcp->offered_sn_mask), &(dm_netif.dhcp->offered_gw_addr));
  •                 netif_set_up(&dm_netif);
  •         }else{
  •                 IP4_ADDR(&gw, 192, 168, 0, 1);
  •                 IP4_ADDR(&ipaddr, 192, 168, 0, 105);
  •                 IP4_ADDR(&netmask, 255, 255, 255, 0);
  •                 netif_set_addr(&dm_netif, &ipaddr, &netmask, &gw);
  •                 netif_set_up(&dm_netif);
  •         }
  •         dhcp_stop(&dm_netif);
  • #endif        <img src="http://bbs.elecfans.com/forum.php?mod=image&aid=424380&size=300x300&key=1ae9ddfd57145c59&nocache=yes&type=fixnone" border="0" aid="attachimg_424380" alt="">
  • }

[color=rgb(51, 102, 153) !important]复制代码

接下来是网络任务函数,net_task,调用 sch_add(net_task, 0, 250)把任务添加到调度器中,250ms循环一下,这样就OK了,用命令行ping一下,大功告成。其中net_task主要是定时更新lwip相关的时钟。其代码如下
  • UINT16_T arp_tmr = 5000;
  • void net_task(void){
  •         if(sch_autodec(&arp_tmr)){//这个函数是每运行一次就回把arp_timr的值减少net_task的周期,直到为0或小于net_task的周期,并返回1;
  •                 arp_tmr = 5000;
  •                 etharp_tmr();
  •         }
  •         tcp_tmr();
  • }

[color=rgb(51, 102, 153) !important]复制代码


呵呵,太陋了,是不是有点敷衍。移植lwip主要是要实现底层的接口,网卡初始化,数据包收发,都在ethernetif.c这个文件中实现。主要是处理数据包的收发。关于这几个函数的具体实现,请参看附件。移植这事很多帖子都讲烂了,这里说说自己在移植过程中的一点收获。最重要的接口移植都在ethernetif.c这个文件中,此外移植的过程中有一些小细节,就是都文件的加载。也许大神看着会觉得这个很简单,但是就是这个头文件的路径问题,在我第一次移植的过程中成了拦路虎。主要是lwip头文件包含使用了相对路径。所以包含路径时一定要包含相对路径的最顶层路径。一般都要包含以lwip为名字的文件夹所在路径。例如包含ipv4相关api的头文件,其路径如下,则应该包含$PROJ_DIR$\..\lwip\include\ipv4.

                               
登录/注册后看高清大图

下面是全部lwip应该包含的头文件,这里是IAR工程的路径包含。
  • $PROJ_DIR$\..\lwip\include
  • $PROJ_DIR$\..\lwip\arch
  • $PROJ_DIR$\..\lwip\include\ipv4
  • $PROJ_DIR$\..\lwip\api
  • $PROJ_DIR$\..\lwip

[color=rgb(51, 102, 153) !important]复制代码


工程建立相关的内存介绍完了,接下来介绍一下tcp,udp相关的应用。主要就是通过TCP和udp跟电脑之间进行数据收发。这里仅仅介绍一下tcp server,tcp client和udp基本都差不多。
tcp server需要先于tcp client建立,待server建立完成后,client才能连接server,并进行数据通信。首先进行初始化
  • void tcpserver_init(void){
  •         struct tcp_pcb *pcb;
  •         pcb = tcp_new();
  •         tcp_bind(pcb, IP_ADDR_ANY, 8080);//这里是8080接口,为了做webserver才设定的,其实也可以改为其他的端口号,
  •         pcb = tcp_listen(pcb);
  •         tcp_accept(pcb, tcpserver_accept);//设置建立连接时的回掉函数。作用就是当建立连接后设置接收数据回掉函数
  • }

[color=rgb(51, 102, 153) !important]复制代码

tcpserver_accept函数内容如下
  • static err_t tcpserver_accept(void *arg, struct tcp_pcb * pcb, err_t err){
  •         tcp_setprio(pcb, TCP_PRIO_MIN);
  •         tcp_recv(pcb, tcpserver_recv);//建立接收回掉函数
  •         return ERR_OK;
  • }

[color=rgb(51, 102, 153) !important]复制代码

下面看看数据接收部分,主要就是把接收到的数据回传给客户端。
  • static err_t tcpserver_recv(void *arg, struct tcp_pcb * pcb, struct pbuf *p, err_t err){
  •         if(p!=NULL){
  • tcp_recved(pcb, p->tot_len);
  • tcp_write(pcb, p->payload, p->len, 1);
  •                 pbuf_free(p);
  •         }
  •         else if(err==ERR_OK){
  •                 return tcp_close(pcb);
  •         }
  •         return ERR_OK;
  • }

[color=rgb(51, 102, 153) !important]复制代码

下面是数据收发,但是有个问题,字符串中间不能有标点,现在还不知道原因,各位大神如果知道原因给点指点,但是这个我用F407解析命令时倒没有这个问题,中间有空格也没问题。

                               
登录/注册后看高清大图







您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表
附近
店铺
微信扫码查看附近店铺
维修
报价
扫码查看手机版报价
信号元
件查询
点位图 AI维修
助手



芯片搜索

快速回复