<ul id="o4jpt"></ul>
  • ZLIP使用簡(jiǎn)介

    李章林1

    1 南開(kāi)大學(xué)電子應(yīng)用實(shí)驗(yàn)室,http://m.wyjjpt.com,版本:2005-11-28)

    1 目錄結(jié)構(gòu)

    TCP/IP協(xié)議棧程序所在目錄。

    Icmp協(xié)議。

    IP層。

    :網(wǎng)絡(luò)接口層。

    TCP協(xié)議層。

    TCPIP內(nèi)存管理程序。

     

     

     

     

     

     

     

     

    :網(wǎng)絡(luò)接口協(xié)議所在目錄。

    ARP協(xié)議。

    :以太網(wǎng)接口協(xié)議。

    RTL8019AS以太網(wǎng)接口芯片驅(qū)動(dòng)程序。

     

     

     

     

     

     

    :全局函數(shù)和宏定義所在目錄

     

     

     

     

    :應(yīng)用層協(xié)議所在目錄

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

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

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

    2 概述

    單片機(jī)上網(wǎng)技術(shù),是當(dāng)前的一個(gè)熱門技術(shù)。單片機(jī)上網(wǎng)技術(shù)中的一個(gè)重要部分是在單片上實(shí)現(xiàn)TCP/IP協(xié)議棧�,F(xiàn)在可獲得的TCP/IP源代碼一般并不為51單片機(jī)設(shè)計(jì),而51單片機(jī)和KeilC51編譯器有其自身的特點(diǎn):存儲(chǔ)類型、函數(shù)指針、重入函數(shù)等,ZLIP就是針對(duì)這些特點(diǎn)設(shè)計(jì)的TCP/IP協(xié)議棧。

    ZLIP設(shè)計(jì)的目標(biāo)是:

    1)              精簡(jiǎn)TCP/IP協(xié)議棧,以減小代碼量。ZLIP目前沒(méi)有支持UDP協(xié)議,ICMP協(xié)議也只支持其中的echo協(xié)議(響應(yīng)ping數(shù)據(jù)包)。lwIP是一個(gè)功能全面的TCP/IP協(xié)議棧,但是相對(duì)51來(lái)說(shuō)代碼量較大。

    2)             應(yīng)用層接口簡(jiǎn)單,以兼容通用的socket接口。uIP有很小的代碼量和減小代碼量(選擇AVR為目標(biāo)器件時(shí),代碼為5K左右)和RAM使用量(100字節(jié)左右)。uIP采用了不保存需要應(yīng)答的數(shù)據(jù)包的RAM使用方案,沒(méi)有和BSD的套接字接口兼容,應(yīng)用層接口較復(fù)雜。

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

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

    1:技術(shù)參數(shù)

    代碼量(字節(jié))

    外部RAM使用量(字節(jié))

    發(fā)送速度(字節(jié)/秒)

    14841

    11068

    5.892K

    ZLIP的特點(diǎn)如下:

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

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

    3)支持多TCP連接、多網(wǎng)絡(luò)設(shè)備。能方便地移植到多任務(wù)操作系統(tǒng)和其它CPU下。能方便地替換網(wǎng)絡(luò)接口協(xié)議和網(wǎng)卡驅(qū)動(dòng)設(shè)備。

    4)支持ping命令的響應(yīng)。

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

    3電路圖

    1RTL8019AS電路左半部分

    2RTL8019AS電路右半部分

    該程序不能在KeilC下軟件仿真,因?yàn)槌绦虻倪\(yùn)行需要外部電路配合。該51系統(tǒng)的外部電路主要有:以太網(wǎng)接口芯片RTL8019AS電路、外部RAM電路。

           以太網(wǎng)接口芯片RTL8019AS電路圖,如圖1和圖2表示。A0A4接地址線,D0D7接數(shù)據(jù)線,CSRTL是片選線(低電平有效),RD-WR-接讀寫(xiě)信號(hào)線。

    4 應(yīng)用層接口

    zlIP接口函數(shù)基本和BSD的套接字接口相同。

    41提供的用戶接口函數(shù):

    TCPSocket()。

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

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

     

    TCPConnect()。

    函數(shù)原型: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的服務(wù)器的DestPort端口發(fā)起連接。參數(shù)recvclose用于設(shè)置當(dāng)接收到數(shù)據(jù)包和對(duì)方要求關(guān)閉TCP連接時(shí)應(yīng)該調(diào)用的回調(diào)函數(shù)指針。連接成功返回TRUE,否則返回FALSE。

     

    TCPSend()

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

    功能:發(fā)送數(shù)據(jù)。發(fā)送數(shù)據(jù)的TCP連接是套接字指針pTCB對(duì)應(yīng)的連接,發(fā)送的數(shù)據(jù)的起始地址為buf,大小為DataSize。發(fā)送成功返回TRUE,否則返回FALSE。

     

    TCPSendEx()

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

    功能:快速發(fā)送數(shù)據(jù)。在使用TCPSend函數(shù)時(shí),你首先需要將數(shù)據(jù)放入buf指向的內(nèi)存中,然后調(diào)用TCPSend函數(shù),接著該函數(shù)會(huì)將buf指向的內(nèi)存區(qū)數(shù)據(jù)拷貝到TCP緩沖區(qū)中。使用TCPSendEx 時(shí)你首先用TCPAllocate(DATA_SIZE)獲得一個(gè)TCP緩沖區(qū),然后直接將數(shù)據(jù)放入TCP緩沖區(qū)中,從而比TCPSend函數(shù)少一次數(shù)據(jù)拷貝,提高發(fā)送速度。

    參數(shù):發(fā)送數(shù)據(jù)的TCP連接是套接字指針pTCB對(duì)應(yīng)的連接,發(fā)送的數(shù)據(jù)放在TCP緩存MemHead中。發(fā)送成功返回TRUE,否則返回FALSE。

     

    TCPListen()

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

    功能:使用套接字pTCBScrPort端口監(jiān)聽(tīng)。參數(shù)accept是當(dāng)有客戶端向這個(gè)監(jiān)聽(tīng)端口連接成功時(shí)調(diào)用的回調(diào)函數(shù)指針。

     

    TCPClose()。

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

    功能:我方主動(dòng)關(guān)閉連接時(shí)調(diào)用TCPClose函數(shù),它將要求關(guān)閉套接字pTCB對(duì)應(yīng)的連接。TCPClose返回以后這個(gè)TCP連接可能保持,因?yàn)榱硪环竭沒(méi)有發(fā)起關(guān)閉請(qǐng)求。

     

    TCPAbort()。

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

    功能:當(dāng)使用完這個(gè)套接字以后,調(diào)用TCPAbort,將這個(gè)套接字釋放,還給系統(tǒng)。

    42使用步驟

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

    1)首先設(shè)置一個(gè)25ms的定時(shí)中斷函數(shù)(示例程序?yàn)?/span>Timer函數(shù))。請(qǐng)?jiān)谥袛嗪瘮?shù)中調(diào)用NetIfTimer(); ARPTimer(); TCPTimer();三個(gè)函數(shù)。

     

           2)寫(xiě)OnReceive函數(shù),它應(yīng)該有如下的參數(shù)和返回值,函數(shù)名可以任意:

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

    在使用TCPConnect函數(shù)時(shí),OnReceive1將作為TCPConnect函數(shù)的一個(gè)參數(shù),也就是設(shè)置該socket的接收函數(shù)。當(dāng)TCP連接接收到對(duì)方數(shù)據(jù)時(shí),將自動(dòng)調(diào)用OnReceive1函數(shù)。buf指向接收的數(shù)據(jù),size是接收的數(shù)據(jù)量的大小。你可以在OnReceive1中處理接收的數(shù)據(jù)。當(dāng)程序中有多個(gè)TCP連接同時(shí)存在時(shí),你需要給每個(gè)連接準(zhǔn)備一個(gè)OnReceive函數(shù)。

     

           3)寫(xiě)OnClose函數(shù),它應(yīng)該有如下的參數(shù)和返回值,函數(shù)名可以任意:

    void OnClose1(socket DT_XDATA * pSocket) REENTRANT_MUL

    類似于OnReceive函數(shù),當(dāng)TCP連接的另一方首先向我方發(fā)起關(guān)閉連接的請(qǐng)求時(shí),系統(tǒng)將自動(dòng)調(diào)用OnClose函數(shù)。pSocket指向?qū)⒁P(guān)閉的socket。如果你想立即關(guān)閉這個(gè)連接則在OnClose函數(shù)中調(diào)用TCPClose函數(shù)。當(dāng)程序中有多個(gè)TCP連接同時(shí)存在時(shí),你需要給每個(gè)連接準(zhǔn)備一個(gè)OnClose函數(shù)。

     

    4)寫(xiě)OnAccept函數(shù)。如果你的程序中用到TCPListen函數(shù)監(jiān)聽(tīng)某端口,這時(shí)需要寫(xiě)OnAccept函數(shù)。它應(yīng)該有如下的參數(shù)和返回值,函數(shù)名可以任意:

    void OnAccept1(socket DT_XDATA *pNewSocket) REENTRANT_MUL

    當(dāng)一個(gè)正在listensocket接受了對(duì)方的連接以后將會(huì)自動(dòng)調(diào)用該函數(shù)。pNewSocket是將要獲得這個(gè)連接的控制權(quán)的socket指針。一般在OnAccept函數(shù)中做以下處理:

           ExAccept = pNewSocket;            //保存pNewSocket,以后可以用ExAccept發(fā)送數(shù)據(jù)

           pNewSocket->recv = OnAcceptRecv;  //設(shè)置pNewSocketOnReceive函數(shù)。

           pNewSocket->close = OnClose;          //設(shè)置pNewSocketOnClose函數(shù)。

    當(dāng)程序中有多個(gè)處于listensocket時(shí),你需要給每個(gè)socket準(zhǔn)備一個(gè)OnAccept函數(shù)

     

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

    /* init. the order is not important */

           NetIfInit();     //初始化網(wǎng)絡(luò)接口

           ARPInit();      //初始化ARP

           TCPInit();      //初始化TCP

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

           RTLInit(EtherAddr);      //初始化RTL8019AS,EtherAddr為以太網(wǎng)地址

     

           /* init Devcie struct and init this device */

    /* 初始化一個(gè)以太網(wǎng)接口設(shè)備,并設(shè)置這個(gè)設(shè)備的發(fā)送和接收驅(qū)動(dòng)函數(shù)。如果你的系統(tǒng)中以太網(wǎng)接口芯片的驅(qū)動(dòng)不一樣,只要替換這里的發(fā)送和接口驅(qū)動(dòng)函數(shù)就可以了*/

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

     

           /* add this device to NetIf */

    /* 添加一個(gè)網(wǎng)絡(luò)接口設(shè)備。參數(shù)含義是:該設(shè)備的IP地址、子網(wǎng)掩碼、網(wǎng)關(guān)、輸入函數(shù)指針、輸出函數(shù)指針、該設(shè)備的指針。如果你的系統(tǒng)中有多個(gè)網(wǎng)絡(luò)設(shè)備,比如moden,可以編寫(xiě)moden的輸入輸出函數(shù),使用NetIfAdd函數(shù)添加這個(gè)設(shè)備。*/

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

     

           6)啟動(dòng)25ms的定時(shí)中斷

     

           7)使用類似

    ExConn = TCPSocket(IPAddr);

           語(yǔ)句分配一個(gè)socket,并且綁定這個(gè)socket的源IP地址。

     

           8)

    如果我方作為服務(wù)器方,監(jiān)聽(tīng)某一端口則:

                                TCPListen(ExConn,Port1,OnAccept1);

    當(dāng)另一方向我方Port1端口進(jìn)行連接時(shí),系統(tǒng)自動(dòng)調(diào)用OnAccpet1函數(shù)。

           如果我方作為客戶端,向另一方的某個(gè)端口進(jìn)行連接則:

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

    即向IP地址為IPAddr2的服務(wù)器的Port2端口進(jìn)行連接。在連接成功以后,如果接收到另一方的數(shù)據(jù)則自動(dòng)調(diào)用OnReceive1函數(shù),如果接收到另一方的關(guān)閉請(qǐng)求則自動(dòng)調(diào)用OnClose1函數(shù)。

     

           9)當(dāng)某個(gè)socket處于連接狀態(tài)時(shí),可以使用TCPSend或者TCPSendEx函數(shù)發(fā)送數(shù)據(jù)。

     

           10)需要關(guān)閉連接的時(shí)候,使用TCPClose關(guān)閉連接。

     

           11)當(dāng)一個(gè)socket不再需要時(shí),使用TCPAbort將這個(gè)socket還給系統(tǒng)。

    5 移植相關(guān)修改

    5.1 RTL8019AS的基地址

    修改Netif\RTL8019.h中的

    #define RTL_BASE_ADDRESS 0xb000

    默認(rèn)的基地址為0xb000。當(dāng)單片機(jī)訪問(wèn)0xb000開(kāi)始的地址的時(shí)候,CSRTL信號(hào)線應(yīng)給低電平,以選通RTL8019AS。

    5.2 TCP緩沖區(qū)大小設(shè)置

    修改TCIPIP\TCPIPmem.h中的

    #define TCPIP_BUF_SIZE    0x2000

    默認(rèn)為8K,建議大于4K。緩沖區(qū)過(guò)小,將會(huì)影響發(fā)送和接收速度。

    5.3 多網(wǎng)絡(luò)設(shè)備

    如果你的系統(tǒng)中有多個(gè)網(wǎng)絡(luò)設(shè)備。修改TCPIP\NetIf.h中的

    #define NET_IF_MAX_NUM       1

    默認(rèn)情況下為最多一個(gè)設(shè)備。

    在主程序中使用NetIfAdd函數(shù)添加網(wǎng)絡(luò)設(shè)備。

    5.4 TCP連接數(shù)的設(shè)置

    修改TCPIP\TCP.h中的

    #define TCP_CONNECTION_MAX_NUM         10

    默認(rèn)情況下最多支持10個(gè)socket同時(shí)工作。

    5.5 網(wǎng)絡(luò)接口層協(xié)議的最大幀頭長(zhǎng)度

    只有當(dāng)你的程序使用以太網(wǎng)以外的網(wǎng)絡(luò)接口協(xié)議時(shí),才需要修改。修改TCPIP\NetIf.h中的

    #define NETIF_HEAD_MAX_LEN      14

    默認(rèn)是以太網(wǎng)幀頭長(zhǎng)度,即14個(gè)字節(jié)。

    5.6 ARP表的大小設(shè)置

    修改Netif\ARP.h中的

    #define ARP_ENTRY_MAX_NUM              4

    默認(rèn)情況下ARP表大小為4個(gè)記錄。當(dāng)ARP表已經(jīng)滿的時(shí)候,新的記錄將會(huì)覆蓋最老的那個(gè)記錄。

    5.7響應(yīng)ping命令

    如果不希望系統(tǒng)能夠響應(yīng)ping命令,則修改TCPIP\icmp.h中的

    #define ICMP_EN  1

    默認(rèn)情況下該開(kāi)關(guān)是打開(kāi)的。如果不需要此功能將其設(shè)置為0

    5.8 到其它CPU的移植

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

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

    2)      注釋掉#define MCU_C51這一行。注釋掉這個(gè)選項(xiàng)開(kāi)關(guān)以后將程序從C51變?yōu)?/span>ANSIC,程序中將沒(méi)有C51特有的關(guān)鍵字。

    3)      字節(jié)順序設(shè)置。即設(shè)置多字節(jié)變量的高字節(jié)存在于低地址還是高地址。51單片機(jī)的字節(jié)順序和0x8086CPU不一樣。刪除#   define HOST_ORDER_AS_NET,如果字節(jié)順序和網(wǎng)絡(luò)字節(jié)順序不一樣。

    4)      是否移植到具有多線程的51單片機(jī)程序中。比如單片上運(yùn)行了RTOS51、uc/OS-IITiny51等單片上的多線程操作系統(tǒng),則需要打開(kāi)#   define MULTI_THREAD開(kāi)關(guān),此時(shí)程序中幾乎所有的函數(shù)都聲明為reentrant類型的。

    5)      如果需要運(yùn)行在調(diào)試狀態(tài)打開(kāi)#   define DEBUG開(kāi)關(guān)。

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

    6 后記

           公布此源代碼,旨在將我的心得和成果和大家共享,共同學(xué)習(xí)和進(jìn)步。由于本人水平有限,錯(cuò)誤和疏漏之處難免,還請(qǐng)各位同行指正。

    參考文獻(xiàn)

    [1] 李章林,張立民. TCP/IP在51單片上的實(shí)現(xiàn)特點(diǎn)和方法. “2003年全國(guó)單片機(jī)和嵌入式系統(tǒng)年會(huì)”論文集.2003年

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

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

    [4] 李章林,張立民. ANSIC程序到KeilC51的移植心得. “2003年全國(guó)單片機(jī)和嵌入式系統(tǒng)年會(huì)”論文集.2003年

     

     

    <ul id="o4jpt"></ul>
  • 丁香婷婷色五月激情综合 | a v 视频在线观看 | 精品无码系列 | avav手机在线 | 亚洲免费日本精品在线观看 | 欧美性猛交久久久久 | 大香蕉伊人操逼网 | 亚洲AV无码成人精品毛片 | 四虎永久www成人影院 | 先锋影音Vs男人资源站 |