一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

依托面向接口編程開(kāi)發(fā)思想,聚焦LED通用設(shè)計(jì)

UtFs_Zlgmcu7890 ? 來(lái)源:互聯(lián)網(wǎng) ? 作者:佚名 ? 2018-01-15 09:59 ? 次閱讀

周立功教授新書(shū)《面向AMetal框架與接口編程(上)》,對(duì)AMetal框架進(jìn)行了詳細(xì)介紹,通過(guò)閱讀這本書(shū),你可以學(xué)到高度復(fù)用的軟件設(shè)計(jì)原則和面向接口編程的開(kāi)發(fā)思想,聚焦自己的“核心域”,改變自己的編程思維,實(shí)現(xiàn)企業(yè)和個(gè)人的共同進(jìn)步。

第八章為深入理解AMetal,本文內(nèi)容為8.1 LED 通用接口。

第八章導(dǎo)讀

面向通用接口的編程使得應(yīng)用程序與具體硬件無(wú)關(guān),可以很容易地實(shí)現(xiàn)跨平臺(tái)復(fù)用。但究其本質(zhì)如何,具體是怎樣實(shí)現(xiàn)的呢?

8.1 LED 通用接口

本節(jié)將以LED 通用接口為例,詳細(xì)介紹通用接口的設(shè)計(jì)方法。

>>> 8.1.1 定義接口

合理的接口應(yīng)該是易閱讀的、職責(zé)明確的,下面將從接口的命名、參數(shù)和返回值三個(gè)方面闡述在AMetal 中定義接口的一般方法。

1. 接口命名

在AMetal 中,所有通用接口均以“am_”開(kāi)頭,緊接著是操作對(duì)象的名字,對(duì)于LED控制接口來(lái)說(shuō),所有接口應(yīng)該以“am_led_”為前綴。

當(dāng)接口的前綴定義好之后,需要考慮定義哪些功能性接口,然后根據(jù)功能完善接口名。對(duì)于LED 來(lái)說(shuō),核心的操作是控制LED 的狀態(tài),點(diǎn)亮或熄滅LED,因此需要提供一個(gè)設(shè)置(set)LED 狀態(tài)的函數(shù),比如:

  • am_led_set

顯然,通過(guò)該接口可以設(shè)置LED 的狀態(tài),為了區(qū)分是點(diǎn)亮還是熄滅LED,需要通過(guò)一個(gè)參數(shù)指定具體的操作。

在大多數(shù)應(yīng)用場(chǎng)合中,可能需要頻繁地開(kāi)燈和關(guān)燈操作,每次開(kāi)關(guān)燈都需要通過(guò)傳遞參數(shù)給am_led_set()接口實(shí)現(xiàn)開(kāi)燈和關(guān)燈,這樣做會(huì)非常繁瑣。因此可以為常用的開(kāi)燈和關(guān)燈操作定義專用的接口,也就不再需要額外參數(shù)區(qū)分具體的操作。比如,使用on 和off 分別表示開(kāi)燈和關(guān)燈,則定義開(kāi)燈和關(guān)燈的接口名為:

  • am_led_on

  • am_led_off

在一些特殊的應(yīng)用場(chǎng)合種,比如,LED 閃爍,其可能并不關(guān)心具體的操作是開(kāi)燈還是關(guān)燈,它僅僅需要LED 的狀態(tài)發(fā)生翻轉(zhuǎn)。此時(shí),可以定義一個(gè)用于翻轉(zhuǎn)(toggle)LED 狀態(tài)的接口,其接口名為:

  • am_led_toggle

2. 接口參數(shù)

在AMetal 中,通用接口的第一個(gè)參數(shù)表示要操作的具體對(duì)象。顯然,一個(gè)系統(tǒng)可能有多個(gè)LED,為了確定操作的LED,最簡(jiǎn)單的方法是為每個(gè)LED 分配一個(gè)唯一編號(hào),即ID號(hào),然后通過(guò)ID 號(hào)確定需要操作的LED。ID 號(hào)是一個(gè)從0 開(kāi)始的整數(shù),其類(lèi)型為int,基于此,所有接口的第一個(gè)參數(shù)定義為int 類(lèi)型的led_id。

對(duì)于am_led_set 接口來(lái)說(shuō),除使用led_id 確定需要控制的LED 外,還需要使用一個(gè)參數(shù)區(qū)分是點(diǎn)亮LED 還是熄滅LED。由于是二選一的操作,因此該參數(shù)的類(lèi)型使用布爾類(lèi)型:am_bool_t。當(dāng)值為真(AM_TRUE)時(shí),則點(diǎn)亮LED;當(dāng)值為假(AM_FALSE)時(shí),則熄滅LED。基于此,包含參數(shù)的am_led_set 接口函數(shù)原型為(還未定義返回值):

對(duì)于am_led_on、am_led_off 和am_led_toggle 接口來(lái)說(shuō),它們的職責(zé)單一,僅僅需要指定控制的LED,即可完成點(diǎn)亮、熄滅或翻轉(zhuǎn)操作,無(wú)需額外的其它參數(shù)。因此對(duì)于這類(lèi)接口,參數(shù)僅僅只需要led_id。其函數(shù)原型如下:

