第一章基于单片机的网络编程概述随着网络技术的迅猛发展,Internet已经走进千家万户,越来越多的人拥有了随时随地上网的条件,享受着网络带来的方便快捷的生活。同时,随着嵌入式控制技术的成熟,网络也逐步与之结合,深入到工业、楼宇、家居智能化等领域,实现远程数据采集、远程控制等功能。网络化已经成为新一代嵌入式系统发展的一个重要趋势。试想不久的将来,坐在办公室的电脑前就能查看和控制家里的门窗和灯的状态,甚至可以在下班时把家里配好汤料的电饭煲打开,到家就能闻到扑鼻而来的香味了。盛行全球的Internet网络是基于TCP/IP协议族为基础组建的,TCP/IP是网络通讯系统互联的事实标准。研究嵌入式系统的网络化,就要先从TCP/IP的概念入手。1.1TCP/IP的概念及分层结构TCP/IP协议是传输控制协议的简称,它实际上是一个协议族,包括许多相关协议。其中最核心的协议是IP(网际协议)和TCP(传输控制协议),其它还包括ARP(地址解析协议)、RARP(逆地址解析协议)、ICMP(Internet控制报文协议)、UDP(用户数据报协议)、IGMP(Internet组管理协议)、DNS(域名系统)、TFTP(简单文件传送协议)、BOOTP(引导程序协议)、SNMP(简单网络管理协议)、Telnet(远程控制协议)、FTP(文件传送协议)、SMTP(简单邮件传送协议)等重要协议。并且,随着网络技术的发展,还会不断有新的协议加入到TCP/IP协议族。这些协议规范了不同的场景下的网络互连,实际应用中可以根据系统的需要使用其中的一些协议。从TCP/IP协议的数量就可以看出,Internet网络是一个比较复杂的系统,能适配多种应用场景,根据使用协议的不同而实现不同的功能。为了降低网络设计的复杂性,设计者将以分层的方式组织TCP/IP协议,每一层可能包括不同通信服务的多种协议。从最底层的硬件开始,每一层都建立在其下一层的基础上,并负责向其上一层提供服务。只有相邻层才能通过软件接口联系起来,非相邻层没有直接的联系。TCP/IP的分层见图1-1,分为物理链路层、网络层、传输层和应用层四层。图1-1TCP/IP协议族的分层结构物理链路层:包含网络芯片的硬件和基于硬件上的芯片级驱动。随着网络物理介质的不同和使用网络芯片的不同,需要选择不同的通信方式和修改相应的驱动程序,但只要对外提供的接口不变,网络层的程序是不用修改的。例如以太网(Ethernet)和通过Modem上网的方式不同,驱动不同,但不影响网络层。网络层:接收物理链路层过滤后的数据,并对通过识别不同的分组信息后传给传输层中不同的协议。著名的IP(网际协议)是网络层的协议,它支持将多种网络技术互联为一个逻辑网络。IP提供不可靠的、无连接的、尽最大努力交付的分组传输机制,为两个物理设备之间的信息传递提供最好的传输服务。所有具有网络层的因特网设备都会运行IP协议。传输层:传输层的两个重要协议TCP(传输控制协议)和UDP(用户数据报),都是端到端的协议,根据应用程序需要的服务的不同可以选择其中的一个协议。发送时,TCP和UDP都将报文头和数据打包放在IP的数据段中发送出去。接收IP分组后,剥离IP的首部,得出是TCP还是UTP协议,再根据其首部中端口的不同,交给应用层程序处理。应用层:这一层的功能最终面向用户,因此非常丰富,并且千差万别。每一个应用层协议都是为了解决某一类应用问题而规定的,是通信双方都需要遵循该协议才能正常通讯。比如,telnet提供远程登陆服务;FTP提供应用级的文件传输服务;SMTP提供简单的电子邮件发送服务;http提供网页浏览服务;还有域名服务系统DNS、简单网络管理协议SNMP等等。1.2TCP/IP网络的通信流程前面说过,TCP/IP分为四层。那么为什么要这样设计,分层之间怎样通信?我们从生活中的信件传递说起。如果你要告诉对方一些事情,写到信纸上后,需要装到写有对方邮编、地址和收件人的信封里,然后给邮递员。邮递员在邮局里需要将同一城市的信件和物品打包成一个编织袋,袋子上写着始发城市和目的城市,如深圳邮局到北京邮局。然后这个编织袋会经过飞机、火车或汽车送往北京邮局。以上过程都属于“封装”的过程。编织袋到目的城市后,对方邮递员拆开编织袋,将信封送到接收人手中。对方拆开信件后才能读出真正的内容。这个过程属于“解包”的过程。虽然发件人要说的事情不在信封上,信封看起来是个多余的东西。但没有信封的话,每个邮递员要读信才知道发件人要干什么,这样做至少有两点问题:1)邮递员并不关心信件的内容,但它要读完信件才知道要发送的地址,非常浪费时间。2)侵犯了隐私权。所以通过统一格式的信封不仅减轻了邮递员的负担,同时也不会担心别人侵犯了个人的隐私。对物流来说也一样,增加编织袋后,物流就只关心发送站和目的站,不关心里面是信件还是包裹,要送给哪个人。网络通信也是这样,发送方需要一层层“封装”信息,接收方需要一层层“解包”信息。这样不仅方便实现和维护,而且由于模块化设计,隔离层之间的变动不会相互影响,相对比较安全可靠。基于分层设计的TCP/IP通信的基本过程如图1-2。图1-2TCP/IP数据传输过程当发送方的每一层收到其上一层传来的数据后,都要加上本层的首部,然后再传给其下一层。这一层并不知道上一层给它的数据中哪些是用户需要发送的真正数据,它把上一层的协议首部和数据都看成自己的数据。这个过程就称之为“封装”。比如网络层的IP协议接收到传输层TCP送过来的数据后,它并不知道传输的是FTP还是http或其它应用层协议的内容,只知道传过来的数据都是TCP数据,因此它增加一个IP首部,在首部的协议字段中填写TCP协议值(6),并且填写好总长度,校验和等选项后送给物理链路层的以太网协议。以太网层软件再在所有数据前增加一个以太网帧首部后发送出去。在接收方每一层收到相邻的下一层送来的数据后,将本层协议的首部去掉后交给其上一层。这个过程就称之为“解包”。经过层层剥离后,真正的数据交给等待数据的应用程序。1.3单片机控制的网络硬件框图嵌入式系统应用广泛,一些大型的通信基站(常常建立在高山上的铁塔)里的控制器就是ARM或PowerPC等嵌入式处理器,其网络功能比电脑里的通讯要强很多。但开发软件需要考虑很多场景,代码都是几十上百万行,开发测试人员上百人,投入成本很大,不适宜个人学习TCP/IP协议和常用的简单控制。我们要研究的基于单片机控制的网络应用,软硬件要求起点低,成本很低,开发出来具有良好的经济价值。硬件平台结构如1-3所示:其中单片机选51系列单片机,要求程序存储器大于16K(一般的增强型51如PHILIPS公司的P89C51RD2,STC的STC89C516RD的程序存储器都接近64K),由于单片机内部RAM比较小,因此需要外接32K的RAM,一般选用62256芯片。与以太网接口的芯片采用RealTek公司的RTL8019AS,RTL8019AS是10Mb/s以太网接口芯片,ISA接口。同时通过MAX232与PC机或其它调试机连接,可以显示调试或相关信息。如果需要使用EEPROM存储相关的IP、MAC等信息,可以外接I2C接口的芯片,如24C02。不过很多单片机内部都集成了EEPROM,如STC的单片机,因此也可以省略存储电路。为保证程序的可靠,看门狗也是必须的,不过很多单片机也是片内集成硬件看门狗,具体可参考芯片手册。由此可见,实现单片机上网的硬件电路比较简单,因此成本也低。由于单片机最小系统(晶振,电源等)和所接芯片(MAX323,RTL8019,RAM等)都有成熟的电路模块,可参考相关芯片手册,这里不再详述。与RTL8019AS的连线介绍也可参考《第三章网络芯片的驱动》。图1-3基于单片机控制的硬件框图1.4常用嵌入式TCP/IP协议栈随着网络的发展,越来越多的人投入到网络协议栈的研究,开发出许多优秀的协议栈。一些著名的嵌入式操作系统都带有强大的TCP/IP功能,如vxWorks,linux。同时,也涌现了许多一些源代码公开的免费协议栈,目前较为著名的免费开源协议栈有:lwIP、uIP、openTCP、TinyTCP等。下面介绍在嵌入式系统应用很广泛的lwIP和uIP协议栈。lwIP:是TCP/IP协议栈的一个小型实现,支持的协议功能比较完整,包括带IP和ICMP的TCP和UDP传输层。一般需要多任务环境支持(也可以移植到没有操作系统的环境下运行),仅协议栈的代码占用ROM40KB,RAM10K以上,不适合8位机系统。目前流行的移植版本是基于ucos2操作系统上和ARM7控制系统。uIP:uIP是专门为8位和16单片机设计的一个非常小的TCP/IP协议栈。uIP完全用C编写,可以很方便的移植到各种不同的结构和操作系统上。一个编译的栈可以有几KBROM或几百字节RAM中运行。并且其硬件处理层、协议栈层和应用层共用一个全局缓存区,不存在数据的拷贝,极大的节省空间和时间。由于结构简单、功能可靠,很多8位单片机都移植uIP协议栈。1.5单片机TCP/IP网络特点单片机在嵌入式领域中属于很低端的处理器,其资源和处理能力有限。首先,它的程序存储空间ROM和数据存储空间RAM都不能超过64K。其次,它的CPU频率一般在12M~40M之间,指令的执行速度相对慢,导致网络传输速度很难上去。据计算,12M的51单片机的最快网络传送速度大概为25KB/s。这些特点,导致单片机上不可能运行大而全的TCP/IP协议栈。需要使用精简的嵌入式协议栈。虽然处理速度和通讯流量不允许很大,但对于一般的工业、楼宇、家居智能化等领域也足够应付。更重要的是,它的成本很低,具有很高的经济价值。考虑到这些特点,uIP协议栈是一个不错的选择。因此本书以图1-3基于单片机控制的硬件和uIP协议栈介绍单片机的TCP/IP网络编程与应用。第二章uIP协议栈分析2.1uIP特性uIP由瑞典计算机科学学院(网络嵌入式系统小组)的AdamDunkels开发。其源代码由C语言编写,并完全公开,所有代码和相关说明文档可以到下载。最新版本是uIP1.0版本,本书移植和使用的版本正是此版本。uIP协议栈去掉了完整的TCP/IP中不常用的功能,简化了通讯流程,但保留了网络通信必须使用的协议,设计重点放在了IP/TCP/ICMP/UDP/ARP这些网络层和传输层协议上,保证了其代码的通用性和结构的稳定性。由于uIP协议栈专门为嵌入式系统而设计,因此还具有如下优越功能:(1)代码非常少,其协议栈代码不到6K,很方便阅读和移植。(2)占用的内存数非常少,RAM占用仅几百字节。(3)其硬件处理层、协议栈层和应用层共用一个全局缓存区,不存在数据的拷贝,且发送和接收都是依靠这个缓存区,极大的节省空间和时间。(4)支持多个主动连接和被动连接并发。(5)其源代码中提供一套实例程序:web服务器,web客户端,电子邮件发送程序(SMTP客户端),Telnet服务器,DNS主机名解析程序等。通用性强,移植起来基本不用修改就可以通过。(6)对数据的处理采用轮循机制,不需要操作系统的支持。由于uIP对资源的需求少和移植容易,大部分的8位微控制器都使用过uIP协议栈,而且很多的著名的嵌入式产品和项目(如卫星,Cisco路由器,无线传感器网络)中都在使用uIP协议栈。2.2uIP架构uIP相当于一个代码库,通过一系列的函数实现与底层硬件和高层应用程序的通讯,对于整个系统来说它内部的协议组是透明的,从而增加了协议的通用性。uIP协议栈与系统底层和高层应用之间的关系如图2-1所示。图2-1uIP在系统中的位置从上图可以看出,uIP协议栈主要提供了三个函数供系统底层调用。即uip_init(),uip_input()和uip_periodic()。其与应用程序的主要接口是UIP_APPCALL()。uip_init()是系统初始化时调用的,主要初始化协议栈的侦听端口和默认所有连接是关闭的。当网卡驱动收到一个输入包时,将放入全局缓冲区uip