周立功教授新書《面向AMetal框架與接口的編程(上)》,對(duì)AMetal框架進(jìn)行了詳細(xì)介紹,通過閱讀這本書,你可以學(xué)到高度復(fù)用的軟件設(shè)計(jì)原則和面向接口編程的開發(fā)思想,聚焦自己的“核心域”,改變自己的編程思維,實(shí)現(xiàn)企業(yè)和個(gè)人的共同進(jìn)步。
第八章為深入理解AMetal,本文內(nèi)容為8.3 蜂鳴器接口和8.4 溫度采集接口。
8.3 蜂鳴器接口
>>> 8.3.1 定義接口
1. 接口命名
由于操作的對(duì)象是蜂鳴器(buzzer),因此,接口命名以“am_buzzer_”作為前綴。對(duì)于蜂鳴器,基本的操作是打開和關(guān)閉蜂鳴器,可定義相應(yīng)的兩個(gè)接口名為:
-
am_buzzer_on
-
am_buzzer_off
特別地,在一些應(yīng)用場(chǎng)合,還需要類似蜂鳴器“嘀一聲”這樣的操作,即鳴叫一定的時(shí)間后自動(dòng)停止??梢远x其接口名為:
-
am_buzzer_beep
-
am_buzzer_beep_async
這里定義了兩個(gè)接口,都是用于蜂鳴器鳴叫指定的時(shí)間,二者的區(qū)別在于函數(shù)返回的時(shí)機(jī)不同。am_buzzer_beep 會(huì)等待鳴叫結(jié)束后返回,am_buzzer_beep_async 不會(huì)等待,函數(shù)立即返回,蜂鳴器鳴叫指定時(shí)間后自動(dòng)停止。
顯然,對(duì)于am_buzzer_beep_async 接口,在最開始的蜂鳴器接口設(shè)計(jì)中,很可能是不會(huì)想到的,該接口是在大量實(shí)際應(yīng)用中得出的,由于在一些特殊的應(yīng)用場(chǎng)景,不希望程序被阻塞,因此,需要提供am_buzzer_beep_async 這樣的異步接口。
2. 接口參數(shù)
在LED 通用接口的設(shè)計(jì)中,由于在一個(gè)系統(tǒng)中,可能存在多個(gè)LED,這就必須使用某種方法區(qū)分不同的LED,如使用了唯一ID 號(hào)led_id 表示來區(qū)分系統(tǒng)中的多個(gè)LED。按照這種邏輯,是否也需要一個(gè)buzzer_id 來區(qū)分不同的蜂鳴器呢?
蜂鳴器的功能單一,是一種發(fā)聲器件,在一個(gè)具體應(yīng)用中,發(fā)聲器件往往只有一個(gè),沒有必要使用多個(gè)蜂鳴器。因此,蜂鳴器可以看做系統(tǒng)的一個(gè)單實(shí)例設(shè)備,基于此,也就無需使用類似于buzzer_id 這樣的參數(shù)來區(qū)分多個(gè)蜂鳴器了,對(duì)于打開和關(guān)閉蜂鳴器的接口,則無需任何參數(shù),即:
-
am_buzzer_on(void);
-
am_buzzer_off(void);
特別地,對(duì)于am_buzzer_beep 和am_buzzer_beep_async 接口,雖無需參數(shù)來區(qū)分多個(gè)蜂鳴器,但由于其功能是鳴叫一定的時(shí)間,因此,還需要一個(gè)用于指定鳴叫時(shí)長(zhǎng)的參數(shù)。
-
am_buzzer_beep(uint32_t ms);
-
am_buzzer_beep_async (uint32_t ms);
其中,ms 用于指定鳴叫時(shí)長(zhǎng),單位為毫秒。
3. 返回值
接口無特殊說明,直接將所有接口的返回值定義為int 類型的標(biāo)準(zhǔn)錯(cuò)誤號(hào)?;诖?,蜂鳴器控制接口的完整定義詳見表8.5。
表8.5 蜂鳴器通用接口(am_buzzer.h)
其對(duì)應(yīng)的類圖詳見圖8.8。
圖8.8 蜂鳴器接口類圖
>>> 8.3.2 實(shí)現(xiàn)接口
1. 抽象的蜂鳴器設(shè)備類
蜂鳴器共計(jì)4 個(gè)通用接口,其中,am_buzzer_beep()和am_buzzer_beep_async()接口可以直接基于am_buzzer_on()和am_buzzer_off()接口實(shí)現(xiàn),am_buzzer_beep()的實(shí)現(xiàn)詳見程序清單8.24。
程序清單8.24 am_buzzer_beep()的實(shí)現(xiàn)
程序中,首先使用am_buzzer_on()打開蜂鳴器,若打開蜂鳴器失?。ǚ祷刂禐樨?fù)數(shù)),則直接返回相應(yīng)的錯(cuò)誤號(hào),若打開成功,則使用am_mdelay()延時(shí)指定的時(shí)間,最后關(guān)閉蜂鳴器。對(duì)于am_buzzer_beep_async()接口,其需要立即返回,不能在函數(shù)內(nèi)部直接使用延時(shí)函數(shù),可以基于軟件定時(shí)器實(shí)現(xiàn),范例程序詳見程序清單8.25。
程序清單8.25 am_buzzer_beep_async()的范例程序
程序中,首先使用am_buzzer_on()打開蜂鳴器,若打開蜂鳴器失?。ǚ祷刂禐樨?fù)數(shù)),則直接返回相應(yīng)的錯(cuò)誤號(hào),若打開成功,則啟動(dòng)軟件定時(shí)器,定時(shí)時(shí)間為指定的鳴叫時(shí)間,啟動(dòng)定時(shí)器后,函數(shù)立即返回。軟件定時(shí)器定時(shí)時(shí)間到后,需要調(diào)用自定義回調(diào)函數(shù)__beep_timer_callback(),在回調(diào)函數(shù)中,關(guān)閉了軟件定時(shí)器和蜂鳴器,鳴叫結(jié)束。
顯然,軟件定時(shí)器在使用前,需要初始化,以將__beep_timer_callback()函數(shù)作為其定時(shí)時(shí)間到后的回調(diào)函數(shù),如:
初始化語句放在哪里呢?這里僅僅展示了使用軟件定時(shí)器實(shí)現(xiàn)am_buzzer_beep_async()函數(shù)的范例,后文再介紹初始化軟件定時(shí)器的合適時(shí)機(jī)。
由于am_buzzer_beep()和am_buzzer_beep_async()接口可以直接基于am_buzzer_on()和am_buzzer_off()實(shí)現(xiàn),因此實(shí)現(xiàn)蜂鳴器接口的核心是實(shí)現(xiàn)am_buzzer_on()和am_buzzer_off()接口,按照LED 或HC595 的設(shè)計(jì)方法,可以抽象對(duì)應(yīng)的兩個(gè)方法。即:
雖然按照這種設(shè)計(jì)方法是完全可行的,但是考慮到on 和off 是一組相互對(duì)稱的接口,功能是同屬一類的,具有很大的相似性,因此,可以僅抽象一個(gè)方法,使用一個(gè)布爾類型的參數(shù)區(qū)分操作是打開還是關(guān)閉,比如:
可見,定義抽象方法并不一定是原封不動(dòng)的按照接口定義抽象方法,可以作適當(dāng)?shù)恼{(diào)整,只要基于抽象方法,能夠?qū)崿F(xiàn)通用接口即可。
雖然只有一個(gè)抽象方法,但是為了保證結(jié)構(gòu)的統(tǒng)一,也為了方便后續(xù)擴(kuò)展(如新增抽象方法等),往往還是將抽象方法放到一個(gè)虛函數(shù)表中。即:
類似地,將抽象方法和p_cookie 定義在一起,即為抽象的蜂鳴器設(shè)備。如:
在前面實(shí)現(xiàn)am_buzzer_beep_async()接口時(shí),使用到了軟件定時(shí)器,顯然,軟件定時(shí)器是用于實(shí)現(xiàn)一個(gè)蜂鳴器鳴叫功能的,是與蜂鳴器設(shè)備相關(guān)的,其不應(yīng)定義為全局變量,取而代之的是,直接定義在抽象設(shè)備結(jié)構(gòu)體中,即:
抽象設(shè)備中定義的抽象方法需要由具體的蜂鳴器設(shè)備來完成,am_buzzer_on()和am_buzzer_off()接口則可以直接基于抽象方法實(shí)現(xiàn)。
在定義蜂鳴器接口時(shí),由于蜂鳴器是單實(shí)例設(shè)備(系統(tǒng)中只有一個(gè)),因此沒有在接口中定義區(qū)分蜂鳴器對(duì)象的參數(shù),如ID 號(hào)或者句柄參數(shù)等,那么,在實(shí)現(xiàn)接口時(shí),如何找到相應(yīng)的設(shè)備呢?由于在系統(tǒng)中只有一個(gè)蜂鳴器設(shè)備,因此,可以直接使用一個(gè)全局變量來指向蜂鳴器設(shè)備,am_buzzer_on()和am_buzzer_off()的實(shí)現(xiàn)詳見程序清單8.26。
程序清單8.26 am_buzzer_on 和am_buzzer_off ()的范例程序
其中,__gp_buzzer_dev 是指向蜂鳴器設(shè)備的指針,初始沒有任何有效的蜂鳴器設(shè)備,因此初始值為NULL。顯然,要正常使用蜂鳴器,就必須使__gp_buzzer_dev 指向有效的蜂鳴器設(shè)備,這就需要由具體蜂鳴器設(shè)備實(shí)現(xiàn)pfn_buzzer_set 抽象方法。
為了完成__gp_buzzer_dev 的賦值,需要定義一個(gè)設(shè)備注冊(cè)接口,用于向系統(tǒng)中注冊(cè)一個(gè)有效蜂鳴器設(shè)備:
其中,為了方便向系統(tǒng)中添加一個(gè)蜂鳴器設(shè)備時(shí),避免直接操作蜂鳴器設(shè)備的各個(gè)成員,將需要賦值的成員通過參數(shù)傳遞給接口函數(shù)。其實(shí)現(xiàn)詳見程序清單8.27。
程序清單8.27 向系統(tǒng)中添加蜂鳴器設(shè)備
該程序首先判定參數(shù)的有效性,然后完成了抽象設(shè)備中抽象方法和p_cookie 賦值,接著給全局變量__gp_buzzer_dev 的賦值,使其指向有效的蜂鳴器設(shè)備,最后,初始化了抽象設(shè)備中的軟件定時(shí)器,便于實(shí)現(xiàn)異步的蜂鳴器鳴叫接口,由此可見,軟件定時(shí)器的初始化操作是在添加一個(gè)蜂鳴器設(shè)備時(shí)完成的。
顯然,接下來,就需要基于抽象的蜂鳴器設(shè)備派生具體的蜂鳴器設(shè)備,在具體的蜂鳴器設(shè)備中,完成抽象方法pfn_buzzer_set 的實(shí)現(xiàn),并使用am_buzzer_dev_register()接口向系統(tǒng)中添加一個(gè)蜂鳴器設(shè)備,使得用戶可以使用蜂鳴器通用接口操作到具體有效的蜂鳴器。
為了便于查閱,如程序清單8.28 所示展示了蜂鳴器設(shè)備接口文件(am_buzzer_dev.h)的內(nèi)容。其對(duì)應(yīng)的類圖詳見圖8.9。
程序清單8.28 am_buzzer_dev.h 文件內(nèi)容
圖8.9 抽象的蜂鳴器設(shè)備類
2. 具體的蜂鳴器設(shè)備類
以使用PWM 輸出控制蜂鳴器發(fā)聲為例,簡(jiǎn)述具體蜂鳴器設(shè)備的實(shí)現(xiàn)方法。首先應(yīng)該基于抽象設(shè)備類派生一個(gè)具體的設(shè)備類,其類圖詳見圖8.10,可直接定義具體的蜂鳴器設(shè)備類,如:
圖8.10 具體的蜂鳴器設(shè)備類
am_buzzer_pwm_dev_t 即為具體的蜂鳴器設(shè)備類。具有該類型后,即可使用該類型定義一個(gè)具體的蜂鳴器設(shè)備實(shí)例,即:
特別地,由于蜂鳴器是單實(shí)例設(shè)備,不能夠使用該類型定義多個(gè)實(shí)例,因此,可以直接在具體設(shè)備實(shí)現(xiàn)的文件內(nèi)部定義一個(gè)蜂鳴器設(shè)備實(shí)例,無需用戶使用該類型自定義設(shè)備實(shí)例?;诖?,am_buzzer_pwm_dev_t 類型無需開放給用戶,可以直接定義在.c 文件中,由于am_buzzer_pwm_dev_t 類型無需開放給用戶,僅內(nèi)部使用,因此可以修改類型名為雙下劃線“__”開頭,如在am_buzzer_pwm.c 文件中定義設(shè)備類型以及對(duì)應(yīng)的設(shè)備實(shí)例如下:
在使用PWM 輸出控制蜂鳴器時(shí),需要知道PWM 的句柄,通道號(hào)等相關(guān)信息,這些信息需要保存在設(shè)備中,因此更新設(shè)備類型的定義如下:
顯然,這些成員需要初始化后才能使用,定義初始化函數(shù)的原型為:
其中,pwm_handle 為標(biāo)準(zhǔn)的PWM 服務(wù)句柄,chan 為PWM 通道號(hào),duty_ns 和period_ns分別指定了輸出PWM 波形的脈寬和周期,決定了蜂鳴器鳴叫的響度和頻率,比如,AM824-Core 板載的蜂鳴器。
若使用SCT 輸出PWM,由于PIO0_24 對(duì)應(yīng)SCT 的通道1,因此初始話函數(shù)的調(diào)用形式如下:
程序中,使用了am_lpc82x_sct0_pwm_inst_init()函數(shù)獲取到了PWM 句柄,使用了通道1,并設(shè)定輸出PWM 的周期為400000ns,即 2.5KHz (1000000000 / 400000),脈寬恰好為周期的一半,即輸出PWM 的占空比為50%。初始化函數(shù)的實(shí)現(xiàn)范例詳見程序清單8.29。
程序清單8.29 初始化函數(shù)實(shí)現(xiàn)范例
該程序首先判定了參數(shù)的有效性,然后完成了設(shè)備實(shí)例中相關(guān)成員的賦值,接著調(diào)用了am_buzzer_dev_register()函數(shù),將蜂鳴器設(shè)備添加到系統(tǒng)中,最后配置了PWM 輸出通道的脈寬和周期。添加設(shè)備時(shí),將p_funcs 賦值為&__g_buzzer_pwm_drv_funcs,p_cookie 賦值為具體設(shè)備的地址,即p_cookie 指向了設(shè)備自身。__g_buzzer_pwm_drv_funcs 中包含了抽象方法的具體實(shí)現(xiàn),完整定義詳見程序清單8.30。
程序清單8.30 抽象方法的實(shí)現(xiàn)
為了便于查閱,如程序清單8.31 所示展示了蜂鳴器設(shè)備接口文件(am_buzzer_pwm.h)的內(nèi)容。
程序清單8.31 am_buzzer_pwm.h 文件內(nèi)容
由此可見,與其它具體設(shè)備的接口文件(詳見程序清單8.14、程序清單8.17 和程序清單8.23)相比,不同的是,其沒有包含具體設(shè)備類型的定義,初始化接口的第一個(gè)參數(shù),也不是指向具體設(shè)備的指針。這是由于蜂鳴器是單實(shí)例設(shè)備,系統(tǒng)中最多只能定義一個(gè),因此直接在實(shí)現(xiàn)文件的內(nèi)部完成了設(shè)備實(shí)例的定義,相關(guān)類型無需開放給用戶。同理,由于是單實(shí)例設(shè)備,初始化函數(shù)初始化的必然是文件內(nèi)部定義的設(shè)備實(shí)例,無需額外使用指向設(shè)備的指針指定要初始化的設(shè)備。
至此,詳細(xì)介紹了LED 通用接口、HC595 接口和蜂鳴器接口,它們代表了AMetal 中典型的3 種類型的設(shè)備接口。
-
LED 通用接口:使用唯一ID 區(qū)分不同設(shè)備;
-
HC595 接口:使用句柄區(qū)分不同的設(shè)備,句柄本質(zhì)上是指向設(shè)備的指針;
-
蜂鳴器接口:不使用任何參數(shù)區(qū)分不同設(shè)備,是一種單實(shí)例設(shè)備。
8.4 溫度采集接口
>>> 8.4.1 定義接口
1. 接口命名
由于操作的對(duì)象是溫度(temperature),為了縮短接口名,將temperature 縮寫為temp,因此,接口命名以“am_temp_”作為前綴。對(duì)于溫度采集,主要的操作就是讀取當(dāng)前溫度??啥x接口名為:
-
am_temp_read
2. 接口參數(shù)
顯然,一個(gè)系統(tǒng)中可能存在多個(gè)溫度傳感器,可以簡(jiǎn)單的使用句柄來區(qū)分不同的溫度傳感器,因此第一個(gè)參數(shù)的類型定義為溫度傳感器句柄,和HC595 設(shè)備類似,其應(yīng)該定義為指向抽象溫度設(shè)備的指針,假定抽象溫度設(shè)備的類型為am_temp_dev_t,則handle 的類型可以定義為:
讀取溫度接口的核心功能是返回當(dāng)前的溫度值,首先需要定義溫度值的類型,然后再確定溫度值的返回方式:通過返回值返回或通過出口參數(shù)返回。
通常使用1 位小數(shù)表示溫度值,比如,37.5℃,由此可見,溫度值需要使用小數(shù)表示,但要求的精度并不高,往往只會(huì)精確到小數(shù)點(diǎn)后一位,因此溫度值可以使用float 類型表示。
由于AMetal 運(yùn)行的實(shí)際硬件平臺(tái)往往是以低端的Cortex-M0、Cortex-M0+和Cortex-M3等作為內(nèi)核的芯片,這些芯片沒有硬件浮點(diǎn)運(yùn)算單元,浮點(diǎn)運(yùn)算的效率很低。因此,AMetal平臺(tái)中,不建議使用浮點(diǎn)類型,據(jù)此,可以使用整數(shù)表示溫度值,同時(shí),為了保證一定的精度,使用整數(shù)表示擴(kuò)大1000 倍后的溫度值。如實(shí)際溫度為37.5 度,則使用整數(shù)37500 表示。使用這種方法巧妙的避免了使用浮點(diǎn)類型,但也能保證實(shí)際溫度的精度為小數(shù)點(diǎn)后三位。由于溫度可能存在負(fù)值,因此,使用有符號(hào)的32 位數(shù)據(jù)來表示溫度值,即溫度值的類型定義為int32_t。
在通用接口中,返回值往往定義為int 類型的錯(cuò)誤號(hào),且使用負(fù)數(shù)表示出錯(cuò),顯然,如果使用返回值直接返回溫度,用戶將無法區(qū)分溫度為負(fù)數(shù)和讀取溫度出錯(cuò)的情況。為此,使用一個(gè)輸出參數(shù),用以返回溫度值,即定義一個(gè)int32_t 類型的指針作為輸出參數(shù):
-
am_temp_read(am_temp_handle_t handle, int32_t *p_temp)
其中,handle 為溫度傳感器的句柄,p_temp 為輸出參數(shù),用于返回當(dāng)前的溫度值,其表示的溫度值為實(shí)際溫度值的1000 倍。
3. 返回值
接口無特殊說明,直接將所有接口的返回值定義為int 類型的標(biāo)準(zhǔn)錯(cuò)誤號(hào)?;诖?,完整的讀取溫度接口的原型為:
其對(duì)應(yīng)的類圖詳見圖8.11。
圖8.11 溫度采集接口
>>> 8.4.2 實(shí)現(xiàn)接口
1. 抽象的溫度采集設(shè)備類
根據(jù)讀取溫度接口,可以定義相應(yīng)的抽象方法,并將其存放在一個(gè)虛函數(shù)表中:
類似地,將抽象方法和p_cookie 定義在一起,即為抽象的溫度采集設(shè)備。比如:
顯然,具體的溫度采集設(shè)備直接從抽象的溫度采集設(shè)備派生,然后由具體的溫度采集設(shè)備根據(jù)實(shí)際的硬件,實(shí)現(xiàn)讀取溫度的抽象方法。
在讀取溫度接口中,使用了handle 作為第一個(gè)參數(shù),其本質(zhì)上是指向設(shè)備的指針,讀取溫度接口可以直接調(diào)用抽象方法實(shí)現(xiàn),詳見程序清單8.32。
程序清單8.32 讀取溫度接口實(shí)現(xiàn)
在接口實(shí)現(xiàn)中,沒有與硬件相關(guān)的實(shí)現(xiàn)代碼,僅僅是簡(jiǎn)單的調(diào)用了抽象方法。抽象方法需要由具體的溫度采集設(shè)備來實(shí)現(xiàn)。類似地,由于讀取溫度接口的實(shí)現(xiàn)非常簡(jiǎn)單,往往將其實(shí)現(xiàn)直接以內(nèi)聯(lián)函數(shù)的形式存放在.h 文件中。
為便于查閱,如程序清單8.33 所示展示了抽象溫度采集設(shè)備接口文件(am_temp.h)的內(nèi)容,其包含了抽象溫度采集設(shè)備相關(guān)的抽象方法定義、類型定義和接口實(shí)現(xiàn),對(duì)應(yīng)的類圖詳見圖8.12。
圖8.12 抽象的溫度采集設(shè)備類
程序清單8.33 am_temp.h 文件內(nèi)容
2. 具體的溫度采集設(shè)備類
以使用LM75B 溫度傳感器實(shí)現(xiàn)溫度采集為例,簡(jiǎn)述具體溫度采集設(shè)備的實(shí)現(xiàn)方法。首先應(yīng)該基于抽象設(shè)備類派生一個(gè)具體的設(shè)備類,其類圖詳見圖8.13,可直接定義具體的溫度采集設(shè)備類。比如:
圖8.13 具體的溫度采集設(shè)備類
am_temp_lm75_t 為具體的溫度采集設(shè)備類,具有該類型后,即可使用該類型定義一個(gè)具體的溫度采集設(shè)備實(shí)例:
LM75B 是標(biāo)準(zhǔn)的I2C 從機(jī)器件,需要知道LM75B 的從機(jī)地址,才能使用I2C 總線讀取LM75B 中的溫度數(shù)據(jù)。由于從機(jī)地址與LM75 外部引腳電平相關(guān),因此LM75 的地址信息需要由用戶根據(jù)實(shí)際硬件電路設(shè)置。將需要由用戶提供的設(shè)備相關(guān)信息存放到一個(gè)新的設(shè)備信息結(jié)構(gòu)體類型中。比如:
當(dāng)使用AM824-Core 上板載的LM75B 時(shí),LM75B 的7 位I2C 從機(jī)地址為1001A2A1A0,由于A0、A1、A2 均與地連接為低電平,因此可得板載LM75B 的7 位從機(jī)地址為1001000,即:0x48?;诖?,板載LM75B 對(duì)應(yīng)的設(shè)備實(shí)例信息可以定義如下:
同理,在設(shè)備類中需要維持一個(gè)指向設(shè)備信息的指針。此外,由于使用I2C 接口從LM75B中讀取溫度數(shù)據(jù)時(shí),LM75B 相當(dāng)于是一個(gè)I2C 從設(shè)備,為了使用I2C 接口與之通信,需要為L(zhǎng)M75B 定義一個(gè)與之對(duì)應(yīng)的I2C 從設(shè)備,新增兩個(gè)成員,完整的溫度采集設(shè)備定義即為:
顯然,在使用I2C 接口從LM75B 中讀取溫度之前,需要完成設(shè)備中各成員的賦值,這些工作通常在驅(qū)動(dòng)的初始化函數(shù)中完成,定義初始化函數(shù)的原型為:
-
p_lm75 為指向am_temp_lm75_t 類型實(shí)例的指針;
-
p_devinfo 為指向am_temp_lm75_info_t 類型實(shí)例信息的指針。
handle 為I2C 句柄,便于使用I2C 接口讀取溫度數(shù)據(jù),初始化函數(shù)的返回值即為溫度采集設(shè)備句柄,其調(diào)用形式如下:
返回值即為溫度采集設(shè)備的句柄,可以作為溫度采集接口的第一個(gè)參數(shù)(handle)的實(shí)參,初始化函數(shù)的實(shí)現(xiàn)范例詳見程序清單8.34。
程序清單8.34 初始化函數(shù)實(shí)現(xiàn)范例
該程序首先建立了標(biāo)準(zhǔn)的I2C 從設(shè)備,便于后續(xù)使用I2C 接口讀取數(shù)據(jù),然后初始化了p_info 成員,接著完成了抽象溫度采集設(shè)備中p_funcs 和p_cookie 的賦值,最后返回設(shè)備地址作為用戶操作溫度采集設(shè)備的句柄。pfuncs 賦值為了&__g_temp_lm75_drv_funcs,其中包含了讀取溫度抽象方法的具體實(shí)現(xiàn),完整定義詳見程序清單8.35。
程序清單8.35 抽象方法的實(shí)現(xiàn)
在讀取溫度的實(shí)現(xiàn)函數(shù)__temp_lm75_read()中,首先使用I2C 接口從LM75B 中讀取出當(dāng)前的實(shí)際溫度值,詳見程序清單8.35(6);接著對(duì)數(shù)據(jù)進(jìn)行簡(jiǎn)單處理,兩字節(jié)數(shù)據(jù)整合為一個(gè)16 位有符號(hào)的溫度值temp,詳見程序清單8.35(10 ~ 11);最后,確認(rèn)p_temp 指針有效后,將temp 乘以125,再除以32,最終的結(jié)果作為輸出的溫度值。
為什么將temp 乘以125,然后再除以32 呢?這是因?yàn)長(zhǎng)M75B 中直接讀取的數(shù)據(jù)時(shí)實(shí)際溫度值的256倍,即:實(shí)際溫度= temp / 256。
而溫度采集接口需要返回的溫度值是實(shí)際溫度的1000 倍,即:
* p _ temp=實(shí)際溫度*1000 = temp/ 256*1000 = temp*1000/ 256
化簡(jiǎn)可得:
為了便于查閱,如程序清單8.36 所示展示了具體溫度采集設(shè)備(LM75B)接口文件(am_temp_lm75.h)的內(nèi)容。
程序清單8.36 am_temp_lm75.h 文件內(nèi)容
-
蜂鳴器
+關(guān)注
關(guān)注
12文章
889瀏覽量
45843 -
周立功
+關(guān)注
關(guān)注
38文章
130瀏覽量
37558 -
LM75B
+關(guān)注
關(guān)注
0文章
5瀏覽量
9600 -
致遠(yuǎn)電子
+關(guān)注
關(guān)注
13文章
405瀏覽量
31259
原文標(biāo)題:周立功:深入理解AMetal——蜂鳴器接口和溫度采集接口
文章出處:【微信號(hào):Zlgmcu7890,微信公眾號(hào):周立功單片機(jī)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論