實(shí)際上,在AMetal 通用接口的第一個(gè)參數(shù)中,除使用ID 號(hào)表示操作的具體對(duì)象外,還可能直接使用指向具體對(duì)象的指針,或者表示具體對(duì)象的一個(gè)句柄來(lái)表示,它們的作用在本質(zhì)上是完全一樣的。

3. 返回值

對(duì)于用戶來(lái)說(shuō),調(diào)用通用接口后,應(yīng)該可以獲取本次執(zhí)行的結(jié)果,成功還是失敗,或一些其它的有用信息。比如,當(dāng)調(diào)用接口時(shí),如果指定的led_id 超過(guò)有效范圍時(shí),由于沒(méi)有與led_id 對(duì)應(yīng)的LED 設(shè)備,操作必定會(huì)失敗,此時(shí)必須返回錯(cuò)誤,告知用戶操作失敗,且失敗的原因是led_id 不在有效范圍內(nèi),無(wú)與之對(duì)應(yīng)的LED 設(shè)備。

在AMetal 中,通過(guò)返回值返回接口執(zhí)行的結(jié)果,其類(lèi)型為int,返回值的含義為:若返回值為AM_OK,則表示操作成功;若返回值為負(fù)數(shù),則表示操作失敗,失敗原因可根據(jù)返回值,查找am_errno.h 文件中定義的宏,根據(jù)宏的含義確定失敗的原因;若返回值為正數(shù),其含義與具體接口相關(guān),由具體接口定義,無(wú)特殊說(shuō)明時(shí),表明不會(huì)返回正數(shù)。

AM_OK 在am_common.h 文件中定義,其定義如下:

錯(cuò)誤號(hào)在am_errno.h 文件中定義,幾個(gè)常見(jiàn)錯(cuò)誤號(hào)的定義詳見(jiàn)表8.1。比如,在調(diào)用LED 通用接口時(shí),若led_id 不在有效范圍內(nèi),則該led_id沒(méi)有對(duì)應(yīng)的LED 設(shè)備,此時(shí)接口應(yīng)該返回-AM_ENODEV。注意:M_ENODEV 的前面有一個(gè)負(fù)號(hào),以返回負(fù)值。

表8.1 常見(jiàn)錯(cuò)誤號(hào)定義(am_errno.h)

基于此,將所有LED 控制接口的返回值定義為int,LED 控制接口的完整定義詳見(jiàn)表8.2,其對(duì)應(yīng)的類(lèi)圖詳見(jiàn)圖8.1。

表8.2 LED 通用接口(am_led.h)

圖8.1 LED 對(duì)應(yīng)的類(lèi)圖

>>> 8.1.2 實(shí)現(xiàn)接口

當(dāng)完成接口定義后,還需要提供相應(yīng)的驅(qū)動(dòng)實(shí)現(xiàn)這些接口,才能使用這些接口操作LED。

1. 實(shí)現(xiàn)接口初探

LED 有4 個(gè)通用接口函數(shù),其中的am_led_on()和am_led_off()接口是基于am_led_set()接口實(shí)現(xiàn)的,詳見(jiàn)程序清單8.1。

程序清單8.1 am_led_on()和am_led_off()接口的實(shí)現(xiàn)

實(shí)現(xiàn)接口的核心是實(shí)現(xiàn)am_led_set()和am_led_toggle()接口,通用接口在于屏蔽底層的差異性,即無(wú)論底層硬件如何變化,用戶都可以調(diào)用通用接口操作LED。但對(duì)于不同的硬件電路,比如,GPIO 和HC595 控制LED 的硬件電路,設(shè)置LED 狀態(tài)和LED 翻轉(zhuǎn)的具體實(shí)現(xiàn)是不同的。下面以設(shè)置LED 狀態(tài)的具體實(shí)現(xiàn)為例進(jìn)行詳細(xì)說(shuō)明。

對(duì)于GPIO 控制LED 的硬件電路來(lái)說(shuō),當(dāng)使用GPIO 控制AM824-Core 的兩個(gè)板載LED時(shí),LED0 通過(guò)J9 與MCU 的PIO0_20 相連,LED1 通過(guò)J10 與MCU 的PIO0_21 相連。使用短路冒將J9 和J10 短路后即可使用PIO0_20 和PIO0_21 控制LED0 和LED1,當(dāng)引腳輸出低電平時(shí),則點(diǎn)亮LED;當(dāng)引腳輸出高電平時(shí),則熄滅LED,直接使用GPIO 通用接口實(shí)現(xiàn)am_led_set()接口詳見(jiàn)程序清單8.2。

程序清單8.2 am_led_set()的實(shí)現(xiàn)(GPIO 控制LED)

對(duì)于HC595 控制LED 的硬件電路來(lái)說(shuō),當(dāng)將MiniPort-595 和MiniPort-LED 聯(lián)合使用時(shí),通過(guò)控制HC595 的輸出,可以達(dá)到控制LED 點(diǎn)亮和熄滅的效果,當(dāng)相應(yīng)引腳輸出低電平時(shí),則點(diǎn)亮LED;當(dāng)相應(yīng)輸出高電平時(shí),則熄滅LED,直接使用HC595 通用接口實(shí)現(xiàn)am_led_set()接口詳見(jiàn)程序清單8.3。

