OpenHarmony智能開發(fā)套件[驅(qū)動(dòng)開發(fā)篇(上)
想了解更多關(guān)于開源的內(nèi)容,請(qǐng)?jiān)L問:
前言
下面我們繼續(xù)跟著架構(gòu)圖去學(xué)習(xí)另一個(gè)板塊——驅(qū)動(dòng),本片將介紹。
驅(qū)動(dòng)開發(fā)簡介
什么是驅(qū)動(dòng)開發(fā)呢,回想我們之前介紹內(nèi)核的時(shí)候,內(nèi)核的作用是幫助我們完成對(duì)硬件的操控的,我們已經(jīng)通過KAL內(nèi)核抽象層提供的規(guī)范接口,實(shí)現(xiàn)了對(duì)內(nèi)核的一些基本控制,但是并沒有涉及到硬件設(shè)備,那么驅(qū)動(dòng)開發(fā)的含意就呼之欲出了。
驅(qū)動(dòng)開發(fā)是指為操作系統(tǒng)或硬件設(shè)備編寫軟件驅(qū)動(dòng)程序的過程。驅(qū)動(dòng)程序是一種特殊的軟件,它與操作系統(tǒng)或硬件設(shè)備進(jìn)行交互,以使它們能夠有效地通信和協(xié)同工作。通俗點(diǎn)講就是IO控制硬件設(shè)備。IO流在讀寫文件時(shí)大家都會(huì)用到,我們的驅(qū)動(dòng)也像IO流,只不過操作的對(duì)象不在是虛擬的文件,而是你手中的開發(fā)板,實(shí)實(shí)在在摸得到的硬件設(shè)備。
硬件設(shè)備介紹
硬件總覽
筆者使用的是智能家居開發(fā)套件:Hi3861
硬件詳細(xì)介紹
底板
核心板
oled屏幕
交通燈
RGB燈板
環(huán)境檢測板
NFC
驅(qū)動(dòng)開發(fā)
GPIO
GPIO可以理解為數(shù)字I/O,是一種電平控制,由0和1表示,0表示低電平,1表示高電平。Hi3861芯片一共有15各個(gè)GPIO引腳,芯片內(nèi)部集成了GPIO模塊,方便我們?nèi)ナ褂谩?/p>
Hi3861 GPIO 引腳分布
IoT接口
OprnHarmony提供了操作物聯(lián)網(wǎng)各種外接設(shè)備的一組API,方便我們?nèi)タ刂婆c外接設(shè)備的交互。一共有三類IoT接口。
- HAL硬件抽象層接口。
- HDF硬件驅(qū)動(dòng)框架接口。
- 海思SDK接口。
其中HDF接口是主推接口,在上面的架構(gòu)圖中也能看到,海思的SDK是原廠商提供的底層接口。
GPIO控制流程
IoT編程工作環(huán)境補(bǔ)充
在源碼目錄生成的 .vscode的目錄下的 c_cpp_properties.json 文件中做出如下添加。
[注:目錄可能因?yàn)樵创a版本不同而不一致,這里可以手動(dòng)搜索文件來確定庫的存放位置]。
打開 usr_config.mk 文件 修改如下配置,防止后續(xù)的操作中出現(xiàn)編譯錯(cuò)誤,筆者報(bào)錯(cuò)時(shí),也是在這卡了很久。這個(gè)配置項(xiàng)默認(rèn)是關(guān)閉的,就會(huì)導(dǎo)致某些庫中的方法無法被識(shí)別,編譯就會(huì)出問題,主要是pwm模塊的使用,這里提前說一下。
GPIO-API
- GPIO初始化。
unsigned int IoTGpioInit(unsigned int id);
參數(shù)解釋:
- id: GPIO的引腳編號(hào)。
返回值:
- IOT_SUCCESS:如果GPIO設(shè)備成功初始化,則返回該值。
- IOT_FAILURE:如果GPIO設(shè)備初始化失敗,則返回該值。
- GPIO參數(shù)設(shè)置。
unsigned int IoTGpioSetDir(unsigned int id, IotGpioDir dir);
參數(shù)解釋:
- id: GPIO的引腳編號(hào)。
- dir: 設(shè)置GPIO為輸入/輸出。
返回值:
- IOT_SUCCESS:如果GPIO設(shè)備成功設(shè)置,則返回該值。
- IOT_FAILURE:如果GPIO設(shè)備設(shè)置失敗,則返回該值。
其中,IotGPIODir 的定義如下的枚舉類型:
typedef enum {
/** Input */
IOT_GPIO_DIR_IN = 0,
/** Output */
IOT_GPIO_DIR_OUT
} IotGpioDir;
- 設(shè)置GPIO輸出狀態(tài)。
unsigned int IoTGpioSetOutputVal(unsigned int id, IotGpioValue val);
參數(shù)解釋:
- id: GPIO的引腳編號(hào)。
- val: 輸出的電平值。
返回值:
- IOT_SUCCESS:如果GPIO設(shè)備成功設(shè)置,則返回該值。
- IOT_FAILURE:如果GPIO設(shè)備設(shè)置失敗,則返回該值。
其中,IotGPIOValue的定義如下的枚舉類型:
typedef enum {
/** Low GPIO level */
IOT_GPIO_VALUE0 = 0,
/** High GPIO level */
IOT_GPIO_VALUE1
} IotGpioValue;
- 解除GPIO。
unsigned int IoTGpioDeinit(unsigned int id);
參數(shù)解釋:
- id: GPIO的引腳編號(hào)
返回值:
- IOT_SUCCESS:如果GPIO設(shè)備成功解除,則返回該值。
- IOT_FAILURE:如果GPIO設(shè)備解除失敗,則返回該值。
- 獲取GPIO引腳狀態(tài)。
unsigned int IoTGpioGetOutputVal(unsigned int id, IotGpioValue *val);
參數(shù)解釋:
- id: GPIO的引腳編號(hào)
- *val: 獲取輸出的電平值的指針
返回值:
- IOT_SUCCESS:如果GPIO設(shè)備成功獲取,則返回該值。
- IOT_FAILURE:如果GPIO設(shè)備獲取失敗,則返回該值。
這個(gè)API和設(shè)置GPIO引腳的API很像,只不過val屬性變成了個(gè)指針,也就通過這個(gè)指針幫我們獲取到GPIO的引腳狀態(tài)的。
- 引腳中斷函數(shù)注冊(cè)。
unsigned int IoTGpioRegisterIsrFunc(unsigned int id, IotGpioIntType intType, IotGpioIntPolarity intPolarity,
GpioIsrCallbackFunc func, char *arg);
參數(shù)解釋:
- id:GPIO引腳的編號(hào)。
- intType:中斷類型。
- intPolarity:中斷極性。
- func:中斷回調(diào)函數(shù)。
- arg:中斷回調(diào)函數(shù)中使用的參數(shù)的指針。
返回值:
- IOT_SUCCESS:如果成功啟用GPIO引腳的中斷功能,則返回該值。
- IOT_FAILURE:如果啟用GPIO引腳的中斷功能失敗,則返回該值。
其中 IotGpioIntType 定義如下的枚舉類型。
typedef enum {
/** Level-sensitive interrupt */
IOT_INT_TYPE_LEVEL = 0,
/** Edge-sensitive interrupt */
IOT_INT_TYPE_EDGE
} IotGpioIntType;
IOT_INT_TYPE_LEVEL:表示電平觸發(fā)的中斷類型。這種中斷類型基于GPIO引腳的電平狀態(tài)進(jìn)行觸發(fā),即當(dāng)引腳的電平為特定的電平(例如高電平或低電平)時(shí)觸發(fā)中斷。
IOT_INT_TYPE_EDGE:表示邊沿觸發(fā)的中斷類型。這種中斷類型基于GPIO引腳的電平變化進(jìn)行觸發(fā),即當(dāng)引腳的電平從一個(gè)狀態(tài)變化到另一個(gè)狀態(tài)(例如從低電平到高電平或從高電平到低電平)時(shí)觸發(fā)中斷。
IotGpioIntPolarity 定義如下的枚舉類型。
typedef enum {
/** Interrupt at a low level or falling edge */
IOT_GPIO_EDGE_FALL_LEVEL_LOW = 0,
/** Interrupt at a high level or rising edge */
IOT_GPIO_EDGE_RISE_LEVEL_HIGH
} IotGpioIntPolarity;
IOT_GPIO_EDGE_FALL_LEVEL_LOW:表示在低電平或下降沿觸發(fā)中斷。這意味著當(dāng)GPIO引腳的電平為低電平時(shí)或引腳的電平從高電平變?yōu)榈碗娖綍r(shí),觸發(fā)中斷。
IOT_GPIO_EDGE_RISE_LEVEL_HIGH:表示在高電平或上升沿觸發(fā)中斷。這意味著當(dāng)GPIO引腳的電平為高電平時(shí)或引腳的電平從低電平變?yōu)楦唠娖綍r(shí),觸發(fā)中斷。
當(dāng)我們向外界設(shè)備進(jìn)行輸入流操作時(shí),需要處理一些業(yè)務(wù)邏輯,在中斷函數(shù)中完成,后面會(huì)后案例讓大家體會(huì)。
- 引腳中斷函數(shù)解除。
unsigned int IoTGpioUnregisterIsrFunc(unsigned int id);
參數(shù)解釋:
- id:GPIO引腳的編號(hào)。
返回值:
- IOT_SUCCESS:如果成功解除GPIO引腳的中斷功能,則返回該值。
- IOT_FAILURE:如果解除GPIO引腳的中斷功能失敗,則返回該值。
解除類型的API都比較簡單。
- 設(shè)置引腳的功能復(fù)用。
hi_u32 hi_io_set_func(hi_io_name id, hi_u8 val);
參數(shù)解釋:
- id:硬件管腳的枚舉類型 hi_io_name,表示要設(shè)置復(fù)用功能的IO索引。
- val:復(fù)用功能的枚舉類型 hi_u8,表示要設(shè)置的復(fù)用功能。根據(jù)待設(shè)置的硬件管腳,從給定的枚舉值中選擇相應(yīng)的功能。
返回值:
- 0:成功設(shè)置復(fù)用功能。
- HI_ERR_GPIO_INVALID_PARAMETER:設(shè)置復(fù)用功能失敗,輸入?yún)?shù)無效或不支持的功能。
其中 hi_io_name 的美劇類型定義如下:
typedef enum {
HI_IO_NAME_GPIO_0, /**< GPIO0 */
HI_IO_NAME_GPIO_1, /**< GPIO1 */
HI_IO_NAME_GPIO_2, /**< GPIO2 */
HI_IO_NAME_GPIO_3, /**< GPIO3 */
HI_IO_NAME_GPIO_4, /**< GPIO4 */
HI_IO_NAME_GPIO_5, /**< GPIO5 */
HI_IO_NAME_GPIO_6, /**< GPIO6 */
HI_IO_NAME_GPIO_7, /**< GPIO7 */
HI_IO_NAME_GPIO_8, /**< GPIO8 */
HI_IO_NAME_GPIO_9, /**< GPIO9 */
HI_IO_NAME_GPIO_10, /**< GPIO10 */
HI_IO_NAME_GPIO_11, /**< GPIO11 */
HI_IO_NAME_GPIO_12, /**< GPIO12 */
HI_IO_NAME_GPIO_13, /**< GPIO13 */
HI_IO_NAME_GPIO_14, /**< GPIO14 */
HI_IO_NAME_SFC_CSN, /**< SFC_CSN */
HI_IO_NAME_SFC_IO1, /**< SFC_IO1 */
HI_IO_NAME_SFC_IO2, /**< SFC_IO2 */
HI_IO_NAME_SFC_IO0, /**< SFC_IO0 */
HI_IO_NAME_SFC_CLK, /**< SFC_CLK */
HI_IO_NAME_SFC_IO3, /**< SFC_IO3 */
HI_IO_NAME_MAX,
} hi_io_name;
hi_u8 的定義如下:
typedef unsigned char hi_u8;
Hi3861的引腳數(shù)量少,很多功能都是被集成在同一個(gè)引腳上的,因此需要我們?nèi)ミx擇引腳配置。
- 啟用某個(gè)IO引腳的上下拉功能。
hi_u32 hi_io_set_pull(hi_io_name id, hi_io_pull val);
參數(shù)解釋:
- id:硬件管腳的枚舉類型 hi_io_name,表示要設(shè)置上下拉功能的IO引腳的索引。
- val:上下拉狀態(tài)的枚舉類型 hi_io_pull,表示要設(shè)置的上下拉狀態(tài)。
返回值:
- 0:成功設(shè)置上下拉功能。
- HI_ERR_GPIO_INVALID_PARAMETER:設(shè)置上下拉功能失敗,輸入?yún)?shù)無效或不支持的功能。
其中 hi_io_pull 的定義如下的枚舉類型:
typedef enum {
HI_IO_PULL_NONE, /**< Disabled.CNcomment:無拉CNend */
HI_IO_PULL_UP, /**< Pull-up enabled.CNcomment:上拉CNend */
HI_IO_PULL_DOWN, /**< Pull-down enabled.CNcomment:下拉CNend */
HI_IO_PULL_MAX, /**< Invalid.CNcomment:無效值CNend */
} hi_io_pull;
上下拉功能可用于確定GPIO引腳的輸入電平狀態(tài)。例如,通過啟用上拉功能,可以將引腳的輸入電平拉高,使其在未連接外部設(shè)備時(shí)保持為高電平狀態(tài)。這樣,在檢測外部設(shè)備連接時(shí),可以通過讀取引腳的輸入電平狀態(tài)來確定設(shè)備的連接狀態(tài)。
GPIO控制LED案例
能夠使用我們的user按鍵控制可編程led燈的熄滅與點(diǎn)亮。
思路:通過讀取按鍵的電平狀態(tài),觸發(fā)中斷回調(diào)函數(shù),修改led的電平。
- 新建樣例目錄。
applications/sample/wifi-iot/app/led_gpio_demo - 新建源文件和gn文件。
applications/sample/wifi-iot/app/led_gpio_demo/ledGpio.c
applications/sample/wifi-iot/app/led_gpio_demo/BUILD.gn - 編寫源文件,ledGpio.c [筆者加了詳細(xì)的注釋,就直接上代碼了]。
// C語言標(biāo)準(zhǔn)庫
#include <stdio.h>
// 初始化庫
#include "ohos_init.h"
// 內(nèi)核編程標(biāo)準(zhǔn)接口
#include "cmsis_os2.h"
// IoT接口 GPIO
#include "iot_gpio.h"
// 海思SDK IO
#include "hi_io.h"
// 定義引腳的編號(hào)
#define LED_GPIO 9
#define BUTTON_GPIO 5
// 定義ledPin(電平)低電平led點(diǎn)亮,高電平led熄滅,高低電平的定義在之前的api中已經(jīng)介紹過了,是一個(gè)枚舉類型。
static IotGpioValue ledPin = IOT_GPIO_VALUE0;
//GPIO5的中斷處理函數(shù),當(dāng)我們點(diǎn)擊user按鈕時(shí),系統(tǒng)的內(nèi)核就會(huì)暫停手頭的工作來執(zhí)行我們這里的中斷函數(shù)。
static void ButtonPressed(char* atgs){
// 我們的業(yè)務(wù)邏輯是讓led熄滅點(diǎn)亮熄滅點(diǎn)亮,因此只需要修改上方我們定義的ledPin值即可
if(ledPin == IOT_GPIO_VALUE0){
ledPin = IOT_GPIO_VALUE1;
} else {
ledPin = IOT_GPIO_VALUE0;
}
/**
* 當(dāng)然看過源碼的你也可以簡寫成:
* ledPin = !ledPin;
*/
}
// 主函數(shù)
static void GpioInitMain(void){
// 在主函數(shù)中我們通常完成一些GPIO的注冊(cè)和設(shè)置,主要就是用一些介紹給大家的API即可
// GPIO初始化 ——> IoTGpioInit 接口
IoTGpioInit(LED_GPIO);
IoTGpioInit(BUTTON_GPIO);
// 設(shè)置引腳的功能,因?yàn)閔i3861的引腳數(shù)少,一個(gè)引腳上集成了很多功能,需要我們手動(dòng)設(shè)置,選擇其中的一項(xiàng)功能
hi_io_set_func(LED_GPIO, HI_IO_FUNC_GPIO_9_GPIO);
hi_io_set_func(BUTTON_GPIO, HI_IO_FUNC_GPIO_5_GPIO);
// 設(shè)置GPIO的輸入輸出模式 led為輸出模式,button為輸入模式
IoTGpioSetDir(LED_GPIO, IOT_GPIO_DIR_OUT);
IoTGpioSetDir(BUTTON_GPIO, IOT_GPIO_DIR_IN);
// 設(shè)置GPIO5為上拉模式
hi_io_set_pull(BUTTON_GPIO, HI_IO_PULL_UP);
// 注冊(cè)中斷函數(shù)
IoTGpioRegisterIsrFunc(BUTTON_GPIO, IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_FALL_LEVEL_LOW, ButtonPressed, NULL);
// 循環(huán)設(shè)置led的電平
while(1){
IoTGpioSetOutputVal(LED_GPIO, ledPin);
osDelay(10);
}
}
// 測試入口
static void GpioTest(void){
// 創(chuàng)建線程,大家還記得怎么創(chuàng)建的嗎
osThreadAttr_t attr = {"GpioInitMain", 0, NULL, 0, NULL, 1024, osPriorityNormal, 0, 0};
osThreadNew((osThreadFunc_t)GpioInitMain, NULL, &attr);
}
APP_FEATURE_INIT(GpioTest);
- 編寫B(tài)IULD.gn文件。
static_library("led_gpio_demo"){
sources = [
"ledGpio.c"
]
include_dirs = [
"http://commonlibrary/utils_lite/include/",
"http://device/soc/hisilicon/hi3861v100/hi3861_adapter/kal/cmsis",
"http://base/iothardware/peripheral/interfaces/inner_api",
"http://device/soc/hisilicon/hi3861v100/sdk_liteos/include/"
]
}
- 編寫app目錄下的BUILD.gn文件。
- 編譯,燒錄。
- 重啟開發(fā)板,點(diǎn)擊user按鈕,觀察可編程led的狀態(tài)。
PWM
除了GPIO外,我們還可以通過PWM進(jìn)行外部設(shè)備的控制,PWM是一種脈沖調(diào)制技術(shù),用于控制數(shù)字系統(tǒng)中的模擬信號(hào)。通過改變信號(hào)的占空比,PWM可以模擬出不同的電壓或電流值。在PWM信號(hào)中,周期固定,但高電平和低電平的持續(xù)時(shí)間可以不同。例如,一個(gè)50%的占空比意味著高電平和低電平各占一個(gè)周期的一半時(shí)間。當(dāng)占空比增加時(shí),高電平的持續(xù)時(shí)間增加,低電平的持續(xù)時(shí)間減少,平均輸出功率也相應(yīng)增加。因此,我們還可以用PWM控制led的亮度,因?yàn)檎伎毡葧?huì)直接影響輸出的功率,功率會(huì)影響燈的亮度,算是中學(xué)物理了。廣泛應(yīng)用于電機(jī)控制、LED調(diào)光、音頻生成等。
占空比與燈泡亮度
總結(jié)
PWM有兩個(gè)重要的參數(shù),第一個(gè)是輸出頻率,頻率越高,則模擬的效果越好;第二個(gè)是占空比,占空比就是改變輸出模擬效果的電壓大小,占空比越大則模擬出的電壓越大。
PWM-API
很多基礎(chǔ)的IoT接口都已經(jīng)在GPIO-API上講到了,這里的介紹就相對(duì)簡單一點(diǎn)。
- 初始化PWM。
unsigned int IoTPwmInit(unsigned int port);
通過參數(shù)port,指定PWM的端口號(hào)。
- 啟用PWM。
unsigned int IoTPwmStart(unsigned int port, unsigned short duty, unsigned int freq);
參數(shù)解釋:
- port:PWM的端口號(hào)
- duty:PWM輸出的占空比
- freq:PWM輸出的頻率
- 停止PWM。
unsigned int IoTPwmStop(unsigned int port);
通過參數(shù)port,停止PWM的輸出。
結(jié)合GPIO和PWM我們已經(jīng)可以去控制一些板子了,就不單獨(dú)設(shè)計(jì)PWM的案例了。
交通燈板的控制
交通燈板上一共有3個(gè)小板塊,紅綠燈,蜂鳴器,按鈕。下面逐個(gè)為大家講解如何使用對(duì)應(yīng)的API去控制他們。(涉及 GPIO控制設(shè)備和中斷函數(shù)處理 )
按鈕控制蜂鳴器
按一下按鈕,蜂鳴器鳴叫3秒。
- 新建樣例目錄。
applications/sample/wifi-iot/app/pwm_out_demo - 新建源文件和gn文件。
applications/sample/wifi-iot/app/pwm_out_demo/pwm.c
applications/sample/wifi-iot/app/pwm_out_demo/BUILD.gn - 編寫源文件,pwm.c。
#include <stdio.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "hi_io.h"
#include "iot_gpio.h"
// pwm接口
#include "iot_pwm.h"
#include "hi_pwm.h"
#define BUTTON_GPIO 8
#define BEE_GPIO 9
static int flag = 0;
// GPIO8中斷函數(shù)
static void ButtonPressed(char* atgs){
// 業(yè)務(wù)邏輯是讓蜂鳴器響三秒
if(flag == 0){
flag = 1;
}
}
// 主線程函數(shù)
static void PwmInitMain(void){
// 初始化GPIO模塊
IoTGpioInit(BUTTON_GPIO);
IoTGpioInit(BEE_GPIO);
// 設(shè)置引腳功能
hi_io_set_func(BEE_GPIO, HI_IO_FUNC_GPIO_9_PWM0_OUT);
hi_io_set_func(BUTTON_GPIO, HI_IO_FUNC_GPIO_8_GPIO);
// 設(shè)置GPIO輸出模式
IoTGpioSetDir(BEE_GPIO, IOT_GPIO_DIR_OUT);
IoTGpioSetDir(BUTTON_GPIO, IOT_GPIO_DIR_IN);
// 設(shè)置引腳上拉
hi_io_set_pull(BUTTON_GPIO, HI_IO_PULL_UP);
// 注冊(cè)中斷函數(shù)
IoTGpioRegisterIsrFunc(BUTTON_GPIO, IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_FALL_LEVEL_LOW, ButtonPressed, NULL);
// 循環(huán)監(jiān)聽flag,當(dāng)按鈕被按下時(shí),flag會(huì)置為1,蜂鳴器工作3秒
while(1){
if(flag){
// 初始化PWM模塊
IoTPwmInit(HI_PWM_PORT_PWM0);
// 設(shè)置信號(hào)輸出, 端口,占空比,頻率
IoTPwmStart(HI_PWM_PORT_PWM0, 50, 4000);
// 鳴3秒
osDelay(300);
// 停止信號(hào)輸出
IoTPwmStop(HI_PWM_PORT_PWM0);
flag = 0;
}
osDelay(100);
}
}
// 測試入口
static void PwmTest(void){
osThreadAttr_t attr = {"GpioInitMain", 0, NULL, 0, NULL, 1024, osPriorityNormal, 0, 0};
osThreadNew((osThreadFunc_t)PwmInitMain, NULL, &attr);
}
APP_FEATURE_INIT(PwmTest);
- 編寫B(tài)IULD.gn文件。
static_library("pwm_out_demo"){
sources = [
"pwm.c"
]
include_dirs = [
"http://commonlibrary/utils_lite/include/",
"http://device/soc/hisilicon/hi3861v100/hi3861_adapter/kal/cmsis",
"http://base/iothardware/peripheral/interfaces/inner_api",
"http://device/soc/hisilicon/hi3861v100/sdk_liteos/include/"
]
}
- 編寫app目錄下的BUILD.gn文件。
- 編譯,燒錄。
- 重啟開發(fā)板,點(diǎn)擊s1按鈕,可以聽到蜂鳴器鳴叫。
按鈕切換紅綠燈
按一下按鈕,紅綠燈順次切換。
- 新建樣例目錄。
applications/sample/wifi-iot/app/traffic_demo - 新建源文件和gn文件。
applications/sample/wifi-iot/app/traffic_demo/traffic.c
applications/sample/wifi-iot/app/traffic_demo/BUILD.gn - 編寫源文件,traffic.c。
#include <stdio.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "hi_io.h"
#include "iot_gpio.h"
#define BUTTON_GPIO 8
#define RED_GPIO 10
#define GREEN_GPIO 11
#define YELLOW_GPIO 12
// 每個(gè)燈的引腳編號(hào)
static int lights[3] = {RED_GPIO, GREEN_GPIO, YELLOW_GPIO};
// 每個(gè)燈的狀態(tài)
static int lightsStauts[3] = {0, 0, 0};
// 燈的索引
static int lightsIndex = 0;
// 中斷函數(shù)
static void ButtonPress(char *args){
// 點(diǎn)擊按鈕,要能夠切換紅綠燈,修改燈的狀態(tài)數(shù)組即可
for(unsigned int i = 0; i < 3; i++){
if(i == lightsIndex){
lightsStauts[i] = 1;
} else {
lightsStauts[i] = 0;
}
}
lightsIndex++;
if(lightsIndex >= 3){
lightsIndex = 0;
}
}
// 主函數(shù)
static void TrafficInitMain(void){
// GPIO初始化
IoTGpioInit(BUTTON_GPIO);
IoTGpioInit(RED_GPIO);
IoTGpioInit(GREEN_GPIO);
IoTGpioInit(YELLOW_GPIO);
// GPIO功能設(shè)置
hi_io_set_func(BUTTON_GPIO, HI_IO_FUNC_GPIO_8_GPIO);
hi_io_set_func(RED_GPIO, HI_IO_FUNC_GPIO_10_GPIO);
hi_io_set_func(GREEN_GPIO, HI_IO_FUNC_GPIO_11_GPIO);
hi_io_set_func(YELLOW_GPIO, HI_IO_FUNC_GPIO_12_GPIO);
// PGPIO輸入輸出設(shè)置
IoTGpioSetDir(BUTTON_GPIO, IOT_GPIO_DIR_IN);
IoTGpioSetDir(RED_GPIO, IOT_GPIO_DIR_OUT);
IoTGpioSetDir(GREEN_GPIO, IOT_GPIO_DIR_OUT);
IoTGpioSetDir(YELLOW_GPIO, IOT_GPIO_DIR_OUT);
// 引腳上拉
hi_io_set_pull(BUTTON_GPIO, HI_IO_PULL_UP);
// 中斷回調(diào)函數(shù)注冊(cè)
IoTGpioRegisterIsrFunc(BUTTON_GPIO, IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_FALL_LEVEL_LOW, ButtonPress, NULL);
while(1){
// 設(shè)置輸出電平,即可控制燈的點(diǎn)亮熄滅,其實(shí)和之前控制led一樣,只不過這次一下控制3個(gè),用數(shù)組而已
for(unsigned int i = 0; i < 3; i++){
IoTGpioSetOutputVal(lights[i], lightsStauts[i]);
}
osDelay(100);
}
}
// 測試入口
static void TrafficTest(void){
osThreadAttr_t attr = {"TrafficInitMain", 0, NULL, 0, NULL, 1024, osPriorityNormal, 0, 0};
osThreadNew((osThreadFunc_t)TrafficInitMain, NULL, &attr);
}
APP_FEATURE_INIT(TrafficTest);
- 編寫B(tài)IULD.gn文件。
static_library("traffic_demo"){
sources = [
"traffic.c"
]
include_dirs = [
"http://commonlibrary/utils_lite/include/",
"http://device/soc/hisilicon/hi3861v100/hi3861_adapter/kal/cmsis",
"http://base/iothardware/peripheral/interfaces/inner_api",
"http://device/soc/hisilicon/hi3861v100/sdk_liteos/include/"
]
}
- 編寫app目錄下的BUILD.gn文件。
- 編譯,燒錄。
- 重啟開發(fā)板,點(diǎn)擊s1按鈕,可以看到紅綠燈正在切換。大家也可以修改代碼,實(shí)現(xiàn)有紅黃綠,綠黃紅那樣變化。
至此,交通燈板的三個(gè)小模塊就給大家介紹到這里,這些都是基本操作,僅在如何控制設(shè)備,與設(shè)備交互,大家可以根據(jù)自己的想法,創(chuàng)新一些業(yè)務(wù)邏輯,使用該功能板完成相應(yīng)的場景業(yè)務(wù)。
結(jié)束語
本片主要介紹了GPIO,PWM控制驅(qū)動(dòng)的方案,并在交通燈板上進(jìn)行了實(shí)際演示,以及三色燈的使用。后續(xù)的開發(fā)板硬件設(shè)備會(huì)在OpenHarmony智能開發(fā)套件[驅(qū)動(dòng)開發(fā)篇·下]中詳細(xì)講解,包括人體紅外感應(yīng),光敏電阻,RGB燈效,溫濕度傳感器,oled屏幕的點(diǎn)亮。
[本來每一個(gè)案例后面都做了實(shí)際效果演示視頻的,但是視頻好像上傳不了,那暫時(shí)就沒有視頻演示了。]