第八章為深入理解AMetal,本文內(nèi)容為8.6 通用數(shù)碼管接口。
8.6 通用數(shù)碼管接口
>>> 8.6.1 定義接口
1. 接口命名
由于操作的對象是數(shù)碼管(digitron),因此接口命名以“am_digitron_”作為前綴。數(shù)碼管最常見的操作是設(shè)置數(shù)碼管的顯示內(nèi)容,提供一個顯示字符和字符串的接口,其對應(yīng)的接口名為:
-
am_digitron_disp_char_at
-
am_digitron_disp_str
當(dāng)顯示字符或字符串時,需要將各個字符解碼為對應(yīng)的段碼后,數(shù)碼管才能正常顯示。為此需要提供一個設(shè)置解碼函數(shù)的接口,便于用戶根據(jù)實際數(shù)碼管自定義解碼函數(shù),然后通過該接口設(shè)置到系統(tǒng)中。當(dāng)需要顯示一個字符時,系統(tǒng)首先會使用該解碼函數(shù)將字符解碼為段碼。其對應(yīng)的接口名為:
-
am_digitron_disp_decode_set
在一些應(yīng)用場合,可能需要顯示特殊的圖形,此時僅僅有顯示字符或字符串的接口是不夠的,還需要提供一個直接顯示段碼的接口,其對應(yīng)的接口名為:
-
am_digitron_disp_at
此外,作為一個顯示器,還需要清除當(dāng)前數(shù)碼管顯示的所有內(nèi)容,便于重新設(shè)置顯示內(nèi)容,其對應(yīng)的接口名為:
-
am_digitron_disp_clr
特別地,除設(shè)置顯示內(nèi)容相關(guān)的操作外,還需要數(shù)碼管閃爍顯示,其對應(yīng)的接口名為:
-
am_digitron_disp_blink_set
2. 接口參數(shù)
通常系統(tǒng)存在多個數(shù)碼管,比如,同時使用MiniPort-View 和MiniPort-ZLG72128。在一個數(shù)碼管設(shè)備中,又可能包含多個數(shù)碼管,比如,MiniPort-View 和MiniPort-ZLG72128均包含兩個數(shù)碼管。
為了區(qū)分不同的數(shù)碼管設(shè)備,需要為每個數(shù)碼管設(shè)備分配一個唯一ID,基于此,將所有接口的第一個參數(shù)設(shè)定為數(shù)碼管ID,用于指定需要操作的數(shù)碼管設(shè)備。
am_digitron_disp_char_at()接口用于顯示一個字符,雖然有數(shù)碼管設(shè)備ID 用于確定顯示該字符的數(shù)碼管設(shè)備,但僅僅通過數(shù)碼管設(shè)備ID 還不能確定在數(shù)碼管設(shè)備中顯示的具體位置,為此需要新增一個索引參數(shù),用于指定字符顯示的位置,索引的有效范圍為0 ~(數(shù)碼管個數(shù)–1),如MiniPort-View 有兩個數(shù)碼管,則索引的有效范圍為 0 ~ 1。此外,該接口還需要一個參數(shù)用以指定要顯示的字符。定義該接口的函數(shù)原型為(暫未定義返回值類型):
對于am_digitron_disp_str()接口,其用于顯示一個字符串,除數(shù)碼管設(shè)備ID 外,同樣需要一個索引參數(shù)以指定字符串顯示的起始位置,此外,還需要使用參數(shù)指定要顯示的字符串以及顯示字符串的長度。定義該接口的函數(shù)原型為(暫未定義返回值類型):
其中,len 指定顯示的長度,p_str 指定要顯示的字符串,實際顯示的長度為字符串長度和len 中的較小值。
對于am_digitron_disp_decode_set()接口,其用于設(shè)定字符的解碼函數(shù),顯然,一個數(shù)碼管設(shè)備中的多個數(shù)碼管往往是相同的,可以使用同樣的解碼規(guī)則,共用一個解碼函數(shù)。因而接口僅需使用ID 指定數(shù)碼管設(shè)備,無需使用index 指定具體的數(shù)碼管索引。解碼函數(shù)的作用是對字符進行解碼,輸入一個字符,輸出該字符對應(yīng)的編碼。基于此,定義該接口的函數(shù)原型為(暫未定義返回值類型):
其中,pfn_decode 是指向解碼函數(shù)的指針,表明了解碼函數(shù)的類型:具有一個16 位無符號類型的ch 參數(shù),返回值為16 位無符號類型的編碼。這里使用16 位的數(shù)據(jù)表示字符和編碼,是為了更好的擴展性。如除8 段數(shù)碼管外,還存在14 段的米字型數(shù)碼管、16 段數(shù)碼管等,這些情況下,8 位數(shù)據(jù)就無法表示完整的段碼了。
對于am_digitron_disp_at()接口,其用于直接設(shè)置顯示的段碼,和顯示一個字符類似,除數(shù)碼管設(shè)備ID 外,同樣需要使用參數(shù)指定顯示的位置以及要顯示的內(nèi)容(段碼),可定義該接口的原型為(暫未定義返回值類型):
對于am_digitron_disp_clr()接口,其用于清除一個數(shù)碼管設(shè)備顯示的所有內(nèi)容,僅需使用ID 指定需要清除的數(shù)碼管設(shè)備,無需其它額外參數(shù)。定義該接口的原型為(暫未定義返回值類型):
對于am_digitron_disp_blink_set()接口,其用于設(shè)置數(shù)碼管的閃爍屬性,除數(shù)碼管設(shè)備ID 外,還需要使用參數(shù)指定設(shè)置閃爍屬性的數(shù)碼管位置以及使用本次設(shè)置的閃爍屬性(打開閃爍還是關(guān)閉閃爍),定義該接口的原型為(暫未定義返回值類型):
其中,index 指定本次設(shè)置閃爍屬性的數(shù)碼管位置,blink 指定閃爍屬性,當(dāng)值為AM_TRUE 時,則打開閃爍;當(dāng)值為AM_FALSE 時,則關(guān)閉閃爍。
3. 返回值
接口無特殊說明,直接將所有接口的返回值定義為int 類型的標(biāo)準(zhǔn)錯誤號。數(shù)碼管接口的完整定義詳見表8.8。其對應(yīng)的類圖詳見圖8.16。
圖8.16 數(shù)碼管接口
表8.8 數(shù)碼管通用接口(am_digitron_disp.h)
>>> 8.6.2 實現(xiàn)接口
1. 抽象的數(shù)碼管設(shè)備類
類似地,應(yīng)該根據(jù)通用數(shù)碼管接口,定義相應(yīng)的抽象方法,以顯示字符函數(shù)為例,按照前面的通用做法,其抽象方法定義為:
相比于通用接口,其新增了一個用于指向設(shè)備自身的p_cookie 參數(shù)。在定義數(shù)碼管通用接口時,使用ID 唯一的代表了一個數(shù)碼管設(shè)備,可見,在這里,p_cookie 和id 均代指了某一確定的數(shù)碼管設(shè)備,由于抽象方法是由具體數(shù)碼管設(shè)備實現(xiàn)的,p_cookie 也用于指向設(shè)備自身,通過p_cookie 已經(jīng)能夠唯一的確定某一具體設(shè)備,因此,ID 參數(shù)在抽象方法中再無實際用處,將ID 參數(shù)從抽象方法中移除,即:
實際上,可以看作是參數(shù)由抽象意義的ID(僅是一個數(shù)字)變?yōu)榱司哂袑嶋H意義的p_cookie(指向設(shè)備自身的指針)。
基于此,根據(jù)其它通用數(shù)碼管通用接口,為它們一一定義相應(yīng)的抽象方法,并將其存放在一個虛函數(shù)表中,即:
讀者可能會發(fā)現(xiàn),在實現(xiàn)LED 接口時,定義的抽象方法同時包含了p_cookie 和led_id參數(shù)。即:
這是由于在通用LED 接口的設(shè)計中,ID 并非是對LED 設(shè)備進行的編號,而是對系統(tǒng)中所有LED 進行的編號,如AM824-Core 板載了2 個LED,MiniPort-LED 上有8 個LED,如果它們同時使用,則系統(tǒng)中有兩個LED 設(shè)備,但總共有10 個LED,LED 編號為0~9。因此,雖然p_cookie 能夠確定要操作的LED 設(shè)備,但還是不能確定要操作的具體LED,因此,必須將LED 的編號作為參數(shù)傳遞給具體方法,以便準(zhǔn)確的操作到某一具體的LED。
在通用數(shù)碼管接口的設(shè)計中,ID 是對數(shù)碼管設(shè)備的編號,如同時使用MiniPort-View 和MiniPort-ZLG72128 時,系統(tǒng)中有兩個數(shù)碼管設(shè)備,雖總共有4 個數(shù)碼管,但數(shù)碼管設(shè)備的編號只會是0~1。因為如此,數(shù)碼管設(shè)備ID 中并不包含具體數(shù)碼管的位置信息,為了將顯示內(nèi)容顯示到某一確定的數(shù)碼管上,需要使用額外的index 參數(shù)指定。
類似地,將抽象方法和p_cookie 定義在一起,即為抽象的數(shù)碼管設(shè)備。比如:
和LED 抽象設(shè)備類似,實際上可能存在多個數(shù)碼管設(shè)備,由于它們的具體數(shù)目是無法預(yù)先確定的,因此這里使用單向鏈表進行動態(tài)管理,在am_digitron_dev_t 中增加一個p_next成員,用以指向下一個設(shè)備。即:
此時,系統(tǒng)中的多個數(shù)碼管設(shè)備使用鏈表的形式管理。由于在通用接口中,使用id 區(qū)分不同的數(shù)碼管設(shè)備。因此,在通用接口的實現(xiàn)中,需要能夠通過ID 號找到對應(yīng)的數(shù)碼管設(shè)備,以便使用其中的抽象方法。和LED 設(shè)備類似,可以將一個數(shù)碼管設(shè)備和該設(shè)備對應(yīng)的ID 信息綁定在一起,就可以通過ID 找到對應(yīng)的數(shù)碼管設(shè)備。
一個數(shù)碼管設(shè)備對應(yīng)了一個唯一的ID,可以定義數(shù)碼管設(shè)備ID 信息的類型為:
在設(shè)備中新增指向ID 信息的p_info 指針,便于在通用接口實現(xiàn)中根據(jù)ID 查找到對應(yīng)的數(shù)碼管設(shè)備,即:
基于此,am_digitron_disp_char_at()函數(shù)的實現(xiàn)詳見程序清單8.44。
程序清單8.44 am_digitron_disp_char_at()接口實現(xiàn)范例
其中,__digitron_dev_find_with_id()的作用就是遍歷設(shè)備鏈表,與各個設(shè)備中的ID 信息一一比對,以找到數(shù)碼管ID 對應(yīng)的數(shù)碼管設(shè)備,其實現(xiàn)詳見程序清單8.45。
程序清單8.45 查找指定id 的數(shù)碼管設(shè)備
其中,__gp_head 是一個全局變量,指向數(shù)碼管設(shè)備的鏈表頭,初始為NULL,表示初始時系統(tǒng)中無任何數(shù)碼管設(shè)備。同理可得到其它接口的實現(xiàn),詳見程序清單8.46,它們的實現(xiàn)都非常類似,均為首先通過__digitron_dev_find_with_id()函數(shù)找到ID 對應(yīng)的數(shù)碼管設(shè)備,然后直接調(diào)用設(shè)備中的抽象方法。
程序清單8.46 其它數(shù)碼管接口的實現(xiàn)范例
由于當(dāng)前沒有任何數(shù)碼管設(shè)備,因此__digitron_dev_find_with_id()的返回值始終為NULL,使得通用接口的返回值始終為-AM_ENODEV(錯誤:無此設(shè)備)。
為了使通用接口能夠操作到具體有效的數(shù)碼管設(shè)備,就必須在使用通用數(shù)碼管接口前,向系統(tǒng)中添加有效的數(shù)碼管設(shè)備。根據(jù)數(shù)碼管設(shè)備類型的定義,添加一個設(shè)備時,需要完成p_ops、p_cookie 和p_info 的正確賦值,這些成員的值是由具體數(shù)碼管設(shè)備實現(xiàn)或定義的,為此,可以為具體數(shù)碼管的設(shè)備驅(qū)動提供一個添加數(shù)碼管設(shè)備的接口,定義其函數(shù)原型為:
其中,為了方便直接添加一個設(shè)備,避免直接操作數(shù)碼管設(shè)備的各個成員,將需要賦值的成員通過參數(shù)傳遞給接口函數(shù)。其實現(xiàn)詳見程序清單8.47。
程序清單8.47 向系統(tǒng)中添加數(shù)碼管設(shè)備
首先檢查了各個參數(shù)的有效性,然后使用__digitron_dev_find_with_id()函數(shù)判斷新設(shè)備的ID 號是否已經(jīng)在系統(tǒng)中,若系統(tǒng)中已經(jīng)存在該ID,則添加失敗,直接返回操作不允許錯誤(-AM_EPERM)。若系統(tǒng)中不存在該ID,則繼續(xù)執(zhí)行,以確保添加的各個數(shù)碼管設(shè)備的ID 不沖突,保證了數(shù)碼管設(shè)備編號的唯一性,接著將設(shè)備中的各個成員賦值,最后通過程序清單8.47 的17~18 這2 行代碼將新設(shè)備添加到鏈表首部。
圖8.17 抽象的數(shù)碼管設(shè)備類
顯然,接下來需要在具體的數(shù)碼管設(shè)備中,實現(xiàn)相應(yīng)的抽象方法,然后使用am_digitron_dev_add()接口將設(shè)備添加到系統(tǒng)中,使得用戶可以使用數(shù)碼管通用接口操作到具體有效的數(shù)碼管。為了便于查閱,如程序清單8.48 所示展示了數(shù)碼管設(shè)備接口文件(am_digitron_dev.h)的內(nèi)容。
程序清單8.48 am_digitron_dev.h 文件內(nèi)容
2. 具體的數(shù)碼管設(shè)備類
以使用GPIO 驅(qū)動的MiniPort-View 為例,簡述具體數(shù)碼管設(shè)備的實現(xiàn)方法。首先應(yīng)該基于抽象設(shè)備類派生一個具體的設(shè)備類,其類圖詳見圖8.18,定義具體的數(shù)碼管設(shè)備類如下:
圖8.18 具體的數(shù)碼管設(shè)備類
am_digitron_miniport_view_t 即為具體的數(shù)碼管設(shè)備類。具有該類型后,即可使用該類型定義一個具體的數(shù)碼管設(shè)備實例,即:
對于動態(tài)掃描類的數(shù)碼管,需要將數(shù)碼管顯示的段碼緩存到一段內(nèi)存中,然后定時掃描,依次掃描各個數(shù)碼管,從緩存中取出當(dāng)前掃描數(shù)碼管的段碼,然后將段碼輸送到相應(yīng)的引腳上顯示。
為了實現(xiàn)數(shù)碼管定時自動掃描,需要使用到軟件定時器,可以新增一個軟件定時器timer成員;在掃描過程中,需要實時記錄當(dāng)前的掃描位置,以便從相應(yīng)的數(shù)碼管緩存中取出對應(yīng)的段碼,一個數(shù)碼管掃描結(jié)束后,掃描位置要更新為下一個數(shù)碼管的位置,可以新增scan_idx成員來實時存儲當(dāng)前數(shù)碼管的掃描位置。即設(shè)備類型可定義為:
此外,為了保存閃爍屬性,可以新增一個blink_flags 的成員表示各個需要數(shù)碼管的閃爍屬性,某一位的值為1 時,表明對應(yīng)的數(shù)碼管需要閃爍。在一個閃爍周期中,一段時間需要點亮,一段時間需要熄滅,為了判定當(dāng)前應(yīng)該處于何種狀態(tài),可以新增一個閃爍計時器成員blink_cnt,用于在一個閃爍周期內(nèi)計時。特別地,在通用接口中,有一個設(shè)置數(shù)碼管解碼函數(shù)的接口,為了在用戶顯示字符時,能夠使用其設(shè)置的解碼函數(shù)對字符進行解碼,則需要一個函數(shù)指針保存用戶設(shè)置的解碼函數(shù),基于此,設(shè)備類型可定義為:
此外,為了正常使用數(shù)碼管,還需要知道一些硬件相關(guān)的基本信息,如:位選引腳信息、段碼引腳信息、數(shù)碼管個數(shù),段碼數(shù)目等,據(jù)此,可以定義數(shù)碼管設(shè)備的信息類型為:
同時,對于動態(tài)掃描類數(shù)碼管,需要一個緩存用以存儲顯示的段碼,緩存的大小應(yīng)該與數(shù)碼管個數(shù)相同,可以新增一個p_disp_buf 指針以指向相應(yīng)的緩存。此外,數(shù)碼管動態(tài)掃描時,掃描的頻率必須大于25Hz,才能使肉眼看不到動態(tài)掃描的過程,使整個數(shù)碼管的顯示完整、流暢。顯然,頻率越高,掃描越快,顯示就越流暢,但掃描數(shù)碼管時占用的CPU 資源也就越多;頻率越低,系統(tǒng)CPU 資源占用也就越少,但也不能過低。為此,可以在設(shè)備信息中新增一個scan_freq 成員,用以指定掃描的頻率,使得掃描頻率可以由用戶根據(jù)實際情況配置。掃描頻率直接決定了定時器定時掃描的周期,若掃描頻率為50Hz,則掃描一次數(shù)碼管的時間為20ms,由于MiniPort-View 存在兩個數(shù)碼管,因此定時器定時掃描的周期為10ms??梢姡〞r器定時掃描的時間間隔為:1000 / scan_freq / digitron_num。
此外,當(dāng)數(shù)碼管需要閃爍時,為了更加個性化的定制閃爍的效果,可以使用blink_on_time和blink_off_time 分別指定一個閃爍周期內(nèi)點亮的時間和熄滅的時間,它們的時間之和即為閃爍周期,決定了閃爍的頻率。
同時,在數(shù)碼管通用接口中,各個數(shù)碼管設(shè)備使用ID 號進行區(qū)分,顯然,這就要求為具體的數(shù)碼管設(shè)備分配一個唯一ID,可以在設(shè)備信息中新增表示ID 信息的成員dev_info。完整的數(shù)碼管設(shè)備信息的類型定義為:
當(dāng)將AM824-Core 與數(shù)碼管配板MiniPort-View 聯(lián)合使用時,若分配給數(shù)碼管設(shè)備的ID號為0,掃描頻率為50Hz,在一個閃爍周期內(nèi),數(shù)碼管點亮和熄滅的時間均為500ms,基于等效電路圖以及數(shù)碼管信息,定義與MiniPort-View 對應(yīng)的設(shè)備實例信息為:
類似地,在數(shù)碼管的設(shè)備類型中需要維持一個指向數(shù)碼管設(shè)備信息的指針,以便在任何時候都可以從數(shù)碼管設(shè)備中取出相關(guān)的信息使用,完整的數(shù)碼管設(shè)備類型定義為:
實際開發(fā)過程中,通常并不能一次性完整的定義出設(shè)備或設(shè)備信息的結(jié)構(gòu)體類型,往往是在定義好基本結(jié)構(gòu)后,在后續(xù)實現(xiàn)各個抽象方法的過程中,根據(jù)需要增加成員,不斷完善結(jié)構(gòu)體類型的定義。
為了正常掃描數(shù)碼管,需要完成設(shè)備中各成員的賦值,在完成初始賦值后,則可以啟動軟件定時器,進而以設(shè)備信息中指定的掃描頻率自動掃描數(shù)碼管。這些工作通常在驅(qū)動的初始化函數(shù)中完成,定義初始化函數(shù)的原型為:
其中,p_dev 為指向am_digitron_miniport_view_t 類型實例的指針,p_info 為指向am_digitron_miniport_view_info_t 類型實例信息的指針,其調(diào)用形式如下:
初始化完成后,可使用通用數(shù)碼管接口操作編號為0 的數(shù)碼管設(shè)備,初始化函數(shù)的實現(xiàn)范例詳見程序清單8.49。
程序清單8.49 初始化函數(shù)實現(xiàn)范例
該程序首先檢查了參數(shù)的有效性,然后完成了設(shè)備中各個成員的初始賦值,接著根據(jù)位選引腳和段碼引腳的激活電平,將位選引腳和段碼引腳配置成輸出模式,并將初始電平設(shè)置為未激活電平,以使數(shù)碼管初始處于完全熄滅狀態(tài)。
緊接著初始化并啟動了軟件定時器,根據(jù)掃描頻率設(shè)定了軟件定時器的定時周期,必將軟件定時器的周期性回調(diào)函數(shù)設(shè)置為了__digitron_dynamic_scan_timer_cb(),即在該函數(shù)中完成數(shù)碼管的掃描。最后,使用am_digitron_dev_add()接口將設(shè)備添加到了系統(tǒng)中,并將數(shù)碼管ID 號信息作為該接口p_info 的實參,&__g_digitron_dev_ops 作為該接口p_ops 的實參,指向自身的指針p_dev 作為了接口p_cookie 的實參,__g_digitron_dev_ops 中即包含了各個抽象方法的實現(xiàn)。
由此可見,實現(xiàn)整個具體數(shù)碼管設(shè)備的關(guān)鍵,是在__digitron_dynamic_scan_timer_cb()中完成數(shù)碼管的掃描,以及實現(xiàn)各個抽象方法并存于__g_digitron_dev_ops 中。
定時器回調(diào)函數(shù)__digitron_dynamic_scan_timer_cb()的實現(xiàn)詳見程序清單8.50。
程序清單8.50 定時器回調(diào)函數(shù)的實現(xiàn)(數(shù)碼管掃描)
該程序首先處理閃爍計時器,若存在閃爍的數(shù)碼管,則增加閃爍計時器p_dev->blink_cnt,增加的值即為掃描時間間隔。特別地,若值增加后超過了閃爍周期,則重新回到0。然后使用__scan_seg_send()發(fā)送消影段碼,使用__scan_com_sel()處理位選。若當(dāng)前數(shù)碼管需要正常顯示,即當(dāng)前數(shù)碼管不需要閃爍,或者雖然需要閃爍,但根據(jù)閃爍計時器判定當(dāng)前時間處在點亮數(shù)碼管的時間周期,則從顯示緩存中取出當(dāng)前數(shù)碼管的段碼,并使用__scan_seg_send()發(fā)送出去。最后更新了掃描位置索引scan_idx 的值,以便下一次掃描時繼續(xù)掃描下一個數(shù)碼管,段碼發(fā)送函數(shù)和位選函數(shù)的實現(xiàn)詳見程序清單8.51。
程序清單8.51 段碼發(fā)送函數(shù)和位選函數(shù)的實現(xiàn)
接下來,需要一一實現(xiàn)抽象數(shù)碼管設(shè)備中共計定義了6 個抽象方法,以完成__g_digitron_dev_ops 的定義。
-
pfn_decode_set
該方法用于設(shè)定解碼函數(shù),便于顯示時,對各個字符進行解碼。顯然,需要將其保存到設(shè)備中,以便后續(xù)使用。范例程序詳見程序清單8.52。
程序清單8.52 設(shè)置解碼函數(shù)的實現(xiàn)范例程序
-
pfn_blink_set
該方法用于設(shè)定某一個數(shù)碼管的閃爍屬性,設(shè)置閃爍屬性時,只需要將設(shè)備中的閃爍標(biāo)記blibk_flags 相應(yīng)位置1(閃爍)或清零(不閃爍)即可,范例程序詳見程序清單8.53。
程序清單8.53 設(shè)置閃爍屬性函數(shù)的實現(xiàn)范例程序
-
pfn_disp_at
該方法用于在指定數(shù)碼管上顯示指定的段碼圖形,只需要將段碼存放在數(shù)碼管緩存中即可,范例程序詳見程序清單8.54。
程序清單8.54 顯示段碼函數(shù)的實現(xiàn)范例程序
該程序調(diào)用了__digitron_disp_buf_set()函數(shù)將段碼設(shè)置到緩存中,詳見程序清單8.55。
程序清單8.55 __digitron_disp_buf_set()函數(shù)實現(xiàn)
該程序根據(jù)數(shù)碼管段的激活電平?jīng)Q定是否需要將用戶設(shè)置的段碼取反后存入緩沖區(qū)中。
-
pfn_disp_char_at
該方法用于在指定位置顯示字符,這就需要先使用解碼函得到字符對應(yīng)的段碼,然后將段碼設(shè)置到緩沖區(qū)中,范例程序詳見程序清單8.56。
程序清單8.56 顯示字符函數(shù)的實現(xiàn)范例程序
該程序首先通過解碼函數(shù)得到字符的段碼存于seg 中。然后將段碼保存到相應(yīng)的緩沖區(qū)中,且在保存段碼時對小數(shù)點作了特殊的處理。
當(dāng)字符為小數(shù)點時,則使用__digitron_disp_buf_xor()函數(shù)將段碼設(shè)置到函數(shù)區(qū);否則直接使用__digitron_disp_buf_set()函數(shù)將段碼設(shè)置到緩存區(qū)中。
由于由于小數(shù)點比較特殊,因此顯示小數(shù)點時,往往不希望影響該位數(shù)碼管的正常顯示內(nèi)容,比如,如果當(dāng)前數(shù)碼管顯示數(shù)字3,又需要在該數(shù)碼管添加小數(shù)點,則期望的結(jié)果是顯示“3.”,而不僅僅顯示一個小數(shù)點,將之前的3 覆蓋掉。由此可見,在顯示小數(shù)點時,可視為顯示內(nèi)容的一種疊加,而不是直接改變顯示內(nèi)容,__digitron_disp_buf_xor()函數(shù)的實現(xiàn)詳見程序清單8.57。
程序清單8.57 __digitron_disp_buf_xor()函數(shù)實現(xiàn)
若數(shù)碼管段為低電平激活,則需要在原緩沖區(qū)段碼的基礎(chǔ)上,將顯示小數(shù)點需要點亮的段清零,以顯示小數(shù)點;反之則將顯示小數(shù)點需要點亮的段置1,以顯示小數(shù)點。
-
pfn_disp_str
該方法用于從指定位置開始顯示一個字符串,范例程序詳見程序清單8.58。
程序清單8.58 字符串顯示函數(shù)實現(xiàn)范例程序
該程序首先確定了字符串的長度,字符串長度取字符串實際長度和參數(shù)len 中的較小值,然后再while 循環(huán)中,調(diào)用了__digitron_disp_char_at()函數(shù)依次顯示單個字符。
其中的idx 用于指定顯示位置,初始值為index – 1,即字符串顯示起始位置的上一個數(shù)碼管位置,若起始位置為0,則idx 的初始值表示了一個無效的位置。每次顯示新內(nèi)容前,需要更新idx 的值(將idx 加1)。但在某種特殊情況下,小數(shù)點不需要更新顯示位置,例如,顯示字符串“3.5”,期望顯示的效果是只占用2 個數(shù)碼管,分別顯示“3.”和“5”,而不是占用3 個數(shù)碼管,這種情況下,當(dāng)顯示小數(shù)點時,直接顯示在“3”所在的數(shù)碼管中即可,無需將其單獨顯示到一個數(shù)碼管上。程序需要更新顯示位置的條件為:
由此可見,不需要更新位置的條件即為上述條件的反面:
不需要更新位置的條件為:當(dāng)前顯示的字符為小數(shù)點,且上一個字符不為小數(shù)點,同時idx 指定的顯示位置有效。
-
pfn_clr
該方法用于清空數(shù)碼管顯示,需要將緩沖區(qū)中的內(nèi)容全部設(shè)置為熄滅段碼,范例程序詳見程序清單8.59。
程序清單8.59 清空顯示內(nèi)容函數(shù)的實現(xiàn)范例程序
至此,實現(xiàn)了各個抽象方法,基于各個抽象方法的實現(xiàn)函數(shù),__g_digitron_dev_ops 的定義詳見程序清單8.60。
程序清單8.60 __g_digitron_dev_ops 的定義
當(dāng)用戶使用初始化函數(shù)完成一個具體數(shù)碼管設(shè)備的初始化后,即可使用通用數(shù)碼管接口操作數(shù)碼管,顯示具體內(nèi)容。但是,在顯示字符或字符前,必須使用通用接口設(shè)置一個解碼函數(shù)。對于8 段數(shù)碼管,可以將各個ASCII 字符的段碼定義在一個數(shù)組中,然后實現(xiàn)一個解碼函數(shù),詳見程序清單8.61。
程序清單8.61 解碼函數(shù)的實現(xiàn)
基于此,在用戶使用數(shù)碼管接口顯示字符或字符串前,可以使用設(shè)置解碼函數(shù)的接口將該解碼函數(shù)設(shè)置到系統(tǒng)中,以便正確解碼。比如:
如果用戶每次使用數(shù)碼管前,都需要自定義一個解碼函數(shù),則顯得非常麻煩。對于8段數(shù)碼管,常見圖形的顯示方法是固定的,對應(yīng)的段碼是可以確定的,如數(shù)字0 ~ 9。用戶如果沒有特殊需求,使用程序清單8.61 所示的解碼函數(shù)是能滿足絕大部分應(yīng)用的?;诖耍梢詫⒊绦蚯鍐?.61 所示的解碼函數(shù)定義在系統(tǒng)中,直接供用戶使用。為方便用戶使用,可以將該解碼函數(shù)聲明到數(shù)碼管接口文件中。
為了便于查閱,如程序清單8.62 所示展示了具體數(shù)碼管設(shè)備(MiniPort_View)接口文件(am_digitron_miniport_view.h)的內(nèi)容。
程序清單8.62 am_digitron_miniport_view.h 文件內(nèi)容
原文標(biāo)題:周立功:深入理解AMetal——通用數(shù)碼管接口
文章出處:【微信號:ZLG_zhiyuan,微信公眾號:ZLG致遠電子】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論