程序清單8.3 am_led_set()的實(shí)現(xiàn)(HC595 控制LED)

在實(shí)際的應(yīng)用中,__g_hc595_handle 需要賦值后才能使用。通過(guò)程序清單8.2 和程序清單8.3 比較發(fā)現(xiàn),它們?cè)O(shè)置LED 狀態(tài)的實(shí)現(xiàn)是完全不同的。顯然,在同一個(gè)應(yīng)用中,一個(gè)接口的實(shí)現(xiàn)代碼只能有一份,因此程序清單8.2 和程序清單8.3 所示的實(shí)現(xiàn)是不能在一個(gè)應(yīng)用程序中共存的。在這種情況下,要么選擇使用GPIO 控制LED,要么使用HC595 控制LED。

2. 抽象的LED 設(shè)備類(lèi)

在使用不同方式控制LED 時(shí),雖然它們對(duì)應(yīng)am_led_set()和am_led_toggle()的實(shí)現(xiàn)方法不同,但它們要實(shí)現(xiàn)的功能卻是一樣的,這是它們的共性:均要實(shí)現(xiàn)設(shè)置LED 狀態(tài)和翻轉(zhuǎn)LED 狀態(tài)的功能。由于一個(gè)接口的實(shí)現(xiàn)代碼只能有一份,因此它們的實(shí)現(xiàn)不能直接作為通用接口的實(shí)現(xiàn)代碼。為此,可以對(duì)它們的共性進(jìn)行抽象,即抽象為如下兩個(gè)方法:

相對(duì)通用接口來(lái)說(shuō),抽象方法多了一個(gè)p_cookie 參數(shù)。在面向?qū)ο蟮木幊讨校瑢?duì)象中的方法都能通過(guò)隱形指針p_this 訪問(wèn)對(duì)象自身,引用自身的一些私有數(shù)據(jù)。而在C 語(yǔ)言中則需要顯式的聲明,這里的p_cookie 就有相同的作用。

為了節(jié)省內(nèi)存空間,將所有抽象方法放在一個(gè)結(jié)構(gòu)體中,形成一個(gè)虛函數(shù)表,比如:

這里定義了一個(gè)虛函數(shù)表,包含了兩個(gè)方法,分別用于設(shè)置LED 的狀態(tài)和翻轉(zhuǎn)LED。針對(duì)不同的硬件設(shè)備,都可以根據(jù)自身特性實(shí)現(xiàn)這兩個(gè)方法。GPIO 控制LED 的偽代碼詳見(jiàn)程序清單8.4,HC595 控制LED 的偽代碼詳見(jiàn)程序清單8.5。

程序清單8.4 抽象方法的實(shí)現(xiàn)(GPIO 控制LED)

程序清單8.5 抽象方法的實(shí)現(xiàn)(HC595 控制LED)

顯然,__g_led_gpio_drv_funcs 和__g_led_hc595_drv_funcs 分別是使用GPIO 和HC595控制LED 的一種具體實(shí)現(xiàn),它們?cè)谛问缴鲜莾蓚€(gè)不同的結(jié)構(gòu)體常量,在同一系統(tǒng)中是可以共存的。當(dāng)有了針對(duì)不同硬件的驅(qū)動(dòng)后,在am_led_set()接口的實(shí)現(xiàn)中,就需要根據(jù)實(shí)際情況找到對(duì)應(yīng)的驅(qū)動(dòng),然后調(diào)用其中實(shí)現(xiàn)的pfn_led_set 方法。在調(diào)用pfn_led_set()方法時(shí),由于該方法的第一個(gè)參數(shù)為p_cookie,p_cookie 代表了具體的對(duì)象,實(shí)際上驅(qū)動(dòng)函數(shù)和p_cookie一起唯一地確定了一個(gè)具體的LED 設(shè)備?;诖丝梢詫Ⅱ?qū)動(dòng)函數(shù)和p_cookie 定義在一起,形成一個(gè)新的LED 設(shè)備類(lèi)型。即:

其中,p_funcs 為指向驅(qū)動(dòng)虛函數(shù)表的指針,比如,指向__g_led_gpio_drv_funcs 或__g_led_hc595_drv_funcs,p_cookie 為指向設(shè)備的指針,即傳遞給驅(qū)動(dòng)函數(shù)的第一個(gè)參數(shù)。

此時(shí),在am_led_set()接口的實(shí)現(xiàn)中,無(wú)需完成真實(shí)的設(shè)置LED 狀態(tài)的操作,僅需調(diào)用設(shè)備中的pfn_led_set 方法即可,其范例程序詳見(jiàn)程序清單8.6。

程序清單8.6 am_led_set()實(shí)現(xiàn)(1)

