基於 STM32F407 使用 4*4 矩陣鍵盤(附完整程序)

基於STM32 使用 4*4 矩陣鍵盤


作者:李剴
出處:https://www.cnblogs.com/kevin-nancy/ 或者 https://blog.csdn.net/Kevin_8_Lee/article/details/88084516
歡迎轉載,但也請保留上面這段聲明。謝謝!(上面這個也是我寫的博客,只是在另一個平臺)
寫在前面:

  這是我第一次開始寫博客,可能寫的不是很好,也請大家諒解。
  我現在是在上大三,以前在學習過程中遇到過各種各樣的問題,關於51單片機,STM32單片機,最近在學習ARM11的Tiny6410; 以後還會更新一些C/C++/Qt等等方面的東西。
  關於寫博客這件事,其實 一直想寫博客記錄下來,但是因爲某些原因(懶),so , 沒有寫。現在開始,以後遇到單片機上或者編程上遇到的問題,並且自己很好地解決了,我就會在這裏記錄下來。希望通過博客記錄我的學習歷程並希望我所解決問題的過程能夠幫到需要的人,一起加油吧!!!


我是在STM32F407開發板上使用的4*4 矩陣鍵盤
下面是我所使用的開發板

在這裏插入圖片描述

在這裏插入圖片描述
1、首先介紹一下4*4矩陣鍵盤掃描原理

 呃。。。。。就不介紹了,[矩陣鍵盤原理描述](http://www.51hei.com/mcu/3815.html),這個寫的挺好的

2、Cube配置

在這裏插入圖片描述

  矩陣鍵盤從下到上依次接到STM32F407zg單片機的PD0~7引腳  ,其中,矩陣鍵盤下面的四個排針對應的是鍵盤的行(ROW)
  上面四個對應列(COL)   這裏我畫了一張圖來說明我所使用的

鍵盤原理示意

    PD0-3依次對應3-0行  PD4-7依次對應0-3列   這張圖裏可以看到我畫了兩個箭頭,下面就給大家說一下我的配置
   
    配置PD0~3爲推輓輸出   PD4~7爲下拉輸入,下圖是我在STM32CubeMX 5.1.0中配置的

在這裏插入圖片描述

    上面的箭頭,橫向的表示是單片機輸出給鍵盤的,豎向的是表示送給單片機的,也就是單片機配置的輸入引腳
    用來讀取PD4~7的電平

3、程序編寫

 因爲PD4~7爲上拉輸入,所以是處在一種高阻態(可以暫時理解爲高電平,就是四列都爲1)
 我以掃描第一行爲例講解  ,

在這裏插入圖片描述

在這裏插入圖片描述

    上述是軟件實現部分, GPIO->IDR和0xf7相與, 若是0xe7  則二進制位1110 0111,說明PD4變爲了0,所以第一列的按鍵
    s1按下

note:PD7對應二進制的最高位,PD0對應二進制的最低位

    後面以此類推

注意注意注意(重要的事情說三遍):在程序編寫完後,可能出現有些行未掃描,有些行的按鍵按下沒有通過串口返回信息
我的解決方法是,在每一行的掃描之前,將行所對應的引腳清空

在這裏插入圖片描述
這樣就不會有問題了

4、貼上完整程序:

#include "keypad.h"

#include "stdint.h"
#include "stm32f4xx_hal.h"



uint16_t Key_scan(void)
{
	uint16_t Key_val = 0;           // 按鍵掃描返回鍵值,初始化爲0
	                                // 強調一下: 這裏必須付一個初值0 否則串口打印出錯
	uint16_t temp;
    
	/*=========================以下代碼是按鍵掃描程序=========================*/
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET); // 先清空引腳狀態
	
	/*----------------------------Scan the 1st ROW----------------------------*/
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2, GPIO_PIN_SET);   // 設置PD0~2爲1
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_RESET);                       // 設置PD3爲0    二進制編碼爲 0111
	
    if((GPIOD->IDR & 0xF0) != 0xF0)
    {
		HAL_Delay(10);   // 10ms延時消抖
		if((GPIOD->IDR & 0xF0) != 0xF0)
		{                                                                       
			temp = (GPIOD->IDR & 0xF7);                                         // GPIOD->IDR寄存器爲端口輸入數據寄存器
			switch(temp)                                                        // 用來讀取GPIO口的電平狀態
			{
				case 0xE7 : Key_val = 1;
				break;

				case 0xD7 : Key_val = 2;
				break;

				case 0xB7 : Key_val = 3;
				break;

				case 0x77 : Key_val = 4;
				break;

				default  : Key_val = 0; break;

			}
		}
    }
	
	
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
	/*----------------------------Scan the 2nd ROW----------------------------*/
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_3, GPIO_PIN_SET);   
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);                       
	
    if((GPIOD->IDR & 0xF0) != 0xF0)
    {
		HAL_Delay(10);   // 10ms延時消抖
		if((GPIOD->IDR & 0xF0) != 0xF0)
		{
			temp = (GPIOD->IDR & 0xFB);
			switch(temp)
			{
				case 0xEB : Key_val = 5;
				break;

				case 0xDB : Key_val = 6;
				break;

				case 0xBB : Key_val = 7;
				break;

				case 0x7B : Key_val = 8;
				break;

				default  : Key_val = 0; break;

			}
		}
    }
	
	
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
	/*----------------------------Scan the 3rd ROW----------------------------*/
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_SET);   
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_RESET);                       
	
    if((GPIOD->IDR & 0xF0) != 0xF0)
    {
		HAL_Delay(10);   // 10ms延時消抖
		if((GPIOD->IDR & 0xF0) != 0xF0)
		{
			temp = (GPIOD->IDR & 0xFD);
			switch(temp)
			{
				case 0xED : Key_val = 9;
				break;

				case 0xDD : Key_val = 10;
				break;

				case 0xBD : Key_val = 11;
				break;

				case 0x7D : Key_val = 12;
				break;

				default   : Key_val = 0; break;

			}
		}
    }
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
	/*----------------------------Scan the 4th ROW----------------------------*/
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_SET);   
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0, GPIO_PIN_RESET);                       
	
    if((GPIOD->IDR & 0xF0) != 0xF0)
    {
		HAL_Delay(10);   // 10ms延時消抖
		if((GPIOD->IDR & 0xF0) != 0xF0)
		{
			temp = (GPIOD->IDR & 0xFE);
			switch(temp)
			{
				case 0xEE : Key_val = 13;
				break;

				case 0xDE : Key_val = 14;
				break;

				case 0xBE : Key_val = 15;
				break;

				case 0X7E : Key_val = 16;
				break;

				default  : Key_val = 0; break;

			}
		}
    }
	
	return Key_val;
}

5、 這是我的測試結果,見下圖:

在這裏插入圖片描述

這個程序中的編碼只是對應於我自己的接線,自己寫的時候要注意自己的接線
上面有些連接是我上傳的圖片,我自己看的時候看不到圖片,不知道什麼原因,但是點擊鏈接打開就是圖片了


2019/06/19補充

完整工程代碼下載連接

點擊上方藍字下載工程文件,完整的Cube配置工程以及IAR工程文件。
{PS: IAR跟keil都是一樣的,寫代碼來說沒什麼區別,不用擔心不可以移植,都是可以的,如果不懂的可以評論私聊我}


let‘s dream high   每個不滿意的現在,都有一個不努力的曾經。加油吧

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章