久久ER99热精品一区二区-久久精品99国产精品日本-久久精品免费一区二区三区-久久综合九色综合欧美狠狠

新聞中心

EEPW首頁 > 嵌入式系統 > 設計應用 > 基于ARM的W5100底層驅動設計

基于ARM的W5100底層驅動設計

作者: 時間:2016-11-19 來源:網絡 收藏
引言

嵌入式操作系統的引入大大提高了嵌入式系統的功能,方便了嵌入式應用軟件的設計,但同時也占用了寶貴的嵌入式資源。

本文引用地址:http://cqxgywz.com/article/201611/318470.htm

嵌入式操作系統大多采用組件化、模塊化的設計思想,以搭積木的方式通過互連構造軟件,因而是可配置的。但是由于操作系統的多樣性,不同操作系統提供的配置方式迥異且繁簡不一。而由于硬件平臺的多樣性,即使是相同的操作系統,其應用配置也有差別。結果是,應用程序開發者必須熟悉不同的硬件平臺和操作系統才能進行有效的應用開發,增加了應用開發的難度。特別是網絡化嵌入式應用一般出現在比較大型的項目中,復雜度和難度大大增加。因此,提高網絡化嵌入式應用產品質量、縮短開發周期、降低開發成本是開發人員面臨的迫切要求。

1 開發模式方案選擇

面向對象的方法、設計模式的思想是當前實現軟件模塊化、提高軟件可復用性的最優方法。面向對象編程語言、組件和構架是被廣泛認可的、用以降低軟件成本并提高軟件質量的技術。

面向對象的主要好處在于它強調模塊性和可擴展性,將易變的實現細節封裝在穩定的接口后面,增強了軟件的可復用性。但是,在目前的嵌入式實時系統中采用面向對象的方法進行上層軟件的設計還有很多困難。最主要的,就是底層實時操作系統沒有提供有力支持,即使上層軟件勉強采用了面向對象的方法,代碼的模塊化、可移植性、可復用性也難有提高。

因此,為了避免采用傳統操作系統的開發模式帶來復雜問題,本文采用一種自定義的裸機開發模式。該模式避免了不同操作系統平臺改變帶來復雜的問題。其創建項目過程沒有復雜的裁剪,只有根據需要添加相關驅動和編寫適當應用層代碼。即使是硬件平臺的改變,也只是根據硬件配置不同改變其條件編譯而已。

2 自定義裸機開發模式

自定義開發模式下的應用軟件體系結構如圖1所示。該體系結構包含管理層、應用層、控件層、虛設備層和實設備層。其中管理層處于類似于操作系統中“內核”的地位,為其他層的管理者。

圖1
自定義開發模式下的應用軟件體系結構
跟PC機上的Windows應用軟件類似,應用層是由一個或者多個窗口組成的,有可視窗口和不可視窗口。其中各個窗口中又包含一個或者多個控件。控件為窗口提供各種服務,由設備層提供支撐。在控件層和實設備層中間有一個虛設備層。
根據設備功能的復雜程度,虛設備分為簡單的虛設備和復合虛設備。實設備分為簡單的實設備和復合實設備。其中復合設備是由簡單設備組合而成。
從類的關系看,虛設備層就是含有虛函數的基類,該函數一般沒有實現,只是聲明了接口,實設備層就是從該基類繼承下來的,具體實現是由該實設備層來完成。由于接口的穩定性,這就保證了底層硬件改變時,應用層的程序幾乎可以沒有改變或者改變甚小。
3
自定義開發模式下的W5100驅動編寫
3.1
接口電路說明
本驅動設計采用W5100串行SPI接口。SPI接口模式只需要4個引腳進行數據通信,分別為SCLK、/SS(SPI從模式選擇輸入引腳,低電平有效)、MOSI、MISO。W5100
的SPI_EN 引腳高電平表示SPI
使能,/RESET引腳低電平實現W5100芯片的復位。本項目選擇的MCU芯片為LPC2138,其中W5100與LPC2138對應引腳連線如表1所列。
表1 LPC2138與W5100對應引腳連線說明