假定LED 設(shè)備為全局變量__gp_led_dev 指向的設(shè)備,展示了pfn_led_set 方法的調(diào)用形式。而實(shí)際上LED 設(shè)備往往不止一個(gè),比如,用GPIO 控制LED 的設(shè)備和使用HC595 控制LED 的設(shè)備,就需要在系統(tǒng)中管理多個(gè)LED 設(shè)備。由于它們的具體數(shù)目無(wú)法確定,因此需要使用單向鏈表進(jìn)行動(dòng)態(tài)管理。在am_led_dev_t 中增加一個(gè)p_next 成員,用于指向下一個(gè)設(shè)備。即:

此時(shí),系統(tǒng)中的多個(gè)LED 設(shè)備使用鏈表的形式管理。那么在通用接口的實(shí)現(xiàn)中,如何確定該使用哪個(gè)LED 設(shè)備呢?在定義通用接口時(shí),使用了led_id 區(qū)分不同LED,若將一個(gè)LED 設(shè)備和該設(shè)備對(duì)應(yīng)的led_id 綁定在一起,則在通用接口的實(shí)現(xiàn)中,就可以根據(jù)led_id找到對(duì)應(yīng)的LED 設(shè)備,然后使用驅(qū)動(dòng)中提供的相應(yīng)方法完成LED 的操作。

顯然,一個(gè)LED 設(shè)備可能包含多個(gè)LED,在AM824-Core 中,GPIO 控制了2 個(gè)LED,HC595 控制了8 個(gè)LED。如果兩個(gè)設(shè)備同時(shí)使用,則整個(gè)系統(tǒng)中共有10 個(gè)LED,編號(hào)為0~9。一般來(lái)說(shuō),一個(gè)設(shè)備中的所有LED 編號(hào)是連續(xù)的,比如,兩個(gè)LED 設(shè)備的編號(hào)分別為 0~1,2~9。如需獲得一個(gè)LED 設(shè)備中所有LED 的編號(hào),僅需知道LED 的起始編號(hào)和結(jié)束編號(hào)即可,為此定義LED 設(shè)備對(duì)應(yīng)的led_id 信息為:

在設(shè)備中新增指向LED 信息的p_info 指針,便于在通用接口實(shí)現(xiàn)中根據(jù)led_id 查找到對(duì)應(yīng)的LED 設(shè)備,即:

基于此,am_led_set()函數(shù)的實(shí)現(xiàn)詳見(jiàn)程序清單8.7。

程序清單8.7 am_led_set()實(shí)現(xiàn)(2)

其中,__led_dev_find_with_id()的作用就是遍歷設(shè)備鏈表,與各個(gè)設(shè)備中的ID 信息一一比對(duì),以找到led_id 對(duì)應(yīng)的LED 設(shè)備,其實(shí)現(xiàn)詳見(jiàn)程序清單8.8。

程序清單8.8 查找指定led_id 的LED 設(shè)備

其中,__gp_head 是一個(gè)全局變量,初始為NULL,表示初始時(shí)系統(tǒng)中無(wú)任何LED 設(shè)備。同理,可得到am_led_toggle()接口的實(shí)現(xiàn),詳見(jiàn)程序清單8.9。

程序清單8.9 am_led_toggle()實(shí)現(xiàn)

至此,實(shí)現(xiàn)了所有通用接口。由于當(dāng)前沒(méi)有任何LED 設(shè)備,因此__led_dev_find_with_id()為NULL,通用接口的返回值也始終為-AM_ENODEV。

為了使通用接口能夠操作到具體有效的LED,就必須向系統(tǒng)中添加一個(gè)有效的LED 設(shè)備。根據(jù)LED 設(shè)備類(lèi)型的定義,添加一個(gè)設(shè)備時(shí),需要完成p_funcs、p_cookie 和p_info 的正確賦值,這些成員的賦值需要具體的LED 設(shè)備對(duì)象來(lái)完成,如GPIO 控制LED 的設(shè)備。為此,可以為驅(qū)動(dòng)提供一個(gè)添加LED 設(shè)備的接口。比如:

其中,為了方便驅(qū)動(dòng)直接添加一個(gè)設(shè)備,避免直接操作LED 設(shè)備的各個(gè)成員,將需要賦值的成員通過(guò)參數(shù)傳遞給接口函數(shù),其實(shí)現(xiàn)詳見(jiàn)程序清單8.10。

程序清單8.10 向系統(tǒng)中添加LED 設(shè)備

該程序首先通過(guò)判斷新設(shè)備的起始LED 編號(hào)和結(jié)束LED 編號(hào)是否已經(jīng)存在于系統(tǒng)之中來(lái)判斷ID 是否是有效范圍,確保添加的各個(gè)LED 設(shè)備的ID 不沖突,即保證了LED 編號(hào)的唯一性,然后將設(shè)備中的各個(gè)成員賦值,最后通過(guò)程序清單8.10的21~22 行共計(jì)2 行代碼將新設(shè)備添加到鏈表首部。

顯然,接下來(lái)需要在具體的LED 設(shè)備驅(qū)動(dòng)實(shí)現(xiàn)中,使用am_led_dev_add()接口向系統(tǒng)中添加設(shè)備,使得用戶可以使用LED 通用接口操作到具體有效的LED。

