GPIO輸入——按鍵檢測
按鍵檢測使用到GPIO外設的基本輸入功能,本章中不再贅述GPIO外設的概念,如您忘記了可重新回到第八章節(jié)進行閱讀。
12.1. 硬件設計
按鍵機械觸點斷開、閉合時,由于觸點的彈性作用,按鍵開關不會馬上穩(wěn)定接通或一下子斷開,使用按鍵時會產生 圖12_1中的帶波紋信號,需要用軟件消抖處理濾波,不方便輸入檢測。
本實驗用到的野火啟明6M5開發(fā)板的按鍵帶硬件消抖功能,它利用電容充放電的延時,消除了波紋,從而簡化軟件的處理,軟件只需要直接檢測引腳的電平即可。
瑞薩設計的微處理器(MCU)擁有硬件數字濾波的功能用來實現去除按鍵帶來的紋波影響, 不過前提是按鍵用在外部中斷作為按鍵信號輸入的情況下使用, 通過使用數字濾波的方式能夠替代掉用電容式濾波的方法來消除紋波, 從而減少我們在硬件上的開發(fā)成本。
野火啟明6M5開發(fā)板的按鍵電路圖如 圖12_2所示,圖中RA6M5芯片的P004、P005引腳分別通過一個10KΩ的貼片電阻連接到電源的正極,所以按鍵在沒有被按下的時候,GPIO引腳的輸入狀態(tài)為高電平狀態(tài), 分別又通過串聯(lián)一個100Ω的貼片電阻和一個按鍵接地,所以按鍵在被按下的時候,GPIO引腳的輸入狀態(tài)為低電平狀態(tài)。 只要我們檢測引腳的輸入電平,即可判斷按鍵是否被按下。
若您使用的實驗板按鍵的連接方式或引腳不一樣,只需根據我們的工程修改引腳即可,程序的控制原理相同。
12.2. 按鍵程序設計
使用瑞薩官方提供的FPS庫進行編程,瑞薩官方提供的FPS庫具有方便、快捷、簡潔的特性。 在下面會教大家如何使用FPS庫進行編程。
12.2.1. 新建工程
對于 e2 studio 開發(fā)環(huán)境:拷貝一份我們之前的 e2s 工程模板 “11_GPIO_LED” , 然后將工程文件夾重命名為 “12_Key” ,最后再將它導入到我們的 e2 studio 工作空間中。
對于 Keil 開發(fā)環(huán)境:拷貝一份我們之前的 Keil 工程模板 “11_GPIO_LED” , 然后將工程文件夾重命名為 “12_Key” ,并進入該文件夾里面雙擊 Keil 工程文件,打開該工程。
工程新建好之后,在工程根目錄的 “src” 文件夾下面新建 “key” 文件夾, 再進入 “key” 文件夾里面新建 key 驅動的源文件和頭文件:“bsp_key.c” 和 “bsp_key.h”。 工程文件結構如下。
文件結構
12_Key
├─ ......
└─ src
├─ led
│ ├─ bsp_led.c
│ └─ bsp_led.h
├─ key
│ ├─ bsp_key.c
│ └─ bsp_key.h
└─ hal_entry.c
警告
注意:對于使用 Keil 開發(fā)環(huán)境的用戶,將代碼文件放到 “src” 文件夾下之后, Keil 軟件并不會自動將它們加入到工程,這時候需要打開 RASC FSP 配置界面, 點擊一次單擊右上角的 “Generate Project Content” 按鈕,從而 “src” 文件夾下的代碼文件就會被自動加進工程中。 接著關閉 FSP 配置界面返回到 Keil,然后進行一次編譯會彈出一個提示框提示工程結構發(fā)生了變化,點擊確定即可。 對于使用 e2 studio 的用戶則不需如此。
12.2.2. FSP配置
接下來我們要在fsp里配置芯片的引腳相關的屬性。
在打開 “FSP” 配置界面后, 在 “FSP” 配置界面里面點開 “Pins” -> “Ports” -> “P0” -> “P004” , 然后將連接到按鍵的IO引腳的 “Mode” 屬性配置為 “Input Mode” ,其他的屬性默認即可,LED引腳的配置同上節(jié)一樣配置。
Pin Configuration 頁面的 IOPORT 屬性介紹:
IOPORT 屬性介紹
IOPORT 屬性 | 描述 |
---|---|
---------------------------------------------------- |
模式 | IO引腳的工作模式,包括輸入模式和輸出模式。 |
---|---|
拔 | IO引腳是否上拉。 |
驅動器容量 | IO引腳的驅動能力設置。 |
輸出類型 | IO引腳的輸出類型。 可以選 CMOS 推挽輸出或開漏輸出。 |
配置完成之后的配置界面如圖所示。
配置完成之后按下快捷鍵“Ctrl + S”保存,最后點右上角的 “Generate Project Content” 圖標, 讓軟件根據我們的設置自動生成配置代碼即可。
對于 Keil 這邊 RASC 的 FSP 配置也是一樣的,需要先通過 RASC 軟件打開 Keil 工程相關的 FSP 配置界面。 具體的方法在前面的章節(jié)已經詳述過了,這里不再重復說明。
12.3. 按鍵程序思路
使用瑞薩的FSP對軟件設計的思路非常地簡單:首先通過R_IOPORT_Open函數初始化配置 LED 引腳,之后使用R_IOPORT_PinRead 函數來獲取當前引腳的電平的狀態(tài)。
12.3.1. R_IOPORT_PinRead 函數
通過 R_IOPORT_Open 函數初始化相應的引腳之后,我們使用R_IOPORT_PinRead函數來獲取引腳的電平的狀態(tài)。 我們通過分析R_IOPORT_PinRead函數,最主要的是通過p_pin_value這個枚舉類型來獲取IO的狀態(tài)。
fsp_err_t R_IOPORT_PinRead (ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin, bsp_io_level_t * p_pin_value)
注解
bsp_io_port_pin_t枚舉來決定需要獲取的引腳,通過bsp_io_level_t來獲取當前GPIO的狀態(tài)。
e_bsp_io_level枚舉
/* IOPORT 實例控制塊 */
typedef enum e_bsp_io_level
{
BSP_IO_LEVEL_LOW = 0, ///< Low
BSP_IO_LEVEL_HIGH ///< High
} bsp_io_level_t;
12.3.2. 主函數
在while(1)里不斷調用R_IOPORT_PinRead函數,并判斷其返回值,若返回值表示按鍵按下,則LED燈的點亮,否則LED燈滅掉。
完整代碼如下:
代碼清單 12-4:主函數
void hal_entry(void)
{
fsp_err_t err; //
err = R_IOPORT_Open(&g_ioport_ctrl, &g_bsp_pin_cfg); //初始化引腳
assert(FSP_SUCCESS == err); //判斷是否初始化成功
bsp_io_level_t Pin_P004; //定義獲取函數的結構體
while(1)
{
R_IOPORT_PinRead(&g_ioport_ctrl,BSP_IO_PORT_00_PIN_04, &Pin_P004); //運行函數并把獲取的數據賦值結構體
if(Pin_P004 == BSP_IO_LEVEL_LOW){ //判斷按鍵有沒有按下
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_HIGH);//點亮LED
}else if(Pin_P004 == BSP_IO_LEVEL_HIGH){ //判斷按鍵有沒有松開
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_LOW); //關閉LED
}
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
注解
使用這種方式來獲取IO口的狀態(tài)相對會比較復雜,下面將介紹一種新的寫法來簡化這一個過程,可以使程序看起來更簡單,讓我們開發(fā)起來更加的順暢。
12.4. 封裝 Key 設備驅動程序
R_key_read函數
/*
* 按鍵讀取函數 輸入引腳 返回當前引腳的狀態(tài)
* */
uint32_t R_key_read(bsp_io_port_pin_t key)
{
bsp_io_level_t state;
R_IOPORT_PinRead(&g_ioport_ctrl, key, &state);
return state;
}
我們這里對R_IOPORT_PinRead進行一次封裝,為什么要加這一層封裝呢,因為在對R_IOPORT_PinRead編程中多了一個指向型bsp_io_port_pin_t枚舉類型數據, 每當程序中增加一個需要讀取的IO口時我們就需要增加一個枚舉類型數據,這樣大大增加了我們程序的冗余程度。 我們封裝的過程中通過輸入當前的引腳,然后return返回當前的狀態(tài),這樣簡化了我們進行程序的編寫。
Key_Scan函數
/*
* 按鍵掃描函數判斷你的手是否松開
*/
uint32_t Key_Scan(bsp_io_port_pin_t key)
{
if(R_key_read(key) == BSP_IO_LEVEL_HIGH)
{
return KEY_OFF;
}
else
{
do //等待按鍵釋放
{
R_key_read(key);
} while (BSP_IO_LEVEL_LOW == R_key_read(key));
}
return KEY_ON;
}
這是一個對R_IOPORT_PinRead函數的使用案例,當按下按鍵的時候單片機會檢測手是否松開當手離開的時候返回KEY_ON數值,當按鍵沒有被按下的時候Key_Scan函數則返回KEY_OFF的數值, 下面是一個Key_Scan函數的實踐案列。
主函數hal_entry()
void hal_entry(void)
{
while(1)
{
if( Key_Scan(KEY_SW2_PIN) == KEY_ON ) //掃描判斷按鍵
{
LED1_ON; //宏定義LED開
LED2_ON;
LED3_ON;
}
if( Key_Scan(KEY_SW3_PIN) == KEY_ON )
{
LED1_OFF; //宏定義LED關
LED2_OFF;
LED3_OFF;
}
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
在 “hal_entry.c” 文件中添加對頭文件 “bsp_key.h” 的包含, 然后將 hal_entry 入口函數的內容改為如上所示。
12.5. 下載驗證
把編譯好的程序下載到開發(fā)板并復位,按下按鍵可以控制LED燈亮滅。
-
電路圖
+關注
關注
10316文章
10717瀏覽量
527210 -
led燈
+關注
關注
22文章
1592瀏覽量
107749 -
開發(fā)板
+關注
關注
25文章
4896瀏覽量
97058 -
GPIO
+關注
關注
16文章
1188瀏覽量
51834 -
按鍵檢測
+關注
關注
0文章
22瀏覽量
4819
發(fā)布評論請先 登錄
相關推薦
評論