源码公开的TCP/IP协议栈在远程监测中的应用

2007-03-09 19:03:27来源: 互联网
摘要:介绍一个适用于8/16位单片机嵌入式TCP/IP协议栈(uIP)在发电机远程监测系统中的应用。重点阐述uIP的功能特性、体系结构和相关接口,并详细介绍如何在该协议栈上实现一个嵌入式Web服务器。目前uIP已成功地移植到51单片机上。 关键词:TCP/IP协议栈 嵌入式Web服务器 远程监测 目前,随着互联网的发展,越来越多的工业测控设备已经将网络接入功能作为其默认配置,以实现设备的远程监控和信息分布式处理。笔者曾参与某发电机射频监测仪的开发,该设备主要用于诊断和预警发电机早期故障,并通过RS232接口定时输出电平和状态数据,现场专门设一台PC作接收、显示及存储。每年都要有专家到各发电厂对以往数据作检查和诊断,不胜其烦。因此有必要设计一个RS232到Internet的数据传输模块,以便对发电机的运行状况作远程监测。设计该模块的关键在于如何实现一个嵌入式TCP/IP协议栈,根据以往的经验,自己设计一个协议栈的难度很可能超过应用本身,而采用商业的协议栈似乎又无必要 (功能过于复杂),最后笔者选用一种功能简易的免费TCP/IP协议栈uIP 0.9作为设计核心。 1 嵌入式TCP/IP协议栈 目前,市场上几乎所有的嵌入式TCP/IP协议栈都是根据BSD版的TCP/IP协议栈改写的。在商业嵌入式TCP/IP协议栈大都相当昂贵的情况下,很多人转而使用一些源代码公开的免费协议栈,并加以改造应用。目前较为著名的免费协议栈有: lwIP(Light weight TCP/IP Stack)——支持的协议比较完整,一般需要多任务环境支持,代码占用ROM>40KB,不适合8位机系统,没有完整的应用文档; uC/IP(TCP/IP stack for uC/OS)—基于uC/OS的任务管理,接口较复杂,没有说明文档。 笔者采用的协议栈系瑞典计算机科学研究所Adam Dunkels开发的uIP0.9。其功能特性总结如下: *完整的说明文档和公开的源代码(全部用C语言编写,并附有详细注释); *极少的代码占用量和RAM资源要求,尤其适用于8/16位单片机(见表1); *高度可配置性,以适应不同资源条件和应用场合; *支持ARP、IP、ICMP、TCP、UDP(可选)等必要的功能特性; *支持多个主动连接和被动连接并发,支持连接的动态分配和释放; *简易的应用层接口和设备驱动层接口; *完善的示例程序和应用协议实现范例。 表1 uIP在ATMEL AVR上代码和RAM占用情况 协议模块 代码大小/B 使用的RAM/B ARP 1324 118 IP/ICMP/TCP 3304 360 HTTP 994 110 校验和函数 636 0 数据包缓存 0 400 总和 6258 988 注:配置为1个TCP听端口,10个连接,10个ARP表项,400字节数据包缓存。 正是由于uIP所具有的显著特点,自从0.6版本以来就被移植到多种处理器上,包括MSP430、AVR和Z80等。笔者使用的uIP0.9是2003年11月发布的版本。目前,笔者已将它成功移植到MCS-51上了。 2 uIP0.9的体系结构 uIP0.9是一个适用于8/16位机上的小型嵌入式TCP/IP协议栈,简单易用,资源占用少是它的设计特点。它去掉了许多全功能协议栈中不常用的功能,而保留网络通信所必要的协议机制。其设计重点放在IP、ICMP和TCP协议的实现上,将这三个模块合为一个有机的整体,而将UDP和ARP协议实现作为可选模块。UIP0.9的体系结构如图1所示。 UIP0.9处于网络通信的中间层,其上层协议在这里被称之为应用程序,而下层硬件或固件被称之为网络设备驱动。显然,uIP0.9并不是仅仅针对以太网设计的,以具有媒体无关性。 为了节省资源占用,简化应用接口,uIP0.9在内部实现上作了特殊的处理。 ①注意各模块的融合,减少处理函数的个数和调用次数,提高代码复用率,以减少ROM占用。 ②基于单一全局数组的收发数据缓冲区,不支持内存动态分配,由应用负责处理收发的数据。 ③基于事件驱动的应用程序接口,各并发连接采用轮循处理,仅当网络事件发生时,由uIP内核唤起应用程序处理。这样,uIP用户只须关注特定应用就可以了。传统的TCP/IP实现一般要基于多任务处理环境,而大多数8位机系统不具备这个条件。 ④应用程序主动参与部分协议栈功能的实现(如TCP的重发机制,数据包分段和流量控制),由uIP内核设置重发事件,应用程序重新生成数据提交发送,免去了大量内部缓存的占用。基于事件驱动的应用接口使得这些实现较为简单。 3 uIP的设备驱动程序接口 uIP内核中有两个函数直接需要底层设备驱动程序的支持。 一是uip_input()。当设置驱动程序从网络层收到的一个数据包时要调用这个函数,设备驱动程序必须事先将数据包存入到uip_buf[]中,包长放到uip_len,然后交由uip_input()处理。当函数返回时,如果uip_len不为0,则表明有带外数据(如SYN,ACK等)要发送。当需要ARP支持时,还需要考虑更新ARP表示或发出ARP请求和回应,示例如下: #define BUF((struct uip_eth_hdr*)%26;amp;uip_buf[0]) uip_len=ethernet_devicedriver_poll(); //接收以太网数据包(设备驱动程序) if(uip_len>0){ //收到数据 if(BUF->type= =HTONS(UIP_ETHTYPE_IP)){//是IP包吗? uip_arp_ipin(); //去除以太网头结结,更新ARP表 uip_input(); //IP包处理 if(uip_len>0){ //有带外回应数据 uip_arp_out(); //加以太网头结构,在主动连接时可能要构造ARP请求 ethernet_devicedriver_send(); //发送数据到以太网(设备驱动程序) } }else if(BUF->type==HTONS(UIP_ETHTYPE_ARP)){ //是ARP请求包 uip_arp_arpin(); //如是是ARP回应,更新ARP表;如果是请求,构造回应数据包 if(uip_len>0){ //是ARP请求,要发送回应 ethernet_devicedriver_send(); //发ARP回应到以太网上 } } 另一个需要驱动程序支持的函数是uip_periodie(conn)。这个函数用于uIP内核对各连接的定时轮循,因此需要一个硬件支持的定时程序周期性地用它轮循各连接,一般用于检查主机是否有数据要发送,如有,则构造IP包。使用示例如下: for(i=0;i0){ uip_arp_out(); ethernet_devicedriver_send(); } } 从本质上来说,uip_input()和uip_periodic()在内部是一个函数,即uip_process(u8t flag),UIP的设计者将uip_process(UIP_DATA)定义成uip_input(),而将uip_process(UIP_TIMER)定义成uip_periodic(),因此从代码实现上来说是完全复用的。 4 uIP的应用程序接口 为了将用户的应用程序挂接到uIP中,必须将宏UIP_APPCALL()定义成实际的应用程序函数名,这样每当某个uIP事件发生时,内核就会调用该应用程序进行处理。如果要加入应用程序状态的话,必须将宏UIP_APPSTATE_SIZE定义成应用程序状态结构体的长度。在应用程序函数中,依靠uIP事件检测函数来决定处理的方法,另外可以通过判断当前连接的端口号来区分处理不同的连接。下面的示例程序是笔者实现的一个Web服务器应用的框架。 #define UIP_APPCALL uip51_appcall #define UIP_APPSTATE_SIZE sizeof(struct uip51app_state) struct uip51app_state{ unsigned char * dataptr; unsigned int dataleft; }; void uip51_initapp{ //设置主机地址 u16_t ipaddr[2]; uip_ipaddr(ipaddr,202,120,127,192); uip_sethostaddr(ipaddr); uip_listen(HTTP_PORT); //HTTP WEB PORT(80); } void uip51_appcall(void){ struct uip51app_state *s; s=(struct uip51lapp_state *)uip_conn->appstate; //获取当前连接状态指针 if(uip_connected()){ … //有一个客户机连上 } if(uip_newdat()||uip_rexmit()){ //收到新数据或需要重发 if(uip_datalen()>0){ if(uip_conn->lport==80){ //收到GET HTTP请求 update_table_data();//根据电平状态数据表动态生成网页 s->dataptr=newpage; s->dataleft=2653; uip_send(s->dataptr,s->dataleft); //发送长度为2653B的网页 } } } if(uip_acked()){ //收到客户机的ACK if(s->dataleft>uip_mss()%26;amp;%26;amp;uip_conn->lport==80){ //发送长度>最大段长时 s->dataptr+=uip_conn->len; //继续发送剩下的数据 s->dataleft-=uip-conn->len; uip_send(s->dataptr,s->dataleft); } return; } if(uip_poll()) {… //将串口缓存的数据复制到电平状态数据表 return; } if(uip_timedout()|| //重发确认超时 uip_closed()|| //客户机关闭了连接 uip_aborted()){ //客户机中断连接 return;} } 5 uIP0.9在电机远程监测系统中的应用 笔者设计了一个嵌入式Web模块UIPWEB51,用于将发电机射频监测仪串口输出的数据上网,以实现对发电机工作状态的远程监测,目前已获得初步成功。该模块的硬件框图如图2所示。 单片机采用的是Atmel的AT89C55WD,它内置20KB程序Flash,512字节RAM,3个这时器/计数器,工作在22.1184MHz时具有约2MIPS的处理速度。网卡芯片同样采用的是低成本的RTL8019AS,是一款NE2000兼容的网卡芯片,系统外扩了32KB的SRAM,用于串口数据和网络数据的缓冲,另外还存放了uIP的许多全局变量。 UIPWEB51的主程序采用中断加轮循的方式,用中断触发的方式接收发电机射频监测仪发出的数据,开设置了一个接收队列暂存这些数据。在程序中轮循有无网络数据包输入,如有则调用uIP的相关处理函数(如上uip_input()使用示例);如无则检测定时轮循中断是否发生。这里将T2设为uIP的定时轮循计数器,在T2中断中设置轮循标志,一旦主程序检测到这一标志就调用uip_periodic()轮循各连接(如上uip_periodic()使用示例)。 UIPWeb51的应用程序(如uIP的应用程序接口示例),这个Web服务器首先打开80端口的监听,一旦有客户机要求连上,uIP内部会给它分配一个连接项,接着等收到客户机IE浏览器发出的“GET HTTP……”请求后,将发电机电平与状态数据队列中的数据填入网页模板,生成一幅新的网页发给客户机。因为这幅网页的大小已经超过uIP的最大段长(MSS),因此在uIP内核第一次实际只发出了MSS个字节,在连接处于空闲的时候(uip_poll()),应用程序可以从串口队列中读出原始数据,经格式处理后再存到电机电平与状态数据队列中,而在这个队列中保存着当前1min的设备工作数据,以便下次更新网页时使用。在网页中添加了更新按钮,一旦浏览器用户占击了按钮,浏览器会自动发出CGI请求,UIPWEB51收到后,立即发送包含最新数据的网页。如果uIP接收ACK超时,它会自动设置重发标志,应用程序中可以用uip_rexmit()来检测这个标志,重新生成网页并发送。一旦用户关闭了浏览器,uIP也会自动检测到这一事件(应用程序中可以用uip_closed()来检测),并且释放掉这个连接项。 图3是UIPWEB51的总体程序结构图。 6 测试结果 将uIP0.9配置成允许4个并发连接,1个监听端,10端个ARP表项,去掉UDP支持,UIP_ZBUFSIZE=1500和其它优化选项。用KEIL C编译,整个uIP0.9内核模式代码量小于8KB(含Web应用程序),内核对RAM的占用小于2KB(不含网页)。整个系统程序的代码量小于12KB,占用的RAM小于10KB。另外,在公网上测试了该模式的传输速度,大于20Kbps,对于此项应用已达到要求。目前,该模块正准备应用于新一代的发电机射频监测系统中。

关键字:源码  公开  协议  协议栈

编辑: 引用地址:http://www.eeworld.com.cn/wltx/qtjs/200703/2787.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。
论坛活动 E手掌握
微信扫一扫加关注
论坛活动 E手掌握
芯片资讯 锐利解读
微信扫一扫加关注
芯片资讯 锐利解读
推荐阅读
全部
源码
公开
协议
协议栈

小广播

独家专题更多

富士通铁电随机存储器FRAM主题展馆
富士通铁电随机存储器FRAM主题展馆
馆内包含了 纵览FRAM、独立FRAM存储器专区、FRAM内置LSI专区三大部分内容。 
走,跟Molex一起去看《中国电子消费品趋势》!
走,跟Molex一起去看《中国电子消费品趋势》!
 
带你走进LED王国——Microchip LED应用专题
带你走进LED王国——Microchip LED应用专题
 
电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2016 EEWORLD.com.cn, Inc. All rights reserved