在上述分析的過(guò)程中,定義了LED 設(shè)備類(lèi),在其中完成了LED 通用接口的實(shí)現(xiàn),可以用類(lèi)圖來(lái)表示這個(gè)關(guān)系,詳見(jiàn)圖8.2。

圖8.2 抽象的LED 設(shè)備類(lèi)

LED 設(shè)備中存在抽象方法pfn_led_set 和pfn_led_toggle,這兩個(gè)抽象方法是以虛函數(shù)表的形式存在LED 設(shè)備類(lèi)中的。由于存在抽象方法,因此LED 設(shè)備類(lèi)是一個(gè)抽象類(lèi),它本身不能夠直接實(shí)例化,必須由其派生的具體類(lèi)實(shí)現(xiàn)這兩個(gè)抽象方法。為了便于查閱,如程序清單8.11 所示展示了LED 設(shè)備的接口文件am_led_dev.h 的內(nèi)容。

程序清單8.11 am_led_dev.h 文件內(nèi)容

3. 具體的LED 設(shè)備類(lèi)

前面定義的抽象LED 設(shè)備類(lèi)中包含了兩個(gè)抽象方法:pfn_led_set 和pfn_led_toggle。為了使用戶可以通過(guò)LED 通用接口操作LED,就必須根據(jù)實(shí)際硬件連接,實(shí)現(xiàn)兩個(gè)抽象方法,然后將具體設(shè)備添加到系統(tǒng)設(shè)備鏈表中。

下面分別以GPIO 控制LED 的驅(qū)動(dòng)實(shí)現(xiàn)和HC595 控制LED 的驅(qū)動(dòng)實(shí)現(xiàn)為例,闡述LED設(shè)備驅(qū)動(dòng)開(kāi)發(fā)的一般方法,如果后續(xù)有其它類(lèi)型的LED 控制電路,可以按照此方法添加自定義的LED 驅(qū)動(dòng)。

(1) GPIO 控制LED 的驅(qū)動(dòng)實(shí)現(xiàn)

具體LED 設(shè)備的核心功能是實(shí)現(xiàn)抽象設(shè)備類(lèi)中定義的方法,首先應(yīng)該基于抽象設(shè)備類(lèi)派生一個(gè)具體的設(shè)備類(lèi),其類(lèi)圖詳見(jiàn)圖8.3。

圖8.3 具體設(shè)備類(lèi)(GPIO)

可直接定義具體的LED 設(shè)備類(lèi)。比如:

am_led_gpio_dev_t 即為具體的LED 設(shè)備類(lèi)。具有該類(lèi)型后,即可使用該類(lèi)型定義一個(gè)具體的LED 設(shè)備實(shí)例:

在使用GPIO 控制LED 時(shí),需要知道對(duì)應(yīng)的引腳信息和LED 點(diǎn)亮的電平信息,為了便于修改配置,這些信息往往由用戶傳遞給驅(qū)動(dòng)。此外,還需要提供LED 設(shè)備的ID 信息,包含起始ID 和結(jié)束ID,以確定的為設(shè)備中的每個(gè)LED 分配一個(gè)唯一ID?;诖耍梢詫⑿枰捎脩籼峁┑脑O(shè)備相關(guān)信息存放到一個(gè)新的結(jié)構(gòu)體類(lèi)型中,將其作為需要由用戶提供的設(shè)備信息。即:

對(duì)于AM824_Core 的兩個(gè)板載LED 來(lái)說(shuō),若編號(hào)為0~1,則可以使用該類(lèi)型定義其對(duì)應(yīng)的設(shè)備實(shí)例信息如下

為了便于通過(guò)設(shè)備直接找到對(duì)應(yīng)的設(shè)備信息,在設(shè)備類(lèi)中往往直接維持一個(gè)指向設(shè)備信息的指針。即:

顯然,在使用GPIO 控制LED 前,引腳需要初始化為輸出模式,此外,在完成初始化后,還需要將具體的LED 設(shè)備添加到系統(tǒng)中,便于使用通用接口操作LED。這些工作通常在驅(qū)動(dòng)的初始化函數(shù)中完成,初始化函數(shù)的原型為:

其中,p_dev 指向am_led_gpio_dev_t 類(lèi)型的設(shè)備,p_info 為指向am_led_gpio_info_t 類(lèi)型實(shí)例信息的指針,其調(diào)用形式如下:

初始化函數(shù)的的實(shí)現(xiàn)詳見(jiàn)程序清單8.12。

程序清單8.12 初始化函數(shù)實(shí)現(xiàn)(GPIO 控制LED)

程序中,首先通過(guò)LED 的起始編號(hào)和結(jié)束編號(hào),得到了LED 的數(shù)目,由于GPIO 的引腳數(shù)目與LED 數(shù)目相等,因此,也就得到了GPIO 引腳的數(shù)目。然后將所有引腳配置為了輸出模式,并根據(jù)是否為低電平點(diǎn)亮,初始時(shí)使所有LED 處于熄滅狀態(tài)。最后,通過(guò)am_led_dev_add()函數(shù),將具體的LED 設(shè)備添加到了系統(tǒng)之中。

