GPIO是通用輸入輸出接口(General Purpose Input Output)的簡稱,是微控制器最基本也是最常用的外設,本期內(nèi)容將介紹GPIO的基本原理,然后通過「點亮LED」與「按鍵控制LED」兩個小實驗帶領大家了解GPIO基本輸出與輸入功能的使用方法。
系統(tǒng)環(huán)境
Windows 10-64bit
軟件平臺
NucleiStudio IDE 202102版
硬件需求
RV-STAR開發(fā)板
GPIO基本原理
GPIO的全稱是通用輸入輸出接口(General Purpose Input/Output),是很多外設能夠正常工作的基礎,MCU上除了一些特定功能的引腳(如電源引腳)外,其他的引腳基本都可以作為GPIO來使用。
GD32VF103的GPIO端口以“組”的形式工作,命名方式為Px(x=A, B, C, D, E···),每組配置有16個引腳。GPIO端口和其他的備用功能(AFs)共用引腳,在特定的封裝下獲得最大的靈活性。
每個GPIO引腳都可以通過軟件配置為輸出(推挽或開漏)、輸入、外設備用功能或者模擬模式。每個GPIO引腳都可以配置為上拉、下拉或浮空。除模擬模式外,所有的GPIO引腳都具備大電流驅動能力。
(標準GPIO端口的基本結構)
GPIO具有下列特征:
輸入/輸出方向控制
施密特觸發(fā)器輸入功能使能控制
每個引腳都具有弱上拉/下拉功能
推挽/開漏輸出使能控制
置位/復位輸出使能
模擬輸入/輸出配置
備用功能輸入/輸出配置
端口鎖定配置
實驗1:點亮LED
RVSTAR有一個板載的RGB LED,通過PA1、PA2、PA3三個引腳控制LED_G、LED_R、LED_B三個顏色,通過原理圖可以得知:要點亮LED需要通過GPIO引腳輸出一個低電平,當然也可以通過輸出PWM控制三個顏色LED的亮度,進而組合產(chǎn)生不同的顏色。
下面將通過實驗點亮LED_G,并令其以2秒為間隔閃爍:
(RGB LED原理圖 - 1)
(RGB LED原理圖 - 2)
首先參照之前的教程,使用NucleiStudio IDE或PlatformIO IDE創(chuàng)建工程,在main.c文件內(nèi)編寫代碼如下:
/* 實驗1:點亮LED */ #include "nuclei_sdk_hal.h" void led_config(); void led_on(); void led_off(); int main(void) { // 首先對外設進行初始化操作 led_config(); while (1) { led_on(); // 點亮LED delay_1ms(2000); // 延時2秒 led_off(); // 熄滅LED delay_1ms(2000); // 延時2秒 } } void led_config() { // 使能GPIOA端口的外設時鐘 rcu_periph_clock_enable(RCU_GPIOA); // 將PA1初始化為推挽輸出模式 gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1); } void led_on() { // 將輸出引腳置位為0,輸出低電平,燈亮 gpio_bit_reset(GPIOA, GPIO_PIN_1); } void led_off() { // 將輸出引腳置位為1,輸出高電平,燈熄 gpio_bit_set(GPIOA, GPIO_PIN_1); }
然后將工程文件進行編譯和上傳,將可以觀察到板載的綠色LED以2秒為間隔進行閃爍。運行結果如下:
實驗2:按鍵控制LED
實驗1我們使用了GPIO的輸出功能點亮了LED,實驗2將帶領大家使用GPIO的輸入功能:用RVSTAR的板載按鍵控制LED的亮和滅,在使用它之前我們需要了解一點按鍵消抖的知識。
(按鍵的原理圖)
RVSTAR有一個板載的按鍵,連接到了MCU的PA1引腳上,按鍵沒按下時,PA1引腳通過一個下拉電阻接地,處于低電平狀態(tài),按鍵按下時PA1引腳被拉高到3.3V,處于高電平狀態(tài)。由于按鍵是機械結構,在按下和彈起的瞬間會產(chǎn)生抖動,即引腳上的電平狀態(tài)不會被立刻拉高或拉低到穩(wěn)定狀態(tài),因此為了能夠準確檢測用戶的按鍵操作,往往需要通過一定的方法進行消抖處理:
常用的按鍵消抖方法有硬件消抖和軟件消抖:硬件消抖是通過在按鍵兩端增加電容的方式實現(xiàn)的,成本較高;而軟件消抖是在第一次檢測到電平變化后延時一定時間后再次檢測電平狀態(tài),如果檢測到仍處于按下時的電平狀態(tài),那么說明用戶進行了完整的按鍵操作,這個延時時間跟具體的硬件有關,經(jīng)測試,在RVSTAR的按鍵上大約需要是設置100毫秒的延時比較合適。
使用NucleiStudio IDE或PlatformIO IDE創(chuàng)建工程,在main.c文件內(nèi)編寫代碼如下:
/* 實驗2:按鍵控制LED */ #include "nuclei_sdk_hal.h" void led_config(); void led_on(); void led_off(); void key_config(); bit_status key_get_status(); bit_status led_status = 0; // 用來記錄led的當前狀態(tài) int main(void) { led_config(); key_config(); led_off(); while (1) { // 第一次檢測按鍵按下 if(key_get_status() == SET) { // 軟件延時100ms用以消除抖動 delay_1ms(100); // 再次檢測按鍵是否按下 if(key_get_status() == SET) { switch (led_status) { case 0: led_on(); break; case 1: led_off(); break; default: break; } led_status = !led_status; // 每次按鍵操作后切換led的狀態(tài) } } } } void led_config() { // 打開GPIOA端口的外設時鐘 rcu_periph_clock_enable(RCU_GPIOA); // 將PA1初始化為推挽輸出模式 gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1); } void led_on() { // 將輸出引腳置位為0,輸出低電平,燈亮 gpio_bit_reset(GPIOA, GPIO_PIN_1); } void led_off() { // 將輸出引腳置位為1,輸出高電平,燈熄 gpio_bit_set(GPIOA, GPIO_PIN_1); } void key_config() { rcu_periph_clock_enable(RCU_GPIOA); // 開啟外設時鐘 rcu_periph_clock_enable(RCU_AF); // 開啟復用時鐘 gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_0); // 將PA0初始化為浮空輸入模式 } bit_status key_get_status() { // 獲得輸入引腳的狀態(tài),其中bit_status是一個固件庫定義的枚舉類型 return gpio_input_bit_get(GPIOA, GPIO_PIN_0); }
然后將工程文件進行編譯和上傳,將可以觀察到:上電后LED不亮,每次按下按鍵后LED的狀態(tài)會發(fā)生切換。
運行結果如下: