国产在线观看免费视频在线|成人网导航|另类 自拍 校园 小说区|不戴的邻居HD中文|国产精品国产三级国产专区53|黄瓜视频app无限看丝瓜视频丝瓜视在线观看|日本大B视频在线

ZLIP使用簡介

李章林1

1 南開大學電子應用實驗室,http://www.sysdsw.cn,版本:2005-11-28)

1 目錄結構

TCP/IP協議棧程序所在目錄

Icmp協議。

IP層。

:網絡接口層。

TCP協議層。

TCPIP內存管理程序。

 

 

 

 

 

 

 

 

:網絡接口協議所在目錄。

ARP協議。

:以太網接口協議。

RTL8019AS以太網接口芯片驅動程序。

 

 

 

 

 

 

:全局函數和宏定義所在目錄

 

 

 

 

:應用層協議所在目錄

:主程序,這里包含一個如何使用的例子程序。

KeilC目錄下是KeilC51的工程文件所在目錄。用KeilC51打開Ex1.Uv2

MCU目錄下是各種類型的51單片機的頭文件。

2 概述

單片機上網技術,是當前的一個熱門技術。單片機上網技術中的一個重要部分是在單片上實現TCP/IP協議棧。現在可獲得的TCP/IP源代碼一般并不為51單片機設計,而51單片機和KeilC51編譯器有其自身的特點:存儲類型、函數指針、重入函數等,ZLIP就是針對這些特點設計的TCP/IP協議棧。

ZLIP設計的目標是:

1)              精簡TCP/IP協議棧,以減小代碼量。ZLIP目前沒有支持UDP協議,ICMP協議也只支持其中的echo協議(響應ping數據包)lwIP是一個功能全面的TCP/IP協議棧,但是相對51來說代碼量較大。

2)             應用層接口簡單,以兼容通用的socket接口。uIP有很小的代碼量和減小代碼量(選擇AVR為目標器件時,代碼為5K左右)和RAM使用量(100字節左右)。uIP采用了不保存需要應答的數據包的RAM使用方案,沒有和BSD的套接字接口兼容,應用層接口較復雜。

3)             針對KeilC51編譯器設計。所有的外部變量都使用了xdata類型,全部指針都為明確存儲類型的指針,需要重入的函數已經聲明為reentant,使用KeilC的小模式下編譯。

使用12M晶振、KeilC編譯器、89C55單片下測試的技術參數如下:

1:技術參數

代碼量(字節)

外部RAM使用量(字節)

發送速度(字節/秒)

14841

11068

5.892K

ZLIP的特點如下:

1)有適中代碼量和RAM使用量。

2)使用類似MFC的CScoket的套接字接口,使用方便。

3)支持多TCP連接、多網絡設備。能方便地移植到多任務操作系統和其它CPU下。能方便地替換網絡接口協議和網卡驅動設備。

4)支持ping命令的響應。

5)為單片機設計:所有的外部變量都使用了xdata類型,全部指針都為明確存儲類型的指針,需要重入的函數已經聲明為reentant,使用KeilC的小模式編譯。

3電路圖

1RTL8019AS電路左半部分

2RTL8019AS電路右半部分

該程序不能在KeilC下軟件仿真,因為程序的運行需要外部電路配合。該51系統的外部電路主要有:以太網接口芯片RTL8019AS電路、外部RAM電路。

       以太網接口芯片RTL8019AS電路圖,如圖1和圖2表示。A0A4接地址線,D0D7接數據線,CSRTL是片選線(低電平有效),RD-WR-接讀寫信號線。

4 應用層接口

zlIP接口函數基本和BSD的套接字接口相同。

41提供的用戶接口函數:

TCPSocket()

函數原型:socket xdata * TCPSocket(IP_ADDR ScrIP)

功能:申請一個套接字。ScrIP是這個套接字的本地IP地址。返回socket類型指針,如果申請失敗返回NULL

 

TCPConnect()

函數原型:BOOL TCPConnect(socket xdata * pTCB, IP_ADDR DestIP, WORD DestPort,void (code * recv)(void xdata * buf,WORD size),void (code * close)(socket xdata * pSocket))

功能:向IP地址為DestIP的服務器的DestPort端口發起連接。參數recvclose用于設置當接收到數據包和對方要求關閉TCP連接時應該調用的回調函數指針。連接成功返回TRUE,否則返回FALSE

 

TCPSend()

函數原型:BOOL TCPSend(socket xdata * pTCB,void xdata *buf,WORD DataSize)

功能:發送數據。發送數據的TCP連接是套接字指針pTCB對應的連接,發送的數據的起始地址為buf,大小為DataSize。發送成功返回TRUE,否則返回FALSE

 

TCPSendEx()

函數原型:BOOL TCPSendEx(socket xdata * pTCB,struct SMemHead xdata *MemHead)

功能:快速發送數據。在使用TCPSend函數時,你首先需要將數據放入buf指向的內存中,然后調用TCPSend函數,接著該函數會將buf指向的內存區數據拷貝到TCP緩沖區中。使用TCPSendEx 時你首先用TCPAllocate(DATA_SIZE)獲得一個TCP緩沖區,然后直接將數據放入TCP緩沖區中,從而比TCPSend函數少一次數據拷貝,提高發送速度。

參數:發送數據的TCP連接是套接字指針pTCB對應的連接,發送的數據放在TCP緩存MemHead中。發送成功返回TRUE,否則返回FALSE

 

TCPListen()

函數原型:BOOL TCPListen(socket xdata *pTCB,WORD ScrPort,void (code * accept)(socket xdata *pNewTCB))

功能:使用套接字pTCBScrPort端口監聽。參數accept是當有客戶端向這個監聽端口連接成功時調用的回調函數指針。

 

TCPClose()

函數原型:void TCPClose(socket xdata *pTCB)

功能:我方主動關閉連接時調用TCPClose函數,它將要求關閉套接字pTCB對應的連接。TCPClose返回以后這個TCP連接可能保持,因為另一方還沒有發起關閉請求。

 

TCPAbort()

函數原型:void TCPAbort(socket xdata *pTCB)

功能:當使用完這個套接字以后,調用TCPAbort,將這個套接字釋放,還給系統。

42使用步驟

使用ZLIP時,在你的主程序中(請看示例程序的main.c文件)需要做的步驟如下:

1)首先設置一個25ms的定時中斷函數(示例程序為Timer函數)。請在中斷函數中調用NetIfTimer(); ARPTimer(); TCPTimer();三個函數。

 

       2)OnReceive函數,它應該有如下的參數和返回值,函數名可以任意:

void OnReceive1(void DT_XDATA * buf,WORD size)  REENTRANT_MUL

在使用TCPConnect函數時,OnReceive1將作為TCPConnect函數的一個參數,也就是設置該socket的接收函數。當TCP連接接收到對方數據時,將自動調用OnReceive1函數。buf指向接收的數據,size是接收的數據量的大小。你可以在OnReceive1中處理接收的數據。當程序中有多個TCP連接同時存在時,你需要給每個連接準備一個OnReceive函數。

 

       3)OnClose函數,它應該有如下的參數和返回值,函數名可以任意:

void OnClose1(socket DT_XDATA * pSocket) REENTRANT_MUL

類似于OnReceive函數,當TCP連接的另一方首先向我方發起關閉連接的請求時,系統將自動調用OnClose函數。pSocket指向將要關閉的socket。如果你想立即關閉這個連接則在OnClose函數中調用TCPClose函數。當程序中有多個TCP連接同時存在時,你需要給每個連接準備一個OnClose函數。

 

4)OnAccept函數。如果你的程序中用到TCPListen函數監聽某端口,這時需要寫OnAccept函數。它應該有如下的參數和返回值,函數名可以任意:

void OnAccept1(socket DT_XDATA *pNewSocket) REENTRANT_MUL

當一個正在listensocket接受了對方的連接以后將會自動調用該函數。pNewSocket是將要獲得這個連接的控制權的socket指針。一般在OnAccept函數中做以下處理:

       ExAccept = pNewSocket;            //保存pNewSocket,以后可以用ExAccept發送數據

       pNewSocket->recv = OnAcceptRecv;  //設置pNewSocketOnReceive函數。

       pNewSocket->close = OnClose;          //設置pNewSocketOnClose函數。

當程序中有多個處于listensocket時,你需要給每個socket準備一個OnAccept函數

 

       5)在主程序中做初始化工作:

/* init. the order is not important */

       NetIfInit();     //初始化網絡接口

       ARPInit();      //初始化ARP

       TCPInit();      //初始化TCP

       MemInit();      //初始化內存模塊

       RTLInit(EtherAddr);      //初始化RTL8019ASEtherAddr為以太網地址

 

       /* init Devcie struct and init this device */

/* 初始化一個以太網接口設備,并設置這個設備的發送和接收驅動函數。如果你的系統中以太網接口芯片的驅動不一樣,只要替換這里的發送和接口驅動函數就可以了*/

       EtherDevInit(&DevRTL,EtherAddr,RTLSendPacket,RTLReceivePacket);

 

       /* add this device to NetIf */

/* 添加一個網絡接口設備。參數含義是:該設備的IP地址、子網掩碼、網關、輸入函數指針、輸出函數指針、該設備的指針。如果你的系統中有多個網絡設備,比如moden,可以編寫moden的輸入輸出函數,使用NetIfAdd函數添加這個設備。*/

       NetIfAdd(IPAddr,NetMask,GateWay,EtherInput,EtherOutput,&DevRTL);

 

       6)啟動25ms的定時中斷

 

       7)使用類似

ExConn = TCPSocket(IPAddr);

       語句分配一個socket,并且綁定這個socket的源IP地址。

 

       8)

如果我方作為服務器方,監聽某一端口則:

                            TCPListen(ExConn,Port1,OnAccept1);

當另一方向我方Port1端口進行連接時,系統自動調用OnAccpet1函數。

       如果我方作為客戶端,向另一方的某個端口進行連接則:

TCPConnect(ExConn,IPAddr2,Port2,OnReceive2,OnClose2);

即向IP地址為IPAddr2的服務器的Port2端口進行連接。在連接成功以后,如果接收到另一方的數據則自動調用OnReceive1函數,如果接收到另一方的關閉請求則自動調用OnClose1函數。

 

       9)當某個socket處于連接狀態時,可以使用TCPSend或者TCPSendEx函數發送數據。

 

       10)需要關閉連接的時候,使用TCPClose關閉連接。

 

       11)當一個socket不再需要時,使用TCPAbort將這個socket還給系統。

5 移植相關修改

5.1 RTL8019AS的基地址

修改Netif\RTL8019.h中的

#define RTL_BASE_ADDRESS 0xb000

默認的基地址為0xb000。當單片機訪問0xb000開始的地址的時候,CSRTL信號線應給低電平,以選通RTL8019AS

5.2 TCP緩沖區大小設置

修改TCIPIP\TCPIPmem.h中的

#define TCPIP_BUF_SIZE    0x2000

默認為8K,建議大于4K。緩沖區過小,將會影響發送和接收速度。

5.3 多網絡設備

如果你的系統中有多個網絡設備。修改TCPIP\NetIf.h中的

#define NET_IF_MAX_NUM       1

默認情況下為最多一個設備。

在主程序中使用NetIfAdd函數添加網絡設備。

5.4 TCP連接數的設置

修改TCPIP\TCP.h中的

#define TCP_CONNECTION_MAX_NUM         10

默認情況下最多支持10socket同時工作。

5.5 網絡接口層協議的最大幀頭長度

只有當你的程序使用以太網以外的網絡接口協議時,才需要修改。修改TCPIP\NetIf.h中的

#define NETIF_HEAD_MAX_LEN      14

默認是以太網幀頭長度,即14個字節。

5.6 ARP表的大小設置

修改Netif\ARP.h中的

#define ARP_ENTRY_MAX_NUM              4

默認情況下ARP表大小為4個記錄。當ARP表已經滿的時候,新的記錄將會覆蓋最老的那個記錄。

5.7響應ping命令

如果不希望系統能夠響應ping命令,則修改TCPIP\icmp.h中的

#define ICMP_EN  1

默認情況下該開關是打開的。如果不需要此功能將其設置為0

5.8 到其它CPU的移植

zlIP雖然為51單片機設計,但是也可以被移植到其它的CPU上。系統中的GloblDef\GlobleDef.h記錄了CPU的信息,主要修改這個文件。

1)      設置BYTE,WORD,DWORD,BOOL等類型的定義

2)      注釋掉#define MCU_C51這一行。注釋掉這個選項開關以后將程序從C51變為ANSIC,程序中將沒有C51特有的關鍵字。

3)      字節順序設置。即設置多字節變量的高字節存在于低地址還是高地址。51單片機的字節順序和0x8086CPU不一樣。刪除#   define HOST_ORDER_AS_NET,如果字節順序和網絡字節順序不一樣。

4)      是否移植到具有多線程的51單片機程序中。比如單片上運行了RTOS51uc/OS-IITiny51等單片上的多線程操作系統,則需要打開#   define MULTI_THREAD開關,此時程序中幾乎所有的函數都聲明為reentrant類型的。

5)      如果需要運行在調試狀態打開#   define DEBUG開關。

6)      對于IORAM不是統一編址的系統需要修改RTL8019.c文件中的#define ReadReg(port) (*((BYTE DT_XDATA *)port))#define WriteReg(port,value) (*((BYTE DT_XDATA *)port) = value),使程序能夠訪問IO端口。

6 后記

       公布此源代碼,旨在將我的心得和成果和大家共享,共同學習和進步。由于本人水平有限,錯誤和疏漏之處難免,還請各位同行指正。

參考文獻

[1] 李章林,張立民. TCP/IP在51單片上的實現特點和方法. “2003年全國單片機和嵌入式系統年會”論文集.2003年

[2] (電子文獻)Adam Dunkels.uIP - A Free Small TCP/IP Stack[Z].  http://dunkels.com/adam/uip/index.html. 2002-1-15.1

[3] (電子文獻)Adam Dunkels.lwIP - News Archive[Z].http://www.sics.se/~adam/lwip/news.html.2001-1-9.

[4] 李章林,張立民. ANSIC程序到KeilC51的移植心得. “2003年全國單片機和嵌入式系統年會”論文集.2003年