在添加LED 設(shè)備時(shí),LED 的 ID 信息直接使用了設(shè)備信息中的ID 信息,抽象方法的實(shí)現(xiàn)使用了__g_led_gpio_drv_funcs 中實(shí)現(xiàn)的方法(其定義詳見(jiàn)程序清單8.4),p_cookie 直接設(shè)置為了指向設(shè)備自身的指針,正因?yàn)槿绱?,在抽象方法的?shí)現(xiàn)中,p_cookie 參數(shù)即為指向設(shè)備自身的指針,可以通過(guò)p_cookie 得到具體設(shè)備相關(guān)的信息,如GPIO 信息等,進(jìn)而實(shí)現(xiàn)LED 的相關(guān)操作,完善程序清單8.4 中實(shí)現(xiàn)的抽象方法,詳見(jiàn)程序清單8.13。

程序清單8.13 抽象方法的實(shí)現(xiàn)(GPIO 控制LED)

在抽象方法的實(shí)現(xiàn)中,首先通過(guò)類(lèi)型強(qiáng)制轉(zhuǎn)換將p_cookie 轉(zhuǎn)換為指向具體設(shè)備的指針。然后通過(guò)它找到相應(yīng)的引腳信息,進(jìn)而實(shí)現(xiàn)LED 的相關(guān)操作。在設(shè)置LED 狀態(tài)的實(shí)現(xiàn)中,巧妙的使用了“異或(^)”預(yù)算。因?yàn)?a target="_blank">active_low 的值與實(shí)際的點(diǎn)亮電平是恰好相反的,即若active_low 為AM_TRUE,表明輸出低電平點(diǎn)亮,反之,輸出高電平點(diǎn)亮。state 及active_low 的值都將影響本次GPIO 的輸出電平,GPIO 的輸出電平與state 和active_low 的真值表詳見(jiàn)表8.3。由此可見(jiàn),當(dāng)state 與active_low 相同時(shí),則GPIO 輸出0;當(dāng)state 與active_low 不同時(shí),則GPIO 輸出1,恰好是異或關(guān)系。

表8.3 GPIO 輸出增值表

為了便于查閱,如程序清單8.14 所示展示了LED 設(shè)備接口文件am_led_gpio.h 的內(nèi)容。

程序清單8.14 am_led_gpio.h 文件內(nèi)容

(2) HC595 控制LED 的驅(qū)動(dòng)實(shí)現(xiàn)

同樣,首先基于抽象設(shè)備類(lèi)派生一個(gè)具體的設(shè)備類(lèi),其類(lèi)圖詳見(jiàn)圖8.4,可直接定義具體的LED 設(shè)備類(lèi):

am_led_hc595_dev_t 為具體的LED 設(shè)備類(lèi),當(dāng)具有該類(lèi)型后,即可使用該類(lèi)型定義一個(gè)具體的LED 設(shè)備實(shí)例:

圖8.4 具體設(shè)備類(lèi)(HC595)

在使用HC595 控制LED 時(shí),需要知道LED 和HC595相關(guān)的信息,如LED 點(diǎn)亮的電平信息和HC595 的數(shù)目。雖然MiniPort-595 只有一個(gè)HC595,但作為一個(gè)通用的驅(qū)動(dòng),應(yīng)考慮到這些基礎(chǔ)的擴(kuò)展,以便驅(qū)動(dòng)可以盡可能的支持更多的硬件電路。

特別地,HC595 的每次輸出都是完整的輸出,如對(duì)于單個(gè)HC595,其每次輸出都只能輸出完整的8 位數(shù)據(jù),不能單獨(dú)輸出1 位數(shù)據(jù),而LED 的控制又是對(duì)單個(gè)LED 進(jìn)行的,因此,為了在控制一個(gè)LED 時(shí),不影響到其它LED,必須使其他位的輸出保持不變,這就需要實(shí)時(shí)保存當(dāng)前的輸出,為了保存當(dāng)前所有HC595 的輸出信息,需要用戶提供一個(gè)緩沖區(qū),緩沖區(qū)的大小與HC595 的個(gè)數(shù)相等。

此外,還需要提供包含起始ID 和結(jié)束ID 的ID 信息?;诖耍梢詫⑿枰捎脩籼峁┑脑O(shè)備相關(guān)信息存放到一個(gè)新的結(jié)構(gòu)體類(lèi)型中,將其作為需要由用戶提供的設(shè)備信息:

對(duì)于使用MiniPort-595 和MiniPort-LED 聯(lián)合使用的情況,共計(jì)8 個(gè)LED,若分配的編號(hào)為2~9,則可以使用該類(lèi)型定義其對(duì)應(yīng)的設(shè)備實(shí)例信息如下:

同理,在設(shè)備類(lèi)中需要維持一個(gè)指向設(shè)備信息的指針。此外,由于使用HC595 驅(qū)動(dòng)LED時(shí),需要使用HC595 的句柄handle 來(lái)傳輸數(shù)據(jù),因此,用戶還需要提供一個(gè)595 的句柄。handle 需要保存到設(shè)備中:

