AWorksLP對外設進行了高度抽象化,為同一類外設提供了相同的接口,應用程序可以輕松跨平臺。本文以MR6450平臺為例,介紹AWorksLP GPIO外設基本用法。
?簡介
GPIO(General Purpose Input and Output)是通用輸入輸出口。通俗地說,就是一些引腳,可以通過它們對外輸出電平信號或者通過它們讀取外部的電平信息。將I/O口用作普通輸入/輸出功能時,有兩種常見的使用方式:一種是用作普通的輸入/輸出接口;一種是用作中斷輸入接口,即當指定的輸入狀態事件發生(比如:下降沿)時,觸發用戶自定義的回調函數。
?接口介紹
函數列表:
函數原型 | 簡要描述 |
aw_err_t aw_pin_cfg (int pin, uint32_t flags); | 配置引腳屬性 |
aw_err_t aw_gpio_get (int pin); | 讀取引腳的輸入/輸出值 |
aw_err_t aw_gpio_set (int pin, int value); | 設置引腳輸出值 |
aw_err_t aw_gpio_toggle (int pin); | 翻轉引腳的輸出值,即高電平變低電平,低電平變高電平 |
aw_err_t aw_gpio_trigger_cfg (int pin, uint32_t flags); | 配置引腳“觸發條件”,觸發條件可位或 |
aw_err_t aw_gpio_trigger_connect (int pin, aw_pfuncvoid_t pfunc_callback, void *p_arg); | 連接一個回調函數到引腳 |
aw_err_t aw_gpio_trigger_disconnect (int pin, aw_pfuncvoid_t pfunc_callback, void *p_arg); | 斷開引腳的回調函數 |
aw_err_t aw_gpio_trigger_on (int pin); | 開啟引腳的觸發功能 |
aw_err_t aw_gpio_trigger_off (int pin); | 關閉指定引腳的觸發功能 |
使用aw_pin_cfg (int pin, uint32_t flags)接口配置pin為gpio功能時,flags參數詳見下表。
GPIO屬性配置表:
GPIO屬性 | 宏定義 | 值 | 描述 |
GPIO模式 | AW_PIN_CFG_GPIO_INPUT | 1<<0 | 輸入模式 |
AW_PIN_CFG_GPIO_OUTPUT | 2<<0 | 輸出模式 | |
AW_PIN_CFG_GPIO_OUTPUT_LOW | 3<<0 | 輸出模式且輸出低 | |
AW_PIN_CFG_GPIO_OUTPUT_HIGH | 4<<0 | 輸出模式且輸出高 | |
上下拉功能 | AW_PIN_CFG_FLOAT | 0<<3 | 浮空 |
AW_PIN_CFG_PULL_UP | 1<<3 | 上拉 | |
AW_PIN_CFG_PULL_DOWN | 2<<3 | 下拉 | |
AW_PIN_CFG_PULL_UP_DOWN | 3<<3 | 同時使能上下拉 | |
輸出模式 | AW_PIN_CFG_OUTPUT_MODE_DRIVE | 0<<5 | 直接輸出 |
AW_PIN_CFG_OUTPUT_MODE_OPEN_DRAIN | 1<<5 | 開漏輸出 | |
AW_PIN_CFG_OUTPUT_MODE_PUSH_PULL | 2<<5 | 推挽輸出 |
配置時,flags參數可以是一個或者多個相關宏定義的組合,簡單示例如下:
aw_pin_cfg(pin, AW_PIN_CFG_GPIO_INPUT); /* 引腳配置為輸出,浮空(無上下拉),直接輸出 */aw_pin_cfg(pin, AW_PIN_CFG_GPIO_OUTPUT);aw_pin_cfg(pin, AW_PIN_CFG_GPIO_INPUT | AW_PIN_CFG_PULL_DOWN ); aw_pin_cfg(pin, AW_PIN_CFG_GPIO_OUTPUT| AW_PIN_CFG_OUTPUT_MODE_PUSH_PULL)
注意:
- 調用配置時,若上表中GPIO屬性值存在缺省時,則會使用未偏移前對應值為0的宏定義默認填充,如上述示例中line3;
- 配置時需一次性將flags進行傳入,不能每次傳遞一個屬性進行配置進行多次調用,否則可能和期望配置結果不匹配。
使用 aw_gpio_trigger_cfg(int pin, uint32_t flags)接口配置引腳中斷時,flags參數見下表。
GPIO中斷配置表:
宏定義 | 描述 |
AW_GPIO_TRIGGER_HIGH | 高電平觸發 |
AW_GPIO_TRIGGER_LOW | 低電平觸發 |
AW_GPIO_TRIGGER_RISE | 上升沿觸發 |
AW_GPIO_TRIGGER_FALL | 下降沿觸發 |
配置時,flags參數可以是一個或者多個上表宏定義的組合,簡單示例如下:
aw_gpio_trigger_cfg (pin, AW_GPIO_TRIGGER_HIGH);aw_pin_cfg(pin, AW_GPIO_TRIGGER_RISE);aw_pin_cfg(pin, AW_GPIO_TRIGGER_RISE | AW_GPIO_TRIGGER_HIGH ); /* 雙邊沿觸發 */aw_pin_cfg(pin, AW_GPIO_TRIGGER_RISE | AW_GPIO_TRIGGER_FALL);
注意:
- 當設置為不合理條件觸發組合(如 AW_GPIO_TRIGGER_HIGH | AW_GPIO_TRIGGER_FALL)時,該函數會返回-AW_EINVAL。
?使用樣例
AWorksLP SDK相關使用請參考《AWorksLP SDK快速入門(MR6450)——開箱體驗》一文,本文不再贅述。
1.通用IO功能
{SDK}\demos\peripheral\gpio路徑下為通用GPIO例程,例程具體代碼如下:
#include "aworks.h"#include "aw_delay.h"#include "aw_gpio.h"#include "aw_vdebug.h"
/** * \brief GPIO demo 入口 * \return 無 */void demo_gpio_entry (int gpio){ int i = 0;
aw_kprintf("\nGPIO demo testing...\r\n");
/* LED以1s的周期閃爍5次 */ for (i = 0; i < 5; i++) { ? ? ? ?aw_gpio_set(gpio, 0);
aw_mdelay(500);
aw_gpio_set(gpio, 1);
aw_mdelay(500); }
/* LED以0.2s的周期持續閃爍 */ for (i = 0; i < 40; i++) { ? ? ? ?aw_gpio_toggle(gpio); ? ? ? ?aw_mdelay(100); ? ?} ? ?aw_kprintf("\nGPIO demo exit...\r\n");}
上述代碼中使用aw_gpio_set和aw_gpio_toggle接口分別實現了500ms時間間隔的引腳5次反轉以及100ms時間間隔引腳40次反轉。在HPM的SDK中,傳入該例程函數的引腳為RUN燈,所以最終的實驗現象是LED燈先以較慢的速度閃爍,后以較快的速度閃爍,RUN燈的位置如圖1所示。
圖1運行燈
2.中斷功能
{SDK}\demos\peripheral\int路徑下為通用中斷例程,例程具體代碼如下:
#include "aworks.h"#include "aw_gpio.h"#include "aw_sem.h"#include "aw_vdebug.h"#include "aw_delay.h"#include "aw_int.h"
/**\brief 記錄是否產生中斷 */AW_SEMB_DECL_STATIC(__gpio_intr_semb);#define TRIGGER_FLAG AW_GPIO_TRIGGER_RISE
static void __test_gpio_trig_isr (void* arg){ int interrupt_pin = (int)arg;#if TRIGGER_FLAG == AW_GPIO_TRIGGER_LOW || TRIGGER_FLAG == AW_GPIO_TRIGGER_HIGH /* 關閉觸發中斷,避免電平觸發時不停地進中斷導致程序無法繼續運行 */ aw_gpio_trigger_off(interrupt_pin);#endif AW_SEMB_GIVE(__gpio_intr_semb);}
void demo_interrupt_entry (int output_pin, int interrupt_pin){ aw_err_t err; int i; aw_kprintf("\ninterrupt demo testing...\r\n"); /* 信號量初始化 */ AW_SEMB_INIT(__gpio_intr_semb, AW_SEM_EMPTY, AW_SEM_Q_FIFO); /* 連接中斷回調函數 */ err = aw_gpio_trigger_connect(interrupt_pin, __test_gpio_trig_isr, (void *)interrupt_pin); if (err != AW_OK) { aw_kprintf("gpio trigger connect failed!\n"); return; } /* 配置為 TRIGGER_FLAG 對應方式觸發 */ err = aw_gpio_trigger_cfg(interrupt_pin, TRIGGER_FLAG); if (err != AW_OK) { aw_kprintf("gpio trigger cfg failed!\n"); return; } /* 開啟引腳的觸發 */ err = aw_gpio_trigger_on(interrupt_pin); if (err != AW_OK) { aw_kprintf("gpio trigger on failed!\n"); return; } for (i = 0; i < 50; i++) { ? ? ? ? ? ?/* 設置輸出管腳為低電平 */ ? ? ? ?aw_gpio_set(output_pin, 0); ? ? ? ? ? ?/* 等待中斷觸發 */ ? ? ? ?err = AW_SEMB_TAKE(__gpio_intr_semb, 1000); ? ? ? ?if (err == AW_OK) { ? ? ? ? ? ?aw_kprintf("enter gpio interrupt!\n"); ? ? ? ?}#if TRIGGER_FLAG == AW_GPIO_TRIGGER_LOW || TRIGGER_FLAG == AW_GPIO_TRIGGER_HIGH ? ? ? ?/* 打開在回調函數中關閉的觸發中斷 */ ? ? ? ?err = aw_gpio_trigger_on(interrupt_pin); ? ? ? ?if (err != AW_OK) { ? ? ? ? ? ?aw_kprintf("gpio trigger on failed!\n"); ? ? ? ? ? ?return; ? ? ? ?}#endif ? ? ? ?/* 設置輸出管腳為高電平 */ ? ? ? ?aw_gpio_set(output_pin, 1); ? ? ? ? ? ? ? ? ?aw_mdelay(100); ? ?} ? ? ? ? ? ? ?/* 斷開中斷連接回調函數 */ ? ?aw_gpio_trigger_disconnect(interrupt_pin, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? __test_gpio_trig_isr, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (void *)interrupt_pin); ? ? ? ? ? ? ?/* 關閉引腳的觸發 */ ? ?aw_gpio_trigger_off(interrupt_pin); ? ? ? ? ? ? ? ? ?/* 終止信號量 */ ? ?AW_SEMB_TERMINATE(__gpio_intr_semb); ? ? ? ? ? ? ?aw_kprintf("interrupt demo exit...\r\n");}
在例程代碼中通過aw_gpio_trigger_connect、aw_gpio_trigger_cfg、aw_gpio_trigger_on三個接口配置interrupt_pin引腳中斷觸發模式為AW_GPIO_TRIGGER_RISE、中斷回調函數為__test_gpio_trig_isr并對中斷進行使能,同時配置output_pin持續翻轉作為中斷源的提供引腳,當output_pin 輸出滿足例程的中斷條件時,會觸發中斷進入__test_gpio_trig_isr函數釋放__gpio_intr_semb信號量,在例程中獲取信號量成功后并打印"enter gpio interrupt!"。
例程中默認使用中斷例程輸出信號引腳為PIN_PF08、中斷測試引腳為PF09,但由于本文測試所使用開發板并未引出該組引腳,故使用開發板上絲印URX1(PIN_PE24)做信號輸出引腳與UTX1(PIN_PE25)做中斷引腳進行測試,需修改main.c文件中TEST_OUTPUT_PIN與TEST_INTERRUPT_PIN宏定義,修改后如下所示:
#define TEST_OUTPUT_PIN PIN_PE24#define TEST_INTERRUPT_PIN PIN_PE25
修改完成后,重新編譯工程并下載固件至開發板中,將開發板絲印URX1與UTX1引腳短接,并使用串口工具連接至DUART接口,則可看到在上位機中打印下圖信息,表明中斷觸發成功。
圖2串口打印信息注意事項:
- aw_gpio_trigger_connect函數所連接的回調函數是在中斷中進行調用的,故該函數的實現需盡量的簡短、高效,避免執行時間過長,否則可能會影響OS的實時性;
- 若中斷觸發條件為電平觸發時,需在中斷回調中關閉對應引腳中斷,否則電平持續階段會一直產生中斷。
由于篇幅限制,樣例中僅選取了部分特性進行講解,在使用時需根據實際情況配置相應的觸發條件以滿足項目需求,更多引腳屬性功能使用以及中斷組合特性可自行調整測試。
本文對GPIO外設接口及樣例做了詳細介紹,當然其他外設也會陸續發布,請大家關注后續推文更新~
-
GPIO
+關注
關注
16文章
1204瀏覽量
52070
發布評論請先 登錄
相關推薦
評論