admin 管理员组

文章数量: 1086019


2024年3月13日发(作者:表单大师如何导出excel)

TCP/IP在51单片机上的实现特点和方法

李章林

1

,张立民

1

( 1 南开大学信息技术科学学院, 天津 300071 )

摘要:为了实现51单片机接入internet,开发基于51单片机的TCP/IP具有重要意义。为此开发了zlIP,它是针对51单片机的特点使用

KeilC51编程语言编写的TCP/IP,具有代码量小和兼容BSD套接字(socket)用户接口等特点。zlIP1.0版注重于运行速度,zlIP2.0版注重

于用户接口的易用性,以从不同的角度试验在51单片机上实现TCP/IP的特点。通过比较两个版本的优缺点和吸收国内外其它TCP/IP的优

点,分析了在单片机上实现TCP/IP的速度、程序大小、内存大小、编译器等特点,并针对这些特点总结和提出多种技巧和方法,并对这些

技巧、方法的优缺点进行了分析。最后讲述了几点关键技术:设计清晰的TCP/IP和应用层的接口、采用前后台和多线程程序结构的比较,

内存管理方法和防止多余的内存拷贝,实现数据包整序重发和窗口控制等。

关键词:TCP/IP;单片机;zlIP

中文分类号: 文献标识码:A 文章编号:1006-8740(2003)-00-0000-00

1 引言

随着网络应用的不断扩大,将各类电子设备接入Internet的需求越来越大。电子设备入网有多

种解决方案:例如使用嵌入式系统,如使用ARM+Linux;一些实现TCP/IP的芯片也已经可以获得,

(1)

例如Analog Devices推出的Internet Modem;在51系列单片机运行TCP/IP协议栈等。前两种

方案具有良好的性能,而在单片机上实现TCP/IP的方案具有很低的价格,在某些对网络速度要求不

高的领域,有广阔的应用前景。

2 TCP/IP在单片机上实现的特点

2.1 速度慢

我们先来了解51单片机网络传输的极限速率。TCP/IP发送过程中主要的运算量集中在三个部

分:应用程序将数据拷贝到RAM、计算TCP校验和、将RAM中的数据包拷贝到网络设备的发送缓冲

区。对每一个字节数据,两次拷贝大致共使用12×2=24个指令周期;计算TCP校验和使用16个指

令周期。采用12M的晶振,最高网络传输速度为25K字节/秒。实际上要比这个速度慢,zlIP第一

版速度只有11.752K字节/秒。

为了提高速度可以采用快速的单片机比如Winbond公司的77E58或者AVR单片机,当然还可以

提高晶振频率。除此之外还有:使用KeilC时,尽量避免使用Reentrant函数,Reentrant类型的

函数比一般函数速度要慢很多,但是某些时候为了程序结构的需要必须使用Reentrant,这就需要

(2)

在速度和结构之间作一个选择;指针使用“指定存储类型”的指针(memory-specific pointer)

精简协议栈去除运算量大但是用处不大的功能,目前zlIP中TCP定时重发时间是固定的,也没有拥

塞窗口控制,也没有IP层路由算法;防止数据包的不必要的拷贝;优化计算校验和和内存拷贝函数。

2.2 程序存储空间和外部RAM空间不大

通常TCP/IP协议栈需要大量的RAM来存储需要被应答的TCP包,如果规定时间内没有被应答则

重发这个TCP包,被应答以后释放这个TCP包。

(3)

为了减小RAM使用量,能否不存储需要被应答的TCP包?

。当数据包需要重新发送时,如果

能够重新产生数据包所需的数据,那时就可以不存储。例如存在于EEPROM中的html网页。但是这

种方法存在以下两个缺点:一,TCPIP和应用层接口变得复杂。当需要重发时,必须需要应用层重

新产生数据,实际上将TCP负责的重发机制转移到了应用层。应用层程序编写变得复杂。二,对数

据无法重新产生的应用不适用。例如语音采集。

2.3编译器

TCP/IP一般采用C语言或者混合汇编来写。以KeilC516.0编译器为例。与X8086编辑的代码

不同,使用KeilC要注意函数重入、指针、函数指针这三个问题。使用可重入函数和一般指针(generic

pointer)使得程序代码增大,运行速度变慢。使用函数指针时,要么需要手动重建调用树(Call

tree),要么将通过函数指针调用的函数都设置为可重入函数。所以尽量少用重入函数、函数指针和