注意,由于句柄往往需要通過(guò)動(dòng)態(tài)的調(diào)用實(shí)例初始化函數(shù)獲得,比如,HC595 的句柄可通過(guò)如下語(yǔ)句獲得:

而設(shè)備信息往往在系統(tǒng)啟動(dòng)后不會(huì)改變,可以定義為常量,因此,handle 往往由用戶單獨(dú)提供,不存放在設(shè)備信息中。

顯然,在使用GPIO 控制LED 前,需要完成設(shè)備中各成員的賦值,并熄滅所有LED,此外,在初始化完成后,還需要將具體的LED 設(shè)備添加到系統(tǒng)中。這些工作通常在驅(qū)動(dòng)的初始化函數(shù)中完成,初始化函數(shù)的原型為:

其中, p_dev 為指向am_led_hc595_dev_t 類(lèi)型實(shí)例的指針, p_info 為指向am_led_hc595_info_t 類(lèi)型實(shí)例信息的指針,其調(diào)用形式如下:

初始化函數(shù)的的實(shí)現(xiàn)詳見(jiàn)程序清單8.15。

程序清單8.15 初始化函數(shù)實(shí)現(xiàn)(HC595 控制LED)

首先將緩存中的值設(shè)置為使所有LED 熄滅的值,然后使用am_hc595_send()將緩存中的值輸出,使所有LED 處于熄滅狀態(tài)。最后,通過(guò)am_led_dev_add()函數(shù),將具體的LED 設(shè)備添加到了系統(tǒng)之中。

在添加LED 設(shè)備時(shí),LED 的 ID 信息直接使用了設(shè)備信息中的ID 信息,抽象方法的實(shí)現(xiàn)使用了__g_led_hc595_drv_funcs 中實(shí)現(xiàn)的方法(其定義詳見(jiàn)程序清單8.5),p_cookie 直接設(shè)置為了指向設(shè)備自身的指針,正因?yàn)槿绱?,在抽象方法的?shí)現(xiàn)中,p_cookie 參數(shù)即為指向設(shè)備自身的指針,可以通過(guò)p_cookie 得到具體設(shè)備相關(guān)的信息,如HC595 句柄,HC595 緩存等,進(jìn)而實(shí)現(xiàn)LED 的相關(guān)操作,完善程序清單8.5 中實(shí)現(xiàn)的抽象方法詳見(jiàn)程序清單8.16。

程序清單8.16 抽象方法的實(shí)現(xiàn)(HC595 控制LED)

在抽象方法的實(shí)現(xiàn)中,首先通過(guò)類(lèi)型強(qiáng)制轉(zhuǎn)換將p_cookie 轉(zhuǎn)換為指向具體設(shè)備的指針。然后通過(guò)它找到相關(guān)的信息,進(jìn)而實(shí)現(xiàn)LED 的相關(guān)操作。為了便于查閱,如程序清單8.17所示展示了LED 設(shè)備接口文件am_led_hc595.h 的內(nèi)容。

程序清單8.17 am_led_hc595.h 文件內(nèi)容

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 可編程邏輯
    +關(guān)注

    關(guān)注

    7

    文章

    523

    瀏覽量

    44504
  • 通用接口
    +關(guān)注

    關(guān)注

    0

    文章

    2

    瀏覽量

    9714

原文標(biāo)題:周立功:深入理解AMetal——LED 通用接口

