第一次写博客,不足之处各位同仁多多纠正。最近在做一个IP智能广播公共系统,类似于IP服务器点播之类。以前做过IP音乐播放器终端,服务端发PCM流给终端设备,终端设备解码放歌,IP地址固定分配的,当时用的uIP,uIP主要以占内存和ROM少著称,实用8位16位32位单片机,但功能强大不如LWIP。IP智能广播终端设备基本不在一个地方,有可能跨小区基本是多栋楼宇之间设备语音通信,一个局域网之间数据共享多个路由器连接,这个时候嵌入式终端自动获取是重之重要。
首先介绍下LWIP移植过程。类似于文件管理,EMWIN GUI它们之间都有很大共性(个人见解),它们最重要的是在“读”和“写”之间谋划的,现在程序设计已是很成熟了,应用层以基本走向完善,这完全感谢前人为我们做出的贡献,所以你只要把一样东西最原始的操作方式交给协议栈,协议栈就可以在最原始的方法衍生不同的类。文件管理也是,你知道把储存设备的读页写页交给它,它以最合理的方式帮你管理文件资源,GUI软件也是,你只要把LCD读像素点和写像素点交给它,它就为你提供丰富的控件。
废话少说,上代码。LWIP移植也是要你交给它一个读包和写包它才能为你提供服务。
在LWIP协议栈中找到ethernetif.c文件在下个函数提供一个读包的底层函数
static struct pbuf *low_level_input( struct netif *netif )
{
struct pbuf *q,*p = NULL;
u16 Len = 0;
int i =0;
Len = etherdev_read(Data_Buf,1520 *4); //这个就是读包的底层函数
if ( Len == 0 ) return 0;
p = pbuf_alloc(PBUF_RAW, Len, PBUF_POOL);
if (p != NULL)
{
for (q = p; q != NULL; q = q->next)
{
memcpy((u8_t*)q->payload, (u8_t*)&Data_Buf[i], q->len);
i = i + q->len;
}
if( i != p->tot_len ){ return 0;}
}
return p;
}
在下列函数写入一个发送包的底层函数
static err_t low_level_output( struct netif *netif, struct pbuf *p ) /*µ×²ã·¢ËÍÊý¾Ýº¯Êý*/
{
struct pbuf *q;
int i = 0;
err_t xReturn = ERR_OK;
/* Parameter not used. */
for(q = p; q != NULL; q = q->next)
{
memcpy(&Tx_Data_Buf[i], (u8_t*)q->payload, q->len);
i = i + q->len;
}
dm9k_send_packet(Tx_Data_Buf,i); //这个就是要写入发送包函数
return xReturn;
}
两大要点准备好了接下来就把网络设备初始化交这协议栈
在下列函数写入初始化函数
static void low_level_init( struct netif *netif )
{
/* set MAC hardware address length */
netif->hwaddr_len = 6;
/* set MAC hardware address */
netif->hwaddr[0] = macaddress[0];
netif->hwaddr[1] = macaddress[1];
netif->hwaddr[2] = macaddress[2];
netif->hwaddr[3] = macaddress[3];
netif->hwaddr[4] = macaddress[4];
netif->hwaddr[5] = macaddress[5];
/* maximum transfer unit */
netif->mtu = netifMTU;
/* broadcast capability */
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
/* Initialise the EMAC. This routine contains code that polls status bits.
If the Ethernet cable is not plugged in then this can take a considerable
time. To prevent this starving lower priority tasks of processing time we
lower our priority prior to the call, then raise it back again once the
initialisation is complete. */
etherdev_init(netif->hwaddr); //这个就是要写入初始化的函数
}
现在是万事俱备只欠东风,就如CPU它也需要一个晶振心脏它才能工作,协议栈也是,它也需要为提供一个心脏,这个心脏就是一个10ms自加的计数器
........
刚开始已静态IP形式工作,把程序写入板子,然后定义一个UDP服务器发送,已用来观察是否工作,用抓包软件观察其数据包效果图如下
我设置的静态IP为192.168.1.31而抓包软件显示的却是192.169.129.31很明显中间两个字节数据错乱,第一和第四两个字节无错乱说明CPU给DM9000发数据时序是对的,因为DM9000我设置的是工作在8位字宽传送并非16字宽,后来打开PCB板数据以太网接收和发送差分对没等长,在Enc28J60没等长也正常工作,为什么呢?原因就是10MBps和100MBps区别,信号的完整性是跟频率有关系的,
通过查分等差调节第二次打板,已静态IP工作时序正确。
现在我们就开始让LWIP自动获取IP,LWIP有自动获取IP的源码,无需我们自己去写,找到lwipopts.h头文件将其设置为1,为1就是自动获取IP.
然后 通过netif_set_default(&DM9000);netif_set_up(&DM9000);函数使能DM9000烧入板子
通过抓包软件设置抓包为ARP0X0806
说明路由器已经给DM9000分配IP,然后ping 192.168.1.109
ping 通了,拔掉网口在ping无反应,说明192.168.1.109是DM9000自动获取的。
需要完整代码联系我[email protected]