需要知識點
按鍵的原理
GPIO輸入輸出
寄存器操作,如果學過51或者對C語言很熟練這里不存在問題。寄存器說白了就是操作他們的位(寄存器我理解就是一串羊肉串,讓你找出你先吃哪個,比如我要吃中間的哪一個該怎么取出來)
矩陣按鍵原理
如果每個按鍵占用一個GPIO引腳,對于使用多個按鍵來說就是一種資源的浪費,因此當我們在設計時,可以考慮矩陣這種方式。本實驗使用4*4也就是16個按鍵。
矩陣按鍵相對于獨立按鍵稍微麻煩一點。4x4矩陣按鍵按照矩陣方式分別分為4行4列。主要有兩種方式,一種是逐行掃描、一種是行列掃描。
原理圖:
逐行掃描
通過在矩陣按鍵的每一條行線上輪流輸出低電平,檢測矩陣按鍵的列線,當檢測到的列線不全為高電平的時候,說明有按鍵按下。然后,根據當前輸出低電平的行號和檢測到低電平的列號組合,判斷是哪一個按鍵被按下。
行列掃描
首先,在全部行線上輸出低電平,檢測矩陣按鍵的列線,當檢測到的列線不全為高電平的時候,說明有按鍵按下,并判斷是哪一列有按鍵按下。
然后,反過來,在全部列線上輸出低電平,檢測矩陣按鍵的行線,當檢測到的行線不全為高電平的時候,說明有按鍵按下,并判斷是哪一行有按鍵按下。
最后,根據檢測到的行號和檢測的列號組合,以判斷是哪一個按鍵被按下。
按鍵檢測說白了就是按鍵按下之后是不是導通的,而其他沒有按下的按鍵是沒有導通的,代碼也不唯一,是多種多樣的。這里就需要操作寄存器或者使用庫函數的位操作。
流程
矩陣按鍵程序實現
根據是國內棉矩陣按鍵電路圖,編寫矩陣按鍵應用程序,輪徇K1~K8按鍵動作,當對應的按鍵按下后,返回對應的值:
矩陣按鍵:
/************
按鍵表盤為: 1 2 3 10
4 5 6 11
7 8 9 12
13 0 14 15
/K1-K4(行)/
/K5-K8(列)/
/************
K1--->PC0
K2--->PC1
K3--->PC2
K4--->PC3
K5--->PC4
K6--->PC5
K7--->PC6
***********************/
編程要點
RCC_AHB1PeriphClockCmd();
(2)編寫矩陣按鍵掃描程序。
(3)同2-STM32GPIO輸入之按鍵
矩陣按鍵引腳配置
/************************************************************************
* @brief KEY_Config 按鍵初始化配置
* @brief 列檢測初始化
* @param 無
* @retval 無
***********************************************************************/
static void KEY_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*開啟RCC時鐘*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
/*K1-K4(行)*/
GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);
//設置引腳為
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//設置引腳速度50MHZ
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/*K5-K8(列)*/
GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);
//設置引腳為推挽輸出模式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
//設置引腳速度50MHZ
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
矩陣按鍵掃描程序
/************************************************************************
* @brief KEY_4_4_Scan 掃描函數 矩陣按鍵掃描,返回一個鍵值
* @brief 列檢測初始化
* @param 無
* @retval uint8_t
***********************************
按鍵表盤為: 1 2 3 10
4 5 6 11
7 8 9 12
13 0 14 15
************************************
矩陣按鍵:
/************************************
按鍵表盤為: 1 2 3 10
4 5 6 11
7 8 9 12
13 0 14 15
/************************************
K1--->PC0
K2--->PC1
K3--->PC2
K4--->PC3
K5--->PC4
K6--->PC5
K7--->PC6
***********************************************************************/
uint8_t KEY_4_4_Scan(void)
{
u8 KeyVal = 0;
GPIO_Write(GPIOC, (GPIOC->ODR & 0xff00 | 0x000f)); // PC0-PC3全部輸出高。
if (((GPIOC->IDR & 0X00F0)) == 0x0000) // PC4-PC7為0則沒有按鍵按下(第一次檢測按鍵是否有按下)
{
return 0xFF;
}
else
{
Delay_ms(10); //軟件延時
if (((GPIOC->IDR & 0X00F0)) == 0x0000) // PC4-PC7為0則沒有按鍵按下(第二次檢測按鍵是否有按下)
{
return 0xFF;
}
}
GPIO_Write(GPIOC, ((GPIOC->ODR & 0xfff0) | 0x0001)); //僅將PC0置高
switch ((GPIOC->IDR & 0X00f0)) //第一行,從PC4開始拉高,其余為0,PC5-PC7一樣
{
case 0x0010:
KeyVal = 1; // PC4
break;
case 0x0020:
KeyVal = 2; // PC5
break;
case 0x0040:
KeyVal = 3; // PC6
break;
case 0x0080:
KeyVal = 10; // PC7
break;
}
while (((GPIOC->IDR & 0X00F0)) > 0) //等待按鍵釋放,
GPIO_Write(GPIOC, 0x0000); //重新讓PC0到PC3全部輸出低。
GPIO_Write(GPIOC, ((GPIOC->ODR & 0xfff0) | 0x0002)); //僅將PC1置高
switch ((GPIOC->IDR & 0X00F0)) //第一行,從PC4開始拉高,其余為0,PC5-PC7一樣
{
case 0x0010:
KeyVal = 4;
break;
case 0x0020:
KeyVal = 5;
break;
case 0x0040:
KeyVal = 6;
break;
case 0x0080:
KeyVal = 11;
break;
}
while (((GPIOC->IDR & 0X00F0)) > 0) //等待按鍵釋放
GPIO_Write(GPIOC, 0x0000); //重新讓PC0到PC3全部輸出低。
GPIO_Write(GPIOC, ((GPIOC->ODR & 0xfff0) | 0x0004)); //僅將PC2置高
switch ((GPIOC->IDR & 0X00F0))
{
case 0x0010:
KeyVal = 7;
break;
case 0x0020:
KeyVal = 8;
break;
case 0x0040:
KeyVal = 9;
break;
case 0x0080:
KeyVal = 12;
break;
}
while (((GPIOC->IDR & 0X00F0)) > 0)
GPIO_Write(GPIOC, 0x0000); //重新讓PC0到PC3全部輸出低。
GPIO_Write(GPIOC, ((GPIOC->ODR & 0xfff0) | 0x0008)); //僅將PC3置高
switch ((GPIOC->IDR & 0X00F0))
{
case 0x0010:
KeyVal = 13;
break;
case 0x0020:
KeyVal = 0;
break;
case 0x0040:
KeyVal = 15;
break;
case 0x0080:
KeyVal = 16;
break;
}
while (((GPIOC->IDR & 0X00F0)) > 0) //等待按鍵釋放
GPIO_Write(GPIOC, 0x0000); //重新讓PC0到PC3全部輸出低。
return KeyVal;
}
主函數
int main(void)
{
uint8_t Key_value = 0;
// 來到這里的時候,系統的時鐘已經被配置成72M。
LED_Config();
BEEP_Config();
SysTick_InitUP(); //配置10us中斷一次
USART_Config();
KEY_Init();
//矩陣按鍵代碼測試
while (1)
{
Key_value = KEY_4_4_Scan();
if (Key_value != 0xFF)
{
Delay_ms(200);
printf("Key_value=%d\\r\\n", Key_value);
}
Delay_ms(200);
}
}
實驗現象
-
單片機
+關注
關注
6035文章
44554瀏覽量
634653 -
STM32F103
+關注
關注
33文章
477瀏覽量
63600 -
矩陣按鍵
+關注
關注
0文章
28瀏覽量
8362
發布評論請先 登錄
相關推薦
評論