6.1 通用LED接口
AWorks提供了操作LED的通用接口,詳見表6.1。
表6.1 通用LED接口(aw_led.h)
1. 設置LED的狀態
設置LED狀態的函數原型為:
其中,id為LED編號,系統為每個LED都分配了一個唯一ID,通常都是從0開始順序為各個LED編號。如有2個LED,則LED的編號為0~1。布爾類型on參數表明是否點亮LED,若其值為AW_TRUE,則表示點亮LED;若其值為AW_FALSE,則表示熄滅LED。
aw_bool_t類型是AWorks在aw_types.h文件中自定義的布爾類型,使用該類型定義的數據,其值只能為真(AW_TRUE)或假(AW_FALSE)。
點亮編號為0的LED范例程序詳見程序清單6.1。
程序清單6.1 使用aw_led_set()點亮LED的范例程序
熄滅編號為0的LED范例程序詳見程序清單6.2。
程序清單6.2 使用aw_led_set()熄滅LED范例程序
函數的返回值表示本次操作的結果,其類型為aw_err_t,該類型在aw_errno.h文件中定義的一個有符號的整數類型。若接口返回值的類型為aw_err_t,則具有通用的含義:
-
若返回值為AW_OK(常量宏,值為0),則表示操作成功;
-
若返回值為負值,則表示操作失敗,失敗的原因通過返回值確定;
-
若返回值為正數,則具體含義由接口定義,無特殊說明時,表明不會返回正數。
實際上AW_OK是在aw_common.h文件中定義的常量宏,其值為0,定義如下:
當返回負值時,則表示操作失敗,具體失敗的原因可根據返回值查找aw_errno.h文件中定義的錯誤號,通過錯誤號的含義即可確定失敗的原因,詳見表6.2。
表6.2 常見錯誤號的含義(aw_errno.h)
假設硬件只有兩個LED,其操作編號為100的LED,由于LED不存在,將返回-AW_ENODEV,表示設備不存在。注意:AW_ENODEV的前面有一個負號,操作無效ID的范例程序詳見程序清單6.3。
程序清單6.3 操作無效ID的范例程序
通常操作LED,只要LED編號是有效的,這操作均會成功,其返回值為AW_OK。
2. 點亮LED
點亮LED的函數原型為:
其中,id為LED編號,函數的返回值為標準錯誤號,點亮編號為0的LED范例程序詳見程序清單6.4。
程序清單6.4 aw_led_on()范例程序
3. 熄滅LED
熄滅LED的函數原型為:
其中,id為LED編號,函數的返回值為標準錯誤號,熄滅編號為0的LED范例程序詳見程序清單6.5。
程序清單6.5 aw_led_off()范例程序
4. 翻轉LED的狀態
翻轉LED的狀態就是使LED由點亮狀態轉變為熄滅狀態或由熄滅狀態轉變為點亮狀態,其函數原型為:
其中,id為LED編號,函數的返回值為標準錯誤號,通過翻轉LED狀態的接口可以實現LED閃爍,其范例程序詳見程序清單6.6。
程序清單6.6 aw_led_toggle()范例程序
為了展示接口的使用方法,該程序使用了3種方式實現LED的閃爍,詳見程序清單6.7。
程序清單6.7 LED閃爍范例程序
6.2 通用鍵盤接口
AWorks實現了一個輸入子系統架構,可以統一管理按鍵、鼠標、觸摸屏等外部輸入事件。這里以使用按鍵為例,講述輸入系統的使用方法。
對于鍵盤,無論是獨立鍵盤、矩陣鍵盤還是外接的外圍鍵盤管理芯片(如ZLG72128),均可以使用輸入系統進行管理。
對于用戶來講,要使用按鍵,即需要對外部輸入的按鍵事件進行處理,為此,需要向系統中注冊一個輸入事件處理器,該處理器中,包含了用戶自定義的事件處理函數,當有按鍵事件發生時,系統將自動回調事件處理器中的用戶函數。
AWorks提供了注冊輸入事件處理器的接口,其函數原型為:
其中,p_input_handler為指向輸入事件處理器的指針,pfn_cb為指向用戶自定義的輸入事件處理函數的指針,p_usr_data為按鍵處理函數的用戶參數。當輸入事件發生時,系統會回調pfn_cb指向的用戶處理函數,并將p_usr_data作為參數傳遞給用戶處理函數。
1. 輸入事件處理器
p_input_handler指向輸入事件處理器,其類型為:aw_input_handler_t,在
aw_input.h文件中定義,用戶無需關心該類型的具體定義,僅需使用該類型定義一個輸入事件處理器的實例。即:
其中,key_handler為用戶自定義的輸入事件處理器,其地址可以作為p_input_handler的實參傳遞。
2. 用戶自定義事件處理函數
pfn_cb指向用戶自定義的輸入事件處理函數,其類型aw_input_cb_t為事件處理函數的類型,其在aw_input.h文件中定義如下:
當輸入事件發生時,無論是按鍵事件,還是其它坐標事件,比如:鼠標、觸摸屏等。均會調用pfn_cb指針指向的函數,當該函數被調用時,p_input_data為輸入事件相關的數據,包含事件類型(區分按鍵事件或坐標事件,比如:鼠標、觸摸屏等)、按鍵編碼、坐標等信息,用戶可以根據這些數據作出相應的處理動作。p_usr_data為用戶自定義的參數,其值與注冊事件處理器時傳遞的p_usr_data參數一致,若不使用該參數,則可以在注冊事件處理器時,將p_usr_data參數的值設置為NULL。
p_input_data的類型為aw_input_event_t指針類型,該類型在aw_input.h文件中定義如下:
其本質上是一個結構體類型,僅包含一個數據成員,用于表示事件的類型,若為按鍵事件,則該值為AW_INPUT_EV_KEY;若為絕對事件(比如,觸摸屏),則該值為AW_INPUT_EV_ABS。
若p_input_data指向的數據中,ev_type的值為AW_INPUT_EV_KEY,則表示其指向的數據本質上是一個完整的按鍵事件數據,其類型為aw_input_key_data_t,該類型在aw_input.h文件中定義如下:
該類型的第一個數據成員為input_ev,其中包含了事件的具體類型。也正因為其第一個數據成員的類型為aw_input_event_t,系統才可以在回調用戶自定義的函數時,將aw_input_key_data_t類型的指針轉換為指向aw_input_event_t類型的指針使用。
key_code為按鍵編碼,用于區分系統中多個不同的按鍵。例如,系統中存在4個按鍵,則各個按鍵對應的編碼可能分別為:KEY_0、KEY_1、KEY_2、KEY_3。這些編碼都是在aw_input_code.h文件中使用宏的形式定義的。
key_state表示本次按鍵事件具體對應的按鍵狀態,用以區分按鍵事件是按下事件還是釋放事件。若該值不為0,則表示按鍵按下;否則,表示按鍵釋放。
基于此,為了獲取到更多的按鍵相關信息,比如:按鍵編碼、按鍵狀態(按下還是釋放)等??梢詫_input_data強制轉換為aw_input_key_data_t指針類型使用,詳見程序清單6.8。
程序清單6.8 根據輸入事件的類型使用數據
實際上,不同類型的輸入事件,其需要包含的數據是不同的,例如,對于觸摸屏事件,則需要包含橫坐標和縱坐標。為了統一各種不同類型的事件處理函數類型,將aw_input_event_t類型的數據作為所有事件實際數據類型的第一個成員。這樣,可以統一使用aw_input_event_t類型的指針指向實際的數據,以此統一事件處理函數的類型,用戶在事件處理函數中,通過查看事件類型,即可進一步將該指針強制轉換為指向實際數據類型的指針,使用其中更多的信息。
如圖6.1所示的類圖表示了這種關系,實際數據類型均是從基類派生而來的,aw_input_prt_data_t是指針型輸入事件,比如觸摸屏觸摸事件等,其包含了具體坐標信息。
圖6.1 各種類型的輸入事件對應的實際數據類圖
例如,使用一個按鍵(按鍵編碼為KEY_0)控制LED0,當按鍵按下時,則LED0點亮;當按鍵釋放后,則LED0熄滅,相應的按鍵處理函數詳見程序清單6.9。
程序清單6.9 按鍵處理函數范例程序
完成按鍵處理函數的定義后,函數名可作為參數傳遞給aw_input_handler_register()函數的pfn_cb形參。綜合范例程序詳見程序清單6.10。
程序清單6.10 注冊事件處理器范例程序
注冊按鍵處理器后,當按鍵按下或釋放時,均會調用注冊按鍵處理器時指定的回調函數,即程序清單6.10中的__key_process()函數。
若系統中存在多個按鍵,且各個按鍵的處理動作毫不相關,為了分離各個按鍵的處理代碼,可以注冊多個按鍵事件處理器,每個處理器負責處理一個或多個按鍵,范例程序詳見程序清單6.11。
程序清單6.11 注冊多個按鍵處理器范例程序
6.3 通用蜂鳴器接口
AWorks提供了操作蜂鳴器的通用接口,詳見表6.3。
表6.3 通用蜂鳴器接口(aw_buzzer.h)
1. 設置蜂鳴器的響度
該函數用于設置蜂鳴器鳴叫的響度,即控制蜂鳴器發聲的音量。其函數原型為:
beep_level即為鳴叫的響度,其值被量化為百分比,有效值為0 ~ 100。為0時表示靜音,為100時表示聲音最大。設置響度為80%的范例程序詳見程序清單6.12。
程序清單6.12 aw_buzzer_loud_set()范例程序
該接口僅用于設置蜂鳴器的響度,并不會使蜂鳴器立即發聲,必須調用aw_buzzer_on()或aw_buzzer_beep()接口,才能使蜂鳴器發聲。默認情況下,響度為0,因此,在調用相關接口使蜂鳴器鳴叫前,必須正確設置響度。
特別地,部分硬件不支持響度設置,響度是固定的,這種情況下,調用該接口是無效的,返回值為-AW_ENOTSUP(錯誤號,表示不支持)。
2. 打開蜂鳴器
打開蜂鳴器的函數原型為:
打開蜂鳴器,使蜂鳴器開始鳴叫的范例程序詳見程序清單6.13。
程序清單6.13 aw_buzzer_on()范例程序
打開蜂鳴器后,蜂鳴器開始鳴叫,若響度為0,將聽不到聲音。
3. 關閉蜂鳴器
關閉蜂鳴器的函數原型為:
關閉蜂鳴器,使蜂鳴器停止鳴叫的范例程序詳見程序清單6.14。
程序清單6.14 aw_buzzer_off()范例程序
4. 蜂鳴器鳴叫指定時間(同步)
該函數用于打開蜂鳴器,使蜂鳴器鳴叫指定時間后自動關閉,該函數會一直等到蜂鳴器鳴叫結束后返回。其函數原型為:
使蜂鳴器鳴叫50毫秒(“嘀”一聲)的范例程序詳見程序清單6.15。
程序清單6.15 aw_buzzer_beep()范例程序
注意,由于該函數會一直等到蜂鳴器鳴叫結束后才會返回,因此主程序調用該函數后,會阻塞50ms。
5.蜂鳴器鳴叫指定時間(異步)
該函數用于打開蜂鳴器,使蜂鳴器鳴叫指定時間后自動關閉,與aw_buzzer_beep()函數不同的是,該函數會立即返回,不會等待蜂鳴器鳴叫結束。其函數原型為:
使蜂鳴器鳴叫50毫秒(“嘀”一聲)的范例程序詳見程序清單6.16。
程序清單6.16 aw_buzzer_beep_async()范例程序
注意,由于該函數不會等待蜂鳴器鳴叫結束,因此,當調用該函數后,會立即返回,不會被阻塞。這是其與aw_buzzer_beep()接口的本質區別。
基于蜂鳴器通用接口,可以編寫一個簡易測試程序,按鍵按下,蜂鳴器鳴叫;按鍵釋放,蜂鳴器停止鳴叫。范例程序詳見程序清單6.17。
程序清單6.17 蜂鳴器使用范例程序
基于此,若需要實現一個按鍵按下,蜂鳴器“嘀”一聲的效果,按照上述示例,可以簡單修改事件處理函數,使用aw_buzzer_beep()函數實現“嘀”一聲的效果,范例程序詳見程序清單6.18.
程序清單6.18 事件處理函數修改(1)
實際測試會發現,上述程序并不能正常工作,不能觀察到預期的現象。這是由于aw_buzzer_beep()函數會阻塞調用者一定的時間,而按鍵事件回調函數是在中斷環境中運行的,中斷上下文不能被阻塞,因此,aw_buzzer_beep()接口不能夠直接在按鍵事件回調函數中使用。為了實現該應用,可以使用不阻塞的蜂鳴器鳴叫接口aw_buzzer_beep_async()替代,范例程序詳見程序清單6.19。
程序清單6.19 事件處理函數修改(2)
6.4 通用數碼管接口
AWorks提供了操作數碼管的通用接口,詳見表6.4。
表6.4 通用數碼管接口(aw_digitron_disp.h)
1. 設置段碼解碼函數
數碼管的各個段可以組合顯示出多種圖形,使用該函數可以自定義字符的解碼函數,其函數原型為:
其中,id表示設置數碼管顯示器的編號,這里的id指的是顯示器的編號,而不是數碼管的位索引,一個數碼管顯示器可以包含多位數碼管,比如,MiniPort-View顯示器,其包含兩位數碼管。系統中的數碼管顯示器通常從0開始編號,例如,系統中共計有3個數碼管顯示器,則id為0 ~ 2。絕大部分情況下,系統中僅有一個數碼管顯示器,此時,其id為0。
pfn_decode為函數指針,其指向的函數即為設置的解碼函數,解碼函數的參數為uint16_t類型的字符,返回值為uint16_t類型的編碼。
實際應用中,對于8段數碼管,字符'0' ~ '9'等都是有默認編碼的,為此,AWorks提供了默認的8段數碼管解碼函數,可以支持常見的字符'0' ~ '9'以及 'A' 、'B'、 'C' 、'D'、 'E'、 'F'等字符的解碼。其在aw_digitron_disp.h文件中聲明:
如無特殊需求,可以直接將該函數作為相應數碼管顯示器的字符解碼函數,將該函數作為pfn_decode的實參傳遞,范例程序詳見程序清單6.20。
程序清單6.20 aw_digitron_disp_decode_set()范例程序
若由于應用特殊需求,要求字符使用自定義的特殊編碼,例如,要使字符'O'的編碼為 0xFC,則可以自定義如下解碼函數:
然后將該函數作為pfn_decode的實參傳遞即可:
注意,對于一個數碼管顯示器,只能設置一個解碼函數。
2. 設置數碼管閃爍
該函數可以指定數碼管顯示器的某一位數碼管閃爍,其函數原型為:
其中,id為數碼管顯示器編號;index為數碼管索引,當一個數碼管顯示器存在多位數碼管時,使用index參數指定具體操作的數碼管的位置。如MiniPort-View有兩位數碼管,則兩個數碼管的索引分別為0和1;blink表示該位是否閃爍,若其值為AW_TRUE,則閃爍,反之,則不閃爍,默認情況下,所有數碼管均處于未閃爍狀態。如設置1號數碼管閃爍的范例程序詳見程序清單6.21。
程序清單6.21 aw_digitron_disp_blink_set()范例程序
3. 顯示指定的段碼圖形
該函數用于不經過解碼函數解碼,直接顯示段碼指定的圖形,可以靈活的顯示任意特殊圖形,其函數原型為:
其中,id為數碼管顯示器編號;index為數碼管索引;seg為顯示的段碼。如在8段數碼管上顯示字符'-',即需要g段點亮,對應的段碼為0x02(即:0000 0010),范例程序詳見程序清單6.22。
程序清單6.22 aw_digitron_disp_at()范例程序
4. 顯示單個字符
該函數用于在指定位置顯示一個字符,字符經過解碼函數解碼后顯示,若解碼函數不支持該字符,則不顯示任何內容,其函數原型為:
其中,id為數碼管顯示器編號,index為數碼管索引,ch為顯示的字符。比如,顯示字符'H'的范例程序詳見程序清單6.23。
程序清單6.23 aw_digitron_disp_char_at()范例程序
5. 顯示字符串
該函數用于從指定位置開始顯示一個字符串,其函數原型為:
其中,id為數碼管顯示器編號,index為顯示字符串的數碼管起始索引,即從該索引指定的數碼管開始顯示字符串,len指定顯示的長度,p_str指向需要顯示的字符串。
實際顯示的長度是len和字符串長度的較小值,若數碼管位數不夠,則多余字符不顯示。
如顯示字符"HELLO"的范例程序詳見程序清單6.24。
程序清單6.24 aw_digitron_disp_str()范例程序
若使用的是MiniPort-View,由于只存在兩個數碼管,因此最終只會顯示"HE"。
通常情況下,需要顯示一些數字,如顯示變量的值,此時,可以先將變量通過格式化字符串函數輸出到字符串緩沖區中,然后再使用aw_digitron_disp_str()函數顯示該字符串。比如,顯示一個變量i的值,范例程序詳見程序清單6.25。
程序清單6.25 使用aw_digitron_disp_str()顯示整數變量值的范例程序
其中,aw_snprintf()與標準C函數snprintf()函數功能相同,均用于格式化字符串到指定的緩沖區中,其函數原型為(aw_vdebug.h):
其與aw_kprintf()函數的區別是,aw_kprintf()將信息直接通過調試串口打印輸出,而aw_snprintf()函數將信息輸出到大小為sz的buf緩沖區中。
6. 顯示清屏
該函數用于顯示清屏,清除數碼管顯示器中的所有內容,其函數原型為:
其中,id為數碼管顯示器編號,范例程序詳見程序清單6.26。
程序清單6.26 aw_digitron_disp_clr()范例程序
7. 使能數碼管顯示
數碼管默認是處于使能狀態的,只有當被禁能后,才需要使用該函數重新使能。數碼管僅在使能狀態下才可以正常顯示。
該函數用于顯示清屏,清除數碼管顯示器中的所有內容,其函數原型為:
其中,id為數碼管顯示器編號,范例程序詳見程序清單6.27。
程序清單6.27 aw_digitron_disp_enable()范例程序
8. 禁能數碼管實現
數碼管默認處于使能狀態,可以正常顯示。清屏狀態下只是清空了數碼管顯示的內容,數碼管實際上還是處于工作狀態,對于動態掃描類數碼管,依然處于動態掃描狀態,需要消耗CPU資源。若長時間不使用數碼管顯示器,可以徹底關閉數碼管顯示器,關閉數碼管掃描,節省CPU資源,甚至是關閉數碼管的電源,降低系統功耗。關閉數碼管顯示器的函數原型為:
其中,id為數碼管顯示器編號,范例程序詳見程序清單6.28。
程序清單6.28 aw_digitron_disp_disable()范例程序
數碼管被禁能后,將不能再正常顯示,若需正常顯示,必須使用aw_digitron_disp_enable()接口重新使能數碼管。
基于數碼管通用接口,可以編寫一個簡易的60s倒計時程序,當倒計時還剩5s時,數碼管閃爍。范例程序詳見程序清單6.29。
程序清單6.29 倒計時應用程序實現
程序中,將應用程序使用的數碼管顯示器編號使用宏__DIGITRON_ID進行了定義,若一個系統中存在多個數碼管顯示器,則僅需修改該宏對應的宏值,就可以使該倒計時應用程序在不同的數碼管顯示器上運行。
6.5 通用傳感器接口
AWorks提供了通用的傳感器接口,適用于各式各樣的傳感器,例如,溫度、濕度、電壓、電流、壓強、加速度、角速度、光照傳感器等等。
在一個系統中,可能存在多種類型的傳感器,例如,溫度、濕度、電流、壓強等。同時,還可能存在多個同種類型的傳感器,例如,可能連接10個溫度傳感器以測試10個溫度檢測點的溫度。此外,部分傳感器可以采集多路信號,例如,溫濕度傳感器SHT11可以同時采集溫度和濕度。
為了實現對各式各樣的傳感器進行統一管理,在AWorks中,定義了“傳感器通道”的抽象概念,一個傳感器通道用于完成一路物理信號的采集。對于只能采集單一信號的傳感器,每個傳感器只能為系統提供一路傳感器通道,例如,LM75溫度傳感器僅能采集一路溫度信號;對于可以采集多路信號的傳感器,則每個傳感器可以為系統提供多路傳感器通道,例如,SHT11可以同時采集溫度和濕度,其可以為系統提供一路溫度傳感器通道和一路濕度傳感器通道。此外,也可能存在多個相同的傳感器,以便為系統提供多個同類型的的傳感器通道。
如此一來,一個系統中可能存在多個傳感器通道,為了區分各個傳感器通道,在AWorks中,為每個傳感器通道分配了一個唯一 id。例如,某一系統中存在溫度、加速度、角速度等多種傳感器,各傳感器通道對應的id分配范例詳見表6.5。
表6.5 傳感器通道id分配(僅作示意)
實際中,id 與具體硬件平臺相關,用戶應查看SDK中的用戶手冊,獲知系統中可用的傳感器通道資源,以正確使用各個傳感器通道。
對于應用程序來講,僅需通過id使用各個傳感器通道即可,無需關心這些通道具體是由哪個傳感器提供的。例如,某一應用需要采集一路溫度和一路濕度,底層硬件可以是一個SHT11溫濕度傳感器,也可以是一個溫度傳感器和一個濕度傳感器。
常用的傳感器接口詳見表6.6。
表6.6 通用傳感器接口(aw_sensor.h)
1. 獲取傳感器通道類型
傳感器通道有類型之分,不同的類型的傳感器通道采集的物理信號不同,不同物理信號具有不同的基本單位不同。例如,電壓的基本單位為伏特(V);電流的基本單位為安培(A);溫度的基本單位為℃。為便于使用,在AWorks中,將傳感器類型使用宏的形式進行了定義,常用的傳感器類型詳見表6.7。
表6.7 常用的傳感器類型定義(aw_sensor.h)
在AWorks中,提供了獲取傳感器通道類型的接口,其函數原型為:
其中,id為傳感器通道的編號。若函數返回值為非負數(>=0),則表示獲取傳感器類型成功,此時,返回值即為以AW_SENSOR_TYPE_ 為前綴的宏值;否則,表示獲取傳感器類型失敗,此時,返回值為標準錯誤碼,表示了獲取類型失敗的原因。例如,返回值為-AW_ENODEV時,表示id對應的傳感器通道不存在,沒有與之對應的傳感器設備。例如,判斷通道0是否為溫度傳感器的范例程序詳見程序清單6.30。
程序清單6.30 獲取傳感器通道類型的范例程序
2. 使能傳感器通道
在AWorks中,使用一個傳感器通道采集數據的一般流程為:
(1)使能通道;
(2)獲取數據(可以多次獲取);
(3)禁能通道,不再使用時可以禁能通道,以使傳感器進入最佳的低功耗狀態(若支持)。
AWorks為每一個步驟都提供了兩類接口:一類接口用于操作單個傳感器通道,該類接口適用于僅使用單個傳感器通道的應用程序;一類接口用于操作一組(多個)傳感器通道,該類接口適用于需要使用多個傳感器通道的應用程序。當應用需要使用多個傳感器通道時,建議使用操作一組(多個)傳感器通道的接口,而不是多次使用操作單個傳感器通道的接口,后者效率較低,影響系統性能。
在獲取數據前,必須使能傳感器通道,AWorks提供了兩類接口,分別用于使能單個傳感器通道和使能一組(多個)傳感器通道。
-
使能單個傳感器通道
使能單個傳感器通道的函數原型為:
其中,id為傳感器通道的編號。若函數返回值為AW_OK,則表示通道使能成功;否則,表示通道使能失敗,返回值為標準錯誤碼,可以據此判定失敗的原因。例如,返回值為-AW_ENODEV時,表示id對應的傳感器通道不存在。例如,使能通道0的范例程序詳見程序清單6.31。
程序清單6.31 使能單個傳感器通道的范例程序
-
使能一組(多個)傳感器通道
使能一組(多個)傳感器通道的函數原型為:
其中,p_ids為指向傳感器通道id列表的指針;num表示通道的數目,即id列表的大小;p_result指向用于存儲各個通道使能結果的緩存,緩存大小應該與num一致。其類型aw_sensor_val_t 為傳感器數據類型,其詳細定義詳見程序清單6.32。
程序清單6.32 aw_sensor_val_t類型定義(aw_sensor.h)
該類型的本意是表示一個傳感器數據,如電壓、電流、溫度等,當表示一個傳感器數據時,val和unit都有著特殊的含義,具體含義將在數據獲取接口中詳細介紹。當該類型使用于此時,unit的值無效,僅使用val值表示各個通道使能的結果,此時,val值即為標準錯誤碼,若其值為AW_OK,則表示相應的通道使能成功;否則,表示相應的通道使能失敗,例如,值為-AW_ENODEV時,表示對應通道不存在。
aw_sensor_group_enable()函數的返回值同樣為標準錯誤碼,若其值為AW_OK,則表示所有通道使能成功,此時,p_result中所有數據的val值均為AW_OK,因此,當返回值為AW_OK時,無需判斷p_result中的值即可斷定所有通道使能成功;否則,表示存在使能失敗的通道,此時,可以逐一檢查p_result中的值來判斷具體哪些通道使能成功,哪些通道使能失敗。使能一組通道(通道0、3、5、6、8、9)的范例程序詳見程序清單6.33。
程序清單6.33 使能一組(多個)傳感器通道的范例程序
3. 獲取傳感器數據
通道使能后,可以獲取傳感器中的數據, AWorks提供了兩類接口,分別用于獲取單個傳感器通道的數據和獲取一組(多個)傳感器通道的數據。
-
獲取單個傳感器通道的數據
該函數用于獲取單個傳感器通道的數據,其函數原型為:
其中,id為傳感器通道的編號,p_val為輸出參數,用以返回獲取到的傳感器值。函數返回值為標準錯誤碼,若其值為AW_OK,則表示數據獲取成功;否則,表示數據獲取失敗。
aw_sensor_val_t表示傳感器數據類型,回顧(首次定義詳見程序清單6.32)其定義如下:
其中,val為傳感器數值,unit表示了數據單位。
例如:
"M"(106,“兆”)、"k"(103,“千”),"m"(10-6,“毫”)等等,unit使用10的冪進行表示,例如,單位為"m",則unit的值為-3。
為了規范unit的使用,unit不可以為任意值,AWorks根據國際單位制(SI)定義的詞頭(比如:"m"、"μ"、"p"、"n"等等)對其可用取值進行了定義,詳見表6.8。
表6.8 uint可用取值
表中的最后一列即為unit的值,其值表示了10的冪,比如,-9表示的是10-9。單位符號區分大小寫,例如,"m"表示“毫”,對應10-3;而"M"表示“兆”,對應106。英文前綴表示在英文單詞中,通??梢栽谟嬃繂挝坏膯卧~前增加該前綴形成新的單詞,例如,長度單位米的英文單詞為:meter;而千米對應的單詞為:kilometer,這里列出英文單詞前綴,可以方便讀者理解宏值和單位符號的定義。中文讀音為該單位符號的一般讀法,括號內的字在不致混淆的情況下可以省略(通常均省略)。
傳感器val值的實際單位為將表中所示“單位符號”作為基本單位(基本單位與傳感器類型相關,詳見表6.7)的前綴形成的單位。例如,電壓傳感器的基本單位為V,若一個電壓傳感器數據的val為1234,unit為AW_SENSOR_UNIT_MILLI(即:-3),由于-3對應的單位符號為"m",因此,該傳感器數據的單位為"mV",對應的電壓值即為1234mV。
如需將傳感器數據的單位轉換為基本單位,可以使用如下公式:
data值的數據單位即為基本單位,比如,安培(A)、伏特(V)等。
使用一個“整數”和一個“單位”來對傳感器數據進行表示,可以有效的避免使用浮點數(為了保證系統性能,AWorks內部不直接使用浮點數,當然,應用程序依然可以使用浮點數)。
例如,電壓傳感器采集到的電壓可能為1.234V,為了避免使用小數,可以縮小單位至mV("m"表示“毫”,10-3),此時,1.234V即可表示為1234mV。若使用aw_sensor_val_t類型的數據表示該電壓值,則val值為1234,unit為-3(表示10-3,對應了單位前綴:"m",即“毫”)。
由此可見, unit為負數時可以表示一個小數。此外,val值的類型為有符號32位整數,其可以表示的數據范圍為:-2147483648 ~ 2147483647。若數據超過該范圍,則也可以將unit設置為正數,例如,若傳感器數據為2147483647000,則可以將val的值設置為2147483647,unit的值設置為AW_SENSOR_UNIT_KILO(即:3,表示103,對應了符號:"k",即“千”)。
假設傳感器通道0為一個溫度傳感器通道,則獲取溫度的范例程序詳見程序清單6.34。
程序清單6.34 獲取單通道傳感器數據的范例程序
其中,pow()函數為標準C庫提供的數學運算函數(在math.h文件中聲明),用于求取一個數的冪,其函數原型為:
其返回值即為x的y次方,即:xy。該函數的操作數均為double類型的雙精度浮點數,運算效率較低。通常情況下,如非必要,都不建議引入浮點運算。例如,一個傳感器數據僅僅只需要打印顯示,則不需要將其轉換為浮點數,僅需將小數點顯示至合適的位置即可。例如,對于一個溫度傳感器數據,若其unit為-3,則以基本單位℃為單位進行數值的打印顯示時,應顯示3位小數,比如,45087應顯示為45.087℃,基于此,分別顯示整數部分和小數部分即可:
程序中,將val值整除1000作為了整數部分,對1000取余作為了小數部分(打印小數部分時,位寬固定為3位,且不足3位時,應在前面補0,比如45087對1000取余的結果為87,但應顯示為"087")。
由此可見,打印顯示時,完全可以避免浮點運算。需要注意的是,unit的值不一定為-3,也可能為-6或其它值。這種情況下,就要分別處理,例如,為-6時,應打印顯示6位小數:
顯然,這樣處理起來略顯復雜,需要分別為不同的unit值打印不同的小數位數。但在實際應用中,顯示的小數位數往往是固定的,其通常由實際顯示器(比如:數碼管位數,顯示器位寬等)或具體應用需求決定,不難想象,如果一個顯示器一會兒顯示3位小數,一會兒顯示6位小數,用戶體驗將很難得到保證。
如果應用需要將顯示的小數位數固定為3,那么當unit為-6時,可以將unit轉換為-3后再按照3位小數進行顯示,例如:
程序中,首先將unit的值增加了3,即表示將數據擴大了103,即1000倍。為了使數據保持不變,需要將val值縮小1000倍。如此一來,temp_val中的unit值又變為-3了,而后即可按照3位小數進行打印顯示。由于val值整除了1000,那么原來低三位的數據均會丟失,也就意味著,精度會存在損失,實際上, 6位小數僅顯示3位,本身就是一種精度的舍棄。例如,原val值為25234167,unit為-6,表示了25.234167℃。經過轉換后,val值為25234,unit為-3,表示了25.234℃,即完成了由6位小數精度到3位小數精度的轉換。
如果一個系統中固定溫度顯示的精度為3位小數,那么可以將所有溫度數據的unit轉換為-3。為便于用戶使用,AWorks提供了傳感器數據單位轉換函數,其轉換原理如下。
若是擴大單位(增加unit的值),假定unit增加的值為n,則會將val的值整除10n,由于存在整除,將會使原val值的精度減小。精度減小時,遵循四舍五入法則。例如,原數據為1860mV,若將單位轉換為V,則轉換的結果為2V;原數據為1245mV,若將單位轉換為V,則轉換的結果為1V。由于存在精度的損失,單位的擴大應該謹慎使用。
若是縮小單位(減小unit的值),假定unit減小的值為n,則會將val的值乘以10n,但應特別注意,val值的類型為32位有符號數,其能夠表示的數據范圍為:-2147483648 ~ 2147483647。不應使val值擴大10n后超過該范圍??s小單位不存在精度的損失,但應注意數據的溢出,不應將一個數據縮小至太小的單位。若數據可能溢出,則轉換會失敗,原數據的值和單位均會保持不變。
特別地,若轉換前后的單位沒有發生變化,則整個傳感器的值保持不變。
傳感器數據單位轉換的函數原型為:
其中,p_buf為傳感器數據緩存,num為緩存大小,表示需要轉換單位的數據個數,to_unit表示目標單位,其值為AW_SENSOR_UNIT_* (比如: AW_SENSOR_UNIT_MILLI)。若返回值為AW_OK,表示所有數據轉換成功;否則,表明存在轉換失敗的數據,轉換失敗可能是由于在縮小單位時,val值無法完成擴大,即擴大10n后會超過有符號32位數所能夠表示的范圍。轉換失敗的數據val值和unit值將保持不變,用戶可以根據數據轉換結束后的單位是否為目標單位來判斷某一數據是否轉換成功。
例如,從傳感器中獲取數據,并按照3位小數進行打印顯示的范例程序詳見程序清單6.35。
程序清單6.35 傳感器數據單位轉換的范例程序
程序中,假定了通道0為溫度傳感器通道,由于val值能夠表示的數據范圍為-2147483648 ~ 2147483647,當unit為-3時,其可以表示的溫度范圍為:-2147483.648 ~ 2147483.647℃。在一般應用環境中,溫度不會超過該范圍,因此,單位轉換必然會成功,當能夠確定數據不會超過表示范圍時,可以不用判斷單位轉換函數的返回值。
-
獲取一組(多個)傳感器通道的數據
該函數用于獲取一組(多個)傳感器通道的數據,其函數原型為:
其中,p_ids為指向傳感器通道id列表的指針;num表示通道的數目,即id列表的大??;p_buf指向用于存儲各通道數據的緩存,緩存大小應該與num一致,函數執行結束后,其中將包含各個通道的數據。
若返回值為AW_OK,則表示所有通道的數據均獲取成功,p_buf所指緩存中存放了有效的數據;否則,表示存在數據獲取失敗的通道,此時,p_buf所指緩存中,這些失敗的通道對應的數據將為無效值,即:使用 AW_SENSOR_VAL_IS_VALID()宏判斷數據有效性時,將返回FALSE,用戶可以使用AW_SENSOR_VAL_IS_VALID()宏逐一檢查各個通道的數據,以判斷哪些通道的數據獲取成功,哪些通道的數據獲取失敗。特別注意,當數據為無效值時,val值將為標準錯誤碼,用戶可以根據val值判斷該通道失敗的原因,例如,值為-AW_ENODEV時,表示對應通道不存在。
AW_SENSOR_VAL_IS_VALID()宏用于判斷一個數據的有效性,其原型(aw_sensor.h)為:
其中,data為aw_sensor_val_t類型的數據,僅當該宏返回TRUE時,才表示data為有效的傳感器數據。否則,data為無效值,此時,unit值無效,val值表示標準錯誤碼,其反應了數據無效(即某種操作失敗)的原因。
獲取一組通道(通道0、3、5、6、8、9)數據的范例程序詳見程序清單6.36。
程序清單6.36 獲取一組(多個)通道數據的范例程序(1)
通常情況下,為了使程序更加簡潔,也可以不判斷函數的返回值,僅需在最后使用傳感器數據前,判斷傳感器數據是否有效即可,范例程序詳見程序清單6.37。
程序清單6.37 獲取一組(多個)通道數據的范例程序(2)
4.禁能傳感器通道
當某些傳感器通道使用完畢,暫時不需要從其中獲取數據時,可以禁能相應的通道,使其進入一種最佳的低功耗狀態(若支持)。AWorks提供了兩類禁能接口,分別用于禁能單個傳感器通道和禁能一組(多個)傳感器通道。
-
禁能單個傳感器通道
禁能單個傳感器通道的函數原型為:
其中,id為傳感器通道的編號。若函數返回值為AW_OK,則表示通道禁能成功;否則,表示通道禁能失敗,返回值為標準錯誤碼,可以據此判定失敗的原因。例如,返回值為-AW_ENODEV時,表示id對應的傳感器通道不存在。禁能通道0的范例程序詳見程序清單6.38。
程序清單6.38 禁能單個傳感器通道的范例程序
-
禁能一組(多個)傳感器通道
禁能一組(多個)傳感器通道的函數原型為:
其中,p_ids為指向傳感器通道id列表的指針;num表示通道的數目,即id列表的大小;p_result指向用于存儲各個通道禁能結果的緩存,緩存大小應該與num一致。函數執行結束后,其中將包含各個通道禁能的結果,其數據含義與使能通道時的數據含義一致,即:unit的值無效,僅使用val值表示各個通道禁能的結果。此時,val值即為標準錯誤碼,若其值為AW_OK,則表示相應的通道禁能成功;否則,表示相應的通道禁能失敗,例如,值為-AW_ENODEV時,表示對應通道不存在。
aw_sensor_group_disable()函數的返回值同樣為標準錯誤碼,若其值為AW_OK,則表示所有通道禁能成功,此時,p_result中所有數據的val值均為AW_OK,因此,當返回值為AW_OK時,無需判斷p_result中的值即可斷定所有通道禁能成功;否則,表示存在禁能失敗的通道,此時,可以逐一檢查p_result中的值來判斷具體哪些通道禁能成功,哪些通道禁能失敗。禁能一組通道(通道0、3、5、6、8、9)的范例程序詳見程序清單6.39。
程序清單6.39 禁能一組(多個)傳感器通道的范例程序
基于數碼管接口和通用傳感器接口,可以實現一個簡單的應用:使用數碼管實時顯示當前溫度值。范例程序詳見程序清單6.40。
程序清單6.40 使用數碼管實時顯示溫度的范例程序
應用程序中,將需要使用到的傳感器通道id和數碼管顯示器id使用宏的形式在程序前進行了定義(詳見程序清單6.40的第7 ~ 8行),當前id均定義為0,若實際使用的id發生變化,僅需修改這兩個宏值即可。
6.6 溫控器
下面將結合此前介紹的接口,使用LED、蜂鳴器、數碼管、矩陣鍵盤和溫度采集,實現一個簡易的溫控器。
1. 功能簡介
使用標準I2C接口的LM75B溫度傳感器采集溫度并在數碼管上顯示,由于只有兩位數碼管,因此只顯示整數部分;當溫度為負數時,也不顯示負,僅顯示溫度值。
可設置溫度上限值和溫度下限值,當溫度高于上限值或低于下限值時,則蜂鳴器鳴叫。
2. 狀態指示
在調節過程中,使用LED0和LED1兩個LED用于狀態指示:
-
LED0亮:表明當前值為上限值,數碼管顯示上限值;
-
LED1亮:表明當前值為下限值,數碼管顯示下限值;
-
兩燈閃爍:表明正常運行狀態,數碼管顯示環境溫度值。
3. 操作說明
設置上下限值時,共計使用4個按鍵。即:
-
SET鍵:用于進入設置狀態。點擊后首先進入溫度上限值設定,再次點擊可進入溫度下限值設定,再次點擊回到正常運行狀態;
-
左移/右移鍵:用于切換當前調節的位(個位/十位)。當進入設置狀態后,當前調節的位會不斷的閃爍;點擊該鍵可以切換當前調節的位,由個位切換到十位,或由十位切換到個位;
-
加1鍵:當進入設置狀態后,當前調節的位會不斷的閃爍,按該鍵可以使該位上的數值增加1;
-
減1鍵:當進入設置狀態后,當前調節的位會不斷的閃爍,按該鍵可以使該位上的數值增減1。
(1)設置上限值
首次按下SET鍵進入上限值設置,此時LED0點亮,數碼管顯示上限值溫度,個位不停閃爍。按“加1鍵”或“減1鍵”可以對當前閃爍位上得值進行調整,按下“左移/右移鍵”可以切換當前調節的位。
(2)設置下限值
在設置上限值的基礎上,再次點擊SET鍵即可進入下限值的設定,此時LED1點亮,數碼管顯示下限值溫度,個位不停閃爍。按“加1鍵”或“減1鍵”可以對當前閃爍位上的值進行調整,按“左移/右移鍵”可以切換當前調節的位。
4. 功能實現
溫控器的實現范例程序詳見程序清單6.41。程序中比較繁瑣的是按鍵的處理程序。為了使程序結構更加清晰,分別對3種按鍵:切換狀態(KEY0)、切換當前調節位(KEY2)、調節當前位的值(KEY1和KEY3)寫了3個函數,各個函數直接在__key_callback()按鍵回調函數中調用。其它部分均在while(1)主循環中完成,主要完成3件事情:溫度值的采集,每隔500ms進行一次;溫度值的判斷,判斷是否過高或過低,以便報警;正常狀態下LED0和LED1的閃爍。
程序清單6.41 使用通用接口實現溫控器代碼
-
接口
+關注
關注
33文章
8580瀏覽量
151051 -
周立功
+關注
關注
38文章
130瀏覽量
37620
原文標題:AWorks軟件篇 — 通用設備接口
文章出處:【微信號:Zlgmcu7890,微信公眾號:周立功單片機】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論