3.2 W5100驅動分析
本驅動開發環境為:CodeWarrior for ARM Developer Suite
V1.2。
在自定義開發模式中,前期編寫好的驅動類有引腳類、SPI類、外部中斷類,就是所謂簡單設備。這些類及其頭文件的具體介紹略——編者注。
在使用W5100前需要操作其/SS引腳,選中W5100芯片SPI從模式。初次配置或者重新配置W5100相關參數前,需要操作其/RESET引腳,讓所有原來配置復位。配置W5100相關參數是通過SPI讀寫操作來完成的。
W5100從網絡上接收了一個數據包后,會讓其/INT引腳從高電平變為低電平。在本項目中,把該引腳跟LPC2138的外部中斷1引腳相連,如果開啟了外部中斷1,那么就觸發一個外部中斷。該外部中斷服務里面應當有實現LPC2138訪問W5100,并讀取W5100里面接收到的數據包的功能。LPC2138獲取W5100里面的數據包,必須通過SPI讀寫操作的配合才能實現。
綜合上面的分析,該W5100驅動應當是由引腳類、外部中斷類、SPI操作類互相配合完成,因此W5100驅動是一個復合設備。
3.3
W5100實設備驅動編寫
本驅動針對W5100采用UDP協議進行網絡通信功能來編寫。

首先所有實設備都必須從一個虛設備下繼承下來。創建一個名為Ip_NetWork_Virtual_Device網絡虛設備,其部分頭文件略——編者注。
由于網絡通信應用的芯片有多種,但是無論是哪種芯片,實現的功能都離不開網絡包的讀和寫。因此在該虛類里的聲明都是共用的功能。基類里面含有虛函數,就是聲明了接口,但是沒有具體的實現,具體的實現由其具體的實設備來完成。在繼承中,如果基類和派生類中定義了同名的成員函數,當用基類指針指向公有派生類的對象后,可以使用虛函數來實現通過基類指針找到相應的派生類成員函數[11]。
W5100的實設備NetWork_W5100類的部分頭文件略——編者注。
3.4
W5100實設備驅動說明
3.4.1 虛設備類指針
在W5100實設備頭文件中有:
Spi_Virtual_Device*
SpiPort;
OutEint_Virtual_Device* IntDevice;
PinDevice_Virtual_Device *
W5100_Cs;
PinDevice_Virtual_Device *
W5100_RESET;
由于W5100實設備需要幾個簡單設備配合來完成其功能,因此設計W5100實設備驅動擁有這些簡單設備的指針,可以看出這些指針是指向簡單虛設備對象的指針。
聲明為指向基類對象的指針,當它指向公有派生類對象時,可以利用它來直接訪問派生類中從基類繼承下來的成員,不能直接訪問公有派生類中特定的成員。
采用面向對象中模式編程法則中的依賴反轉法則:依賴抽象而不依賴具體[12]。
在main.cpp首先聲明如下的實設備,如下:

