引言 現在許多的系統都采用了多通道Input/Output的設計,控制系統的設計也日趨復雜、龐大,所以有必要將控制電路單獨分離出來(lái)。過(guò)去許多系統均采用C51系列單片機作為控制電路,但其功能有限,電路設計較為復雜、影響了系統的穩定性,也不易擴展。本文介紹的AVR單片機由美國ATMEL公司生產(chǎn),采用RISC指令集,內置RAM及可以擦寫(xiě)數千次的FLASH,采用哈佛結構,速度較快。ATmega128為此系列中功能最強大的一款,用于設計控制系統能適應現時(shí)復雜系統的要求。 AVR單片機介紹 ATMEL公司是世界上著(zhù)名的高性能低功耗非易失性存儲器和數字集成電路的一流半導體制造公司。AVR單片機由ATMEL公司開(kāi)發(fā),是過(guò)去12年里第一個(gè)新發(fā)布的8位RISCMCU,執行大多數指令只需一個(gè)時(shí)鐘周期速度快(8MHzAVR≈200MHzC51)。其32個(gè)通用寄存器直接與ALU相連,消除了運算瓶頸;同時(shí)由于C編譯專(zhuān)家的參與,C代碼效率極高;用戶(hù)在享受C語(yǔ)言帶來(lái)的極大便利的同時(shí)無(wú)需擔心消耗更多的資源。芯片內嵌可串行下載或自我編程的FLASH和E2PROM.具有以下功能:電壓檢測BOD復位源寄存器看門(mén)狗、PWM、10位A/D、模擬比較器、UART、I2C、SPI、實(shí)時(shí)時(shí)鐘等。具有Idle/Power-Save和Power-Down等低功耗運行模式,可電平中斷喚醒PowerDown.同時(shí)具有完整產(chǎn)品線(xiàn),FLASH從1KB到128KB,E2PROM從64B到4KB,SRAM從128B到4KB,引腳數從8到64. 其中Atmeg128為AVR系列中的代表性產(chǎn)品之一。相比其它產(chǎn)品,該芯片有以下特性: (1)先進(jìn)的RISC結構:133條功能強大的指令,大部分在單時(shí)鐘周期內完成,32×8個(gè)通用工作寄存器+外設控制寄存器,最高可工作在16MHz下,性能可達16MIPS;片內帶有執行時(shí)間為2個(gè)時(shí)鐘周期的硬件乘法器。 (2)程序和數據存儲區:128kB在線(xiàn)可編程Flash存儲器,可反復擦寫(xiě)1000次;可通過(guò)獨立的加密位選擇引導程序代碼段,可通過(guò)片內引導程序實(shí)現在線(xiàn)系統編程,寫(xiě)操作時(shí)真正可讀;4kB的EEPROM存儲區,可反復擦寫(xiě)100,000次。4kB的片內SRAM存儲區,可外部擴展為64kB. 系統硬件設計框架 硬件系統主要由CPU(AVR單片機)、人機操作和顯示接口(液晶顯示、鍵盤(pán)、指示燈和蜂鳴器)、通信接口組成。系統框圖如圖1所示 圖1系統硬件設計框圖 CPU為核心處理器件,通過(guò)I/O接口方式或A/D總線(xiàn)方式與液晶、顯示鍵盤(pán)、指示燈和蜂鳴器交互,作者實(shí)現了兩個(gè)版本,分別采用I/O方式和A/D總線(xiàn)方式。通信接口主要用到了UART接口和擴展的網(wǎng)絡(luò )接口。其中UART提供了RS-232和RS-485接口,RS-232提供全雙工單對單通信同時(shí),而RS-485以主/從方式與系統的多個(gè)部分通信,可用于多通道的輸入輸出設備。該芯片本身并不帶網(wǎng)絡(luò )接口,通過(guò)擴展一個(gè)W3100A連接RT-L8201(L)芯片,實(shí)現TCP/IP協(xié)議棧,從而使設備可以接入LAN,實(shí)現在LAN內的遠程控制管理和監控。 系統軟件結構 系統軟件體系分為幾個(gè)部分: (1)系統的循環(huán)檢測部分,用于檢測各通道的系統設備工作是否正常,出現異常時(shí)則通過(guò)三色指示燈報警(綠色代表正常,紅色代表異常,黃色為中間狀態(tài))。 (2)系統的設置部分,接受用戶(hù)按鍵,用戶(hù)可以在GUI上設置希望設置的參數。 (3)網(wǎng)絡(luò )接口部分,此時(shí)單片機系統不參與設置,主要功能將網(wǎng)絡(luò )部分獲得的數據導至各通道。軟件系統的核心部分在于菜單結構的設計。 本系統采用一種基于節點(diǎn)編號的三叉樹(shù)狀菜單的設計。將整個(gè)菜單看作一個(gè)菜單樹(shù),每個(gè)界面對應于樹(shù)中的一個(gè)節點(diǎn),父節點(diǎn)為當前菜單的上一級菜單;右節點(diǎn)為當前菜單的“兄弟”菜單,亦即上級菜單的其余子菜單。 我們采用對節點(diǎn)編號的方式將整個(gè)菜單樹(shù)串起來(lái),通過(guò)識別節點(diǎn)編號(ID)就能知道該節點(diǎn)處于哪一級菜單,同時(shí)也便于我們將菜單數初始化。編號方式:每級子菜單的編號為上級父菜單ID乘以10再加上該級子菜單在上級菜單中對應的子項號(1,2,3.),我們將根節點(diǎn)ID編號為1,則根節點(diǎn)菜單的子菜單對應的ID分別為11,12,13.ID為11的節點(diǎn)的下級菜單ID為:111,112,113.一個(gè)樹(shù)型結構菜單的結構和ID編號的實(shí)例如圖2所示。 Typedef structmenu{ long ID; / /當前菜單ID void ( * disp laymenu) ( long i, unsigned char j) ; / /當前菜單對應處理函數char cur; / /當前菜單子項char total; / /子菜單總數structmenu * up, * down, * right; / /毗鄰子菜單}MENU; 圖2一個(gè)菜單樹(shù)的實(shí)例 對于用戶(hù)按鍵操作切換不同的菜單時(shí),我們只需修改一個(gè)指向對應菜單節點(diǎn)的全局菜單節點(diǎn)指針即可。當用戶(hù)按下“ESC”鍵時(shí),菜單指針指向當前節點(diǎn)的父節點(diǎn),按下“Enter”鍵時(shí),則指針指向對應節點(diǎn)的子節點(diǎn)。 用于A(yíng)VR單片機的RAM空間較小,只有4KB,我們需設計一種合理而簡(jiǎn)潔的數據結構,我們將菜單的數據結構定義為(C語(yǔ)言實(shí)現)。 圖3 menuselect函數的流程圖 將菜單分為顯示型菜單和功能性菜單,顯示型菜單項用于切換各級菜單,功能型菜單則執行最底層菜單所對應的操作,total變量為0則表示為功能型菜單,大于0則表示選擇型菜單。通過(guò)菜單的ID,即可以知道當前菜單的顯示位置和內容,將此信息放在對應的displaymenu函數中可以節省數據空間,不用對于功能型菜單建立額外的ID與處理函數間的對應關(guān)系表,從而實(shí)現功能型菜單和顯示型菜單的一致性操作。一個(gè)供參考的執行函數可以寫(xiě)作: if(g_pmenu->total>0) { g_pmenu=menuselect(g_pmenu,Key);} else {(g_pmenu->displaymenu)(g_pmenu->ID,g_pmenu->cur);} 其中menuselect函數用于切換對應的菜單子項,按鍵為“UP”鍵和“DOWN”鍵時(shí),只需修改g_pmune->cur即可;按下“ENTER”鍵時(shí),則g_pmenu=g_pmenu->down,再根據cur值,g_pmenu=g_pmenu->right;按下“ESC”鍵,則g_pmenu=g_pmenu->up. 這種設計使得代碼數據量變得較小,同時(shí)增強了程序的擴展性,需要增加或修改菜單項時(shí),不論是功能型菜單還是執行性菜單,只需要修改對應的菜單結構的數組即可,而不必修改對應的執行代碼。經(jīng)過(guò)這樣的簡(jiǎn)化后,發(fā)現對于菜單數較多的多通道輸入/輸出系統,系統RAM區還是不夠用。對于一個(gè)8輸入通道的系統,每個(gè)通道的參數設置項可能多達40項,總菜單節點(diǎn)大于300個(gè),每個(gè)節點(diǎn)占用14B,則整個(gè)菜單節點(diǎn)所占的RAM已超過(guò)4K,所以這種方式還是需要進(jìn)一步改進(jìn)。 注意到多通道的參數設置項完全相同,ID為111,112,。,118的菜單分支完全一樣,ID為121和122的菜單分支也完全相同?梢远x一種Sibling菜單,從而刪去ID為112~118以及ID為122的菜單節點(diǎn)和子節點(diǎn)(虛線(xiàn)框所示),其上級菜單(ID為11和ID為12)的項目中的total值均變?yōu)?.為了區別不同的通道分支,有兩種實(shí)現辦法: 一種處理方法采用全局變量 增加一個(gè)g_CODER_Channel_Number的全局變量,用于保存當前的通道號。在menuselect函數中,增加一個(gè)針對本系統設計的一個(gè)判斷,當ID為11時(shí),則不修改對應的g_pmenu->cur,而是直接修改變量g_CODER_Channel_Number,進(jìn)入對應的顯示函數后,直接根據g_CODER_Channel_Number判斷通道號,從而輸出對應的值。這種方法不需要改變系統設計的結構,但需要針對不同的系統修改主處理函數menuselect. 另一種處理方法在菜單結構中增加一個(gè)MenuSibling結構,定義為 typedef struct _menuSibling{ signedcharcur;signedchartotal;}SIBLING;同時(shí)對應的菜單結構修改為typedefstructmenu{…… SIBLINGSibling;}MENU; 這樣,ID為11的結構項的Sibling.total為8,Sibling.cur為當前的子菜單項。判斷到total>0且Sibling.total>0時(shí),可知其下一級菜單為SIB2LING菜單,此時(shí)以前需修改cur想的操作則修改Sibling.cur即可。這種設計下,每個(gè)節點(diǎn)增加了2B的空間,但是保證的程序的一致性,對于不同的系統其設計基本一致。 以上菜單項的設計用于系統設置部分,當退出系統設置時(shí),即進(jìn)入系統循環(huán)檢測部分。單片機通過(guò)RS-485接口檢測各個(gè)通道是否正常,當正常時(shí)則顯示為綠燈,出現異常則顯示為紅燈,黃燈為中間狀態(tài)。指示燈的流程參見(jiàn)圖4. 圖4循環(huán)檢測的指示燈流程 結束語(yǔ) 按照本文提供的方法優(yōu)化后的設計,可以滿(mǎn)足大多數的多通道輸入/輸出系統的控制系統的需要,整個(gè)系統的設計主要在于建立一個(gè)菜單樹(shù),將對應的節點(diǎn)編號,再編寫(xiě)對應的節點(diǎn)處理函數即可。這種設計使得程序的開(kāi)發(fā)、維護都很容易,具有較強的可擴展性和可移植性。 |