文章出處:【微信號(hào):Zlgmcu7890,微信公眾號(hào):周立功單片機(jī)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    面向AMetal框架與接口編程原理和技巧

    面向AMetal框架與接口編程(上)》一書(shū)對(duì)AMetal框架進(jìn)行了詳細(xì)介紹,通過(guò)閱讀這本書(shū),你可以學(xué)到高度復(fù)用的軟件設(shè)計(jì)原則和面向接口
    的頭像 發(fā)表于 10-24 18:15 ?6397次閱讀
    <b class='flag-5'>面向</b>AMetal框架與<b class='flag-5'>接口</b>的<b class='flag-5'>編程</b>原理和技巧

    面向ametal框架與接口編程ametal uart總線

    面向AMetal框架與接口編程(上)》一書(shū)對(duì)AMetal框架進(jìn)行了詳細(xì)介紹,通過(guò)閱讀這本書(shū),你可以學(xué)到高度復(fù)用的軟件設(shè)計(jì)原則和面向接口
    的頭像 發(fā)表于 11-06 06:55 ?6421次閱讀
    <b class='flag-5'>面向</b>ametal框架與<b class='flag-5'>接口</b>的<b class='flag-5'>編程</b>ametal uart總線

    面向通用接口編程之溫度采集接口和鍵盤(pán)知識(shí)分享

    第七章為面向通用接口編程,本文內(nèi)容為7.4 溫度采集接口、7.5 鍵盤(pán)。
    的頭像 發(fā)表于 11-16 03:20 ?4609次閱讀
    <b class='flag-5'>面向</b><b class='flag-5'>通用</b><b class='flag-5'>接口</b>的<b class='flag-5'>編程</b>之溫度采集<b class='flag-5'>接口</b>和鍵盤(pán)知識(shí)分享

    學(xué)習(xí)數(shù)碼管,面向通用接口編程的基礎(chǔ)

    面向AMetal框架與接口編程(上)》一書(shū)對(duì)AMetal框架進(jìn)行了詳細(xì)介紹,通過(guò)閱讀這本書(shū),你可以學(xué)到高度復(fù)用的軟件設(shè)計(jì)原則和面向接口
    的頭像 發(fā)表于 11-17 07:05 ?6457次閱讀
    學(xué)習(xí)數(shù)碼管,<b class='flag-5'>面向</b><b class='flag-5'>通用</b><b class='flag-5'>接口</b><b class='flag-5'>編程</b>的基礎(chǔ)

    溫度傳感器通用接口應(yīng)用案例分析

    對(duì)AMetal框架進(jìn)行了詳細(xì)介紹,通過(guò)閱讀這本書(shū),你可以學(xué)到高度復(fù)用的軟件設(shè)計(jì)原則和面向接口編程開(kāi)發(fā)思想,
    的頭像 發(fā)表于 01-19 10:14 ?1.5w次閱讀
    溫度傳感器<b class='flag-5'>通用</b><b class='flag-5'>接口</b>應(yīng)用案例分析

    應(yīng)用面向對(duì)象編程SoC原則的典型示例

    周立功教授新書(shū)《面向AMetal框架與接口編程(上)》對(duì)AMetal框架進(jìn)行了詳細(xì)介紹,通過(guò)閱讀這本書(shū),你可以學(xué)到高度復(fù)用的軟件設(shè)計(jì)原則和面向接口
    的頭像 發(fā)表于 02-05 09:36 ?1.1w次閱讀
    應(yīng)用<b class='flag-5'>面向</b>對(duì)象<b class='flag-5'>編程</b>SoC原則的典型示例

    如何理解軟件設(shè)計(jì)原則和面向接口編程開(kāi)發(fā)思想

    面向通用接口編程,雖然面向接口編程簡(jiǎn)單易懂,但無(wú)
    的頭像 發(fā)表于 01-22 09:11 ?1.1w次閱讀

    面向對(duì)象的思想讓裸編程帶上靈魂

    告訴我:寫(xiě)好的程序不是如何去完成代碼,而是如何去組織代碼,是如何組織,不是組織。上位機(jī)中面向對(duì)象的編程思想,就是一個(gè)非??扇〉?b class='flag-5'>思想面向對(duì)
    發(fā)表于 11-24 10:00

    LabVIEW面向對(duì)象之學(xué)習(xí)路線圖

    眾所周知,面向對(duì)象的程序設(shè)計(jì)是一種設(shè)計(jì)思想,它不依托于某種編程語(yǔ)言。C++、C#、LabVIEW都可以使用這種模式進(jìn)行編程。同樣的,
    發(fā)表于 07-01 12:13

    談?wù)?b class='flag-5'>面向對(duì)象編程

    工業(yè)控制系統(tǒng)的PLC程序中也可以采用這種設(shè)計(jì)思想,雖然我們無(wú)法實(shí)現(xiàn)面向對(duì)象的很多優(yōu)秀特點(diǎn)如“繼承”,甚至于它根本就不具備面向對(duì)象編程語(yǔ)言的特點(diǎn),但
    發(fā)表于 09-08 07:47

    FPGA開(kāi)發(fā)流程及編程思想

    FPGA開(kāi)發(fā)流程及編程思想,好東西,喜歡的朋友可以下載來(lái)學(xué)習(xí)。
    發(fā)表于 01-18 15:17 ?31次下載

    面向對(duì)象編程——OO思想

    周立功教授數(shù)年之心血之作《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》以及《面向AMetal框架與接口編程(上)》,電子版已無(wú)償性分享到電子工程師與高校群體,書(shū)本內(nèi)容公開(kāi)后,在電子行業(yè)掀起一片學(xué)習(xí)熱潮。
    的頭像 發(fā)表于 09-27 10:20 ?8187次閱讀
    <b class='flag-5'>面向</b>對(duì)象<b class='flag-5'>編程</b>——OO<b class='flag-5'>思想</b>

    面向接口編程——平臺(tái)技術(shù)、開(kāi)關(guān)量信號(hào)

    面向AMetal框架與接口編程(上)》一書(shū)對(duì)AMetal框架進(jìn)行了詳細(xì)介紹,通過(guò)閱讀這本書(shū),你可以學(xué)到高度復(fù)用的軟件設(shè)計(jì)原則和面向接口
    的頭像 發(fā)表于 10-20 14:55 ?4633次閱讀

    面向AMetal框架和接口編程

    面向AMetal框架和接口編程
    發(fā)表于 11-23 15:22 ?8次下載

    封裝變化與面向接口編程

    是封裝變化和面向接口編程兩個(gè)基本的面向對(duì)象設(shè)計(jì)思想具體應(yīng)用,其用意是針對(duì)一組算法,將每個(gè)算法封裝到具有共同
    發(fā)表于 11-28 15:04 ?7402次閱讀
    封裝變化與<b class='flag-5'>面向</b><b class='flag-5'>接口</b><b class='flag-5'>編程</b>