OutInt_2138 NetOutInt; //外部中斷類實設備對象
NetWork_W5100
Net5100;//W5100實設備對象
Spi0_Driver_Lpc Spi0;//SPI實設備對象
Pin_LPC2138 PIN023;
//引腳實設備對象
Pin_LPC2138 PIN031;
//引腳實設備對象
接著在main.cpp采用如下代碼完成Net5100和簡單設備NetOutInt、Spi0、PIN023、PIN031等的關聯:
NetOutInt.WorkModel=Fall_Eage;//表示下降沿觸發
NetOutInt.SubDeviceName=Eint1;//表示使用外部中斷1
NetOutInt.Ini();
NetOutInt.Father=&Net5100;
Net5100.SpiPort=&Spi0;//設置Spi0和SpiPort指針關聯
Net5100.W5100_Cs=&
PIN023; //設置片選引腳關聯
Net5100.W5100_RESET=& PIN031;
//設置復位引腳關聯
在“Net5100.SpiPort=&Spi0”中SpiPort是指向某基類對象的指針,Spi0是該基類的派生類對象,該語句實現把該指針指向其派生類對象。因此就可以利用該指針直接訪問該公有派生類從基類繼承來的成員。同樣,可以利用W5100_Cs和W5100_RESET等基類對象指針直接訪問該基類的派生類——Pin_LPC2138類從基類繼承下來的成員,即引腳的操作函數等。
在NetWork_W5100中有W5100_Send_Receive_Data函數就是利用這個技術,該函數如下:
char
NetWork_W5100::W5100_Send_Receive_Data(char dat){
char
i;
W5100_Cs->Clear();
i=SpiPort->SPI_Send_Receive_Data(dat);
W5100_Cs->Set();
return
i;
}
NetWork_W5100類對象能實現SPI讀寫操作,是因為其擁有一個SPI虛設備的指針。同理,能實現對引腳操作是因為其擁有一個引腳虛設備的指針。
3.4.2
外部中斷實設備和W5100實設備關聯
NetOutInt是一個外部中斷類對象,使用前首先對該對象進行初始化,其中代碼“NetOutInt.SubDeviceName=Eint1”表示該類對象和外部中斷1產生了綁定。
在本項目測試中,W5100從網絡接收到一個數據包后觸發了一個外部中斷1中斷。該W5100實設備類對象Net5100感知該事件,從而對該事件進行處理,接著把該消息發布給其所支撐的控件。
main.cpp中有“NetOutInt.Father=&Net5100;”,其中Father是一個指針,該指針來源如下:
class
Object{
public:
……
Object
*Father;
……
};
由于所有設備類都是從該類間接繼承下來,所以都擁有這個Father指針。
“NetOutInt.Father=&Net5100;”的目的是把Net5100對象地址賦給該指針,因此該指針就指向Net5100,說明NetOutInt擁有一個指向Net5100的指針。main.cpp中,外部中斷1的服務程序代碼如下:
void
__irq
IRQ_Eint1(){
NetOutInt.HardInt(Null);
VICVectAddr=0×00;
NetOutInt.ClearInt();
}
“NetOutInt.HardInt(Null);”其本質就是調用到HardInt函數,如下:
void
OutInt_2138::HardInt(Device*
IntDevice){
……
this->Msg.MsgID=Sys_Msg_OutInt;
this->Msg.Parm1=this->SubDeviceName;
this->Father->Message(Msg);
……
}
“this->Father->Message(Msg);”即中斷服務最后把該工作交給Father指針指向的Net5100,接著該對象調用了其Message函數。NetWork_W5100類的Message函數偽代碼如下:
void
NetWork_W5100::Message(MessageBody SystemMsg){
if
Socket3
SelectSocket(3);
if Socket2
SelectSocket(2);
if
Socket1
SelectSocket(1);
else
SelectSocket(0);
};
其中NetWork_W5100類的SelectSocket函數如下:
void
NetWork_W5100::SelectSocket(char socket){
uint16
address,inttype;
address=COMMON_BASE+0×100*socket+0×0402;
inttype=NetWork_Read(address);

if((inttype&0×04)==0×04){
//接收數據引起中斷
S_UDP_RX_Process(socket,&ReceiveBuffer[0],&ReceiveBuffer[8]);
//從對應的Socket接收數據
Msg.MsgID=Sys_Msg_UdpGetData;
Msg.Msg=&ReceiveBuffer[0];
VclPointer[socket]->Message(Msg);
//向支撐控件發送消息
}
NetWork_Write(address,0xFF);//清除所有的中斷
}
可見,W5100驅動最后把網絡接收到數據包作為一個消息發給其所支撐的上層控件。
4
W5100驅動測試
4.1 測試方案
在PC機上,利用網絡測試工具TCP/UDP
Socke調試工具V2.2,通過網絡向W5100的終端發送一個數據包。當該終端接收到該數據包后,把該包往PC機終端發送。如果發送和接收的數據包一致,說明通信測試成功。
4.2
測試過程
PC機端的IP地址為192.168.1.103,某端口號為9000。W5100本身地址設置為192.168.1.101,某端口號為9000。PC機往W5100終端發送數據包,在如圖2所示操作界面的數據發送窗口輸入“Hello,
This is a happy word!”字符串后,點擊“發送數據”,在操作界面的數據接收窗口接收到“Hello, This is a happy
word!”,并且在操作界面上方顯示“對方IP:192.168.1.101,對方端口:9000”,這跟W5100終端設置是一致的,說明雙方的通信成功。

結語
W5100驅動的創建過程非常復雜,但是對于編寫好的驅動,應用者只需要了解該接口使用的說明,而不用關心其復雜的內部實現細節。如果其他項目需要用到W5100,只需要把該驅動添加到該項目中即可,從而實現驅動的復用,避免重復的工作,縮短項目開發周期。如果下次要使用W5100驅動的其他功能,如TCP協議通信,只需要在原來驅動上添加相應的函數即可,因此維護起來更加方便。



關鍵詞: ARM的W5100底層驅

評論


技術專區

關閉