1

一般指针。

3 zlIP的特点和实现技巧

3.1 特点

其它的TCP/IP有lwIP、uIP、ucIP、tinyTCP等。其中lwIP、uIP、tinyTCP已经成功地移植到

了单片机。lwIP是专门为微处理器设计的TCP/IP协议栈,lwIP的功能很全面,但是相对来说代码

(4)

较大,有人做过移植lwip+ucOSII代码量为60K。uIP侧重于减小代码量(选择AVR为目标器件时,

代码为5K左右)和减小RAM使用量(100字节左右)。uIP采用了不保存需要应答的数据包的RAM使

用方案,没有和BSD的套接字接口兼容,应用层接口较复杂。zlIP介于uIP和lwIP之间,它针对

单片机设计,有中等代码量和RAM使用量,使用套接字的应用层接口,所有的外部变量都使用了xdata

类型,全部指针都为明确存储类型的指针,需要重入的函数已经声明为reentant,使用KeilC的小

模式下编译。使用12M晶振、KeilC编译器、89C52单片下测试的技术参数如下:

表1:zlIP技术参数(Technical parameter of zlIP)

zlIP的版本

1.0

2.0

代码量(字节)

6791

14464

外部RAM使用量(字节)发送速度(字节/秒)

20K

4K

11.752K

5.892K

2.0版主要功能有:支持套接字形式的多个TCP连接。支持多个网络设备。支持通过网关发送数据

包和数据包转发功能。响应ping命令。支持TCP包的整序、重发和窗口控制流量控制。

3.2 zlIP实现TCP/IP的技巧和方法

3.2.1设计套接字接口

zlIP接口函数基本和BSD的套接字接口相同。提供的用户接口函数有:

z TCPSocket()。函数原型:socket * TCPSocket(IP_ADDR ScrIP)。功能:申请一个套接字。ScrIP

是这个套接字的本地IP地址。返回socket类型指针,如果申请失败返回NULL。

z TCPConnect()。函数原型:BOOL TCPConnect(socket * pTCB, IP_ADDR DestIP, WORD

DestPort,void (* recv)(void * buf,WORD size),void (* close)(socket * pSocket))。功

能:向IP地址为DestIP的服务器的DestPort端口发起连接。参数recv和close用于设置当

接收到数据包和对方要求关闭TCP连接时应该调用的回调函数指针。连接成功返回TRUE,否则

返回FALSE。

z TCPSend()。函数原型:BOOL TCPSend(socket * pTCB,void *buf,WORD DataSize)。功能:发

送数据。发送数据的TCP连接是套接字指针pTCB对应的连接,发送的数据的起始地址为buf,

大小为DataSize。发送成功返回TRUE,否则返回FALSE。

z TCPListen()。函数原型:BOOL TCPListen(socket *pTCB,WORD ScrPort,void (* accept)(socket

*pNewTCB)) 。功能:使用套接字pTCB在ScrPort端口监听。参数accept是当有客户端向这个

监听端口连接成功时调用的回调函数指针。

z TCPClose()。函数原型:void TCPClose(socket *pTCB)。功能:我方主动关闭连接时调用TCPClose

函数,它将要求关闭套接字pTCB对应的连接。TCPClose返回以后这个TCP连接可能保持,因

为另一方还没有发起关闭请求。

z TCPAbort()。函数原型:void TCPAbort(socket *pTCB)。功能:当使用完这个套接字以后,调

用TCPAbort,将这个套接字释放,还给系统。

TCP/IP协议运行中,接收数据包到达、另一方发起关闭连接、另一方向我方发起连接这些事件

发生以后如何通知应用层?下面以收到数据包为例提供几种思路:(1)TCP/IP模块设置一个变量

bRecv表征是否有数据包到达,应用层必须反复的查询这个变量,如果为TRUE,则调用一个接收函

数接收这个数据包。但是这种方法增加了应用层程序的复杂性。(2)固定的回调函数。当TCP层接收

到一个数据包后调用OnReceive(pTCB,buf,size)函数。用户必须在应用层定义一个函数名为

OnReceive的函数。然后在OnReceive函数中处理接收的数据。(3)回调函数指针。每个套接字保存

2


本文标签: 使用 数据包 应用层 连接 函数