日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

stm32矩阵键盘学习笔记

發(fā)布時間:2023/12/10 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 stm32矩阵键盘学习笔记 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

矩陣鍵盤

  • 矩陣鍵盤簡介
  • 矩陣鍵盤掃描原理
  • 端口的配置
  • 相關(guān)函數(shù)的編寫
  • 主函數(shù)與其他
  • 串口的接線與矩陣鍵盤的接線
  • load與運行調(diào)試

矩陣鍵盤簡介

  • 什么是矩陣鍵盤
    矩陣鍵盤是單片機外部設(shè)備中所使用的排布類似于矩陣的鍵盤組,由于電路設(shè)計時需要更多的外部輸入,單獨的控制一個按鍵需要浪費很多的IO資源,所以就有了矩陣鍵盤,常用的矩陣鍵盤有4X4和8X8,其中用的最多的是4X4。
  • 矩陣鍵盤的原理
    矩陣鍵盤又稱為行列式鍵盤,它是用4條I/O線作為行線,4條I/O線作為列線組成的鍵盤。
    在行線和列線的每一個交叉點上,設(shè)置一個按鍵。這樣鍵盤中按鍵的個數(shù)是4×4個。
    這種行列式鍵盤結(jié)構(gòu)能夠有效地提高單片機系統(tǒng)中I/O口的利用率。由于單片機IO端口具有線與的功能,因此當(dāng)任意一個按鍵按下時,行和列都有一根線被線與,通過運算就可以得出按鍵的坐標(biāo)從而判斷按鍵鍵值。
  • 矩陣鍵盤掃描原理

  • 行掃描的原理:因為如果有按鍵按下的話,某一個輸入的引腳就會跟對應(yīng)的輸出引腳連接,因為輸出為高電平,所以對應(yīng)的輸入引腳會被拉高,讀取引腳的狀態(tài),判斷哪個引腳被拉高就可以知道哪一行有按鍵按下了;總的來說是通過高四位輸出高電平來對矩陣鍵盤進行逐行掃描,當(dāng)?shù)退奈唤邮盏降臄?shù)據(jù)不全為1的時候,說明有按鍵按下,然后通過接收到的數(shù)據(jù)是哪一位為0來判斷是哪一行按鍵被按下。
  • 再通過列操作模塊:
  • #define KEY_CLO0_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_RESET) #define KEY_CLO1_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_RESET) #define KEY_CLO2_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_14,Bit_RESET) #define KEY_CLO3_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_15,Bit_RESET)#define KEY_CLO0_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET) #define KEY_CLO1_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_SET) #define KEY_CLO2_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_14,Bit_SET) #define KEY_CLO3_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_15,Bit_SET)

    來進行列掃描。

    端口的配置

    介紹完矩陣鍵盤的掃描原理了我們該通過keli來實現(xiàn)我們想要的功能啦,首先我們要進行的就是對我們所需要的端口進行配置,如下:

    //端口的配置 void key_init(){GPIO_InitTypeDef GPIO_InitStruture;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //打開PB時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); //打開PE時鐘//定義PB12、PB13、PB14、PB15為推挽輸出 GPIO_InitStruture.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStruture.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStruture);//定義PD8、PD9、PD10、PD11為上拉輸入 分別定義為四行GPIO_InitStruture.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStruture.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;GPIO_Init(GPIOD,&GPIO_InitStruture); }

    相關(guān)函數(shù)的編寫

    配置完我們所需要的端口,接下來我們就應(yīng)該編寫相關(guān)函數(shù)啦。

  • 行掃描函數(shù):
  • //如果為1,代表沒有按鍵被按下,如果為0,代表有按鍵被按下 char KEY_ROW_SCAN(void) {//讀出行掃描狀態(tài)Key_row[0] = GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_8)<<3;Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_9)<<2);Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_10)<<1);Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11));if(Key_row[0] != 0x0f) //不是1111,代表肯定有一個0行{delay_ms(10); //消抖if(Key_row[0] != 0x0f)//0111 1011 1101 1110{ //printf("Key_Row_DATA = 0x%x\r\n",Key_row[0]);switch(Key_row[0]){case 0x07: //0111 判斷為該列第1行的按鍵按下return 1;case 0x0b: //1011 判斷為該列第2行的按鍵按下return 2;case 0x0d: //1101 判斷為該列第3行的按鍵按下return 3;case 0x0e: //1110 判斷為該列第4行的按鍵按下return 4;default :return 0;}}else return 0;}else return 0; }
  • 按鍵掃描函數(shù):
  • char KEY_SCAN(void) { char Key_Num=0; //1-16對應(yīng)的按鍵數(shù)char key_row_num=0; //行掃描結(jié)果記錄KEY_CLO0_OUT_LOW; if( (key_row_num=KEY_ROW_SCAN()) != 0 ){ while(KEY_ROW_SCAN() != 0); //消抖Key_Num = 0 + key_row_num;}KEY_CLO0_OUT_HIGH;KEY_CLO1_OUT_LOW; if( (key_row_num=KEY_ROW_SCAN()) != 0 ){ while(KEY_ROW_SCAN() != 0);Key_Num = 4 + key_row_num;}KEY_CLO1_OUT_HIGH;KEY_CLO2_OUT_LOW; if( (key_row_num=KEY_ROW_SCAN()) != 0 ){ while(KEY_ROW_SCAN() != 0);Key_Num = 8 + key_row_num;}KEY_CLO2_OUT_HIGH;KEY_CLO3_OUT_LOW; if( (key_row_num=KEY_ROW_SCAN()) != 0 ){while(KEY_ROW_SCAN() != 0);Key_Num = 12 + key_row_num;}KEY_CLO3_OUT_HIGH;return Key_Num; }

    主函數(shù)與其他

  • 主函數(shù):
  • #include "stm32f10x.h" #include "delay.h" #include "led.h" #include "key16.h" #include "stdio.h" #include "usart.h"int main(void) {vu8 key=0;char key_confirm;led_init();delay_init();key_init();NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);uart_init(115200);while(1){key_confirm = KEY_SCAN();if(key_confirm>0&&key_confirm<17){printf("Key_NUM = %d \r\n",key_confirm); //按下1-16個按鍵的操作printf("= = = = = = = = = = = \r\n"); } } }
  • key.c:
  • #include "key16.h" #include "delay.h"uint8_t Key_row[1]={0xff}; //定義一個數(shù)組,存放行掃描狀態(tài)//端口的配置 void key_init(){GPIO_InitTypeDef GPIO_InitStruture;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //打開PB時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); //打開PE時鐘//定義PB12、PB13、PB14、PB15為推挽輸出 GPIO_InitStruture.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStruture.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStruture);//定義PD8、PD9、PD10、PD11為上拉輸入 分別定義為四行GPIO_InitStruture.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStruture.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;GPIO_Init(GPIOD,&GPIO_InitStruture);}/****函數(shù)名:KEY_ROW_SCAN*功 能:按鍵行掃描*返回值:1~4,對應(yīng)1~4行按鍵位置*/ //如果為1,代表沒有按鍵被按下,如果為0,代表有按鍵被按下 char KEY_ROW_SCAN(void) {//讀出行掃描狀態(tài)Key_row[0] = GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_8)<<3;Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_9)<<2);Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_10)<<1);Key_row[0] = Key_row[0] | (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11));if(Key_row[0] != 0x0f) //不是1111,代表肯定有一個0行{delay_ms(10); //消抖if(Key_row[0] != 0x0f)//0111 1011 1101 1110{ //printf("Key_Row_DATA = 0x%x\r\n",Key_row[0]);switch(Key_row[0]){case 0x07: //0111 判斷為該列第1行的按鍵按下return 1;case 0x0b: //1011 判斷為該列第2行的按鍵按下return 2;case 0x0d: //1101 判斷為該列第3行的按鍵按下return 3;case 0x0e: //1110 判斷為該列第4行的按鍵按下return 4;default :return 0;}}else return 0;}else return 0; }/****函數(shù)名:KEY_SCAN*功 能:4*4按鍵掃描*返回值:0~16,對應(yīng)16個按鍵*/ char KEY_SCAN(void) { char Key_Num=0; //1-16對應(yīng)的按鍵數(shù)char key_row_num=0; //行掃描結(jié)果記錄KEY_CLO0_OUT_LOW; if( (key_row_num=KEY_ROW_SCAN()) != 0 ){ while(KEY_ROW_SCAN() != 0); //消抖Key_Num = 0 + key_row_num;}KEY_CLO0_OUT_HIGH;KEY_CLO1_OUT_LOW; if( (key_row_num=KEY_ROW_SCAN()) != 0 ){ while(KEY_ROW_SCAN() != 0);Key_Num = 4 + key_row_num;//printf("Key_Clo_2\r\n");}KEY_CLO1_OUT_HIGH;KEY_CLO2_OUT_LOW; if( (key_row_num=KEY_ROW_SCAN()) != 0 ){ while(KEY_ROW_SCAN() != 0);Key_Num = 8 + key_row_num;//printf("Key_Clo_3\r\n");}KEY_CLO2_OUT_HIGH;KEY_CLO3_OUT_LOW; if( (key_row_num=KEY_ROW_SCAN()) != 0 ){while(KEY_ROW_SCAN() != 0);Key_Num = 12 + key_row_num;}KEY_CLO3_OUT_HIGH;return Key_Num; }
  • key.h:
  • #ifndef _KEY16_H #define _KEY16_H#include "sys.h" #include "stm32f10x.h"#include <string.h>void key_init(); char KEY_SCAN(void); char KEY_ROW_SCAN(void); void HW_KEY_FUNCTION(void);#define KEY_CLO0_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_RESET) #define KEY_CLO1_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_RESET) #define KEY_CLO2_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_14,Bit_RESET) #define KEY_CLO3_OUT_LOW GPIO_WriteBit(GPIOB,GPIO_Pin_15,Bit_RESET)#define KEY_CLO0_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET) #define KEY_CLO1_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_13,Bit_SET) #define KEY_CLO2_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_14,Bit_SET) #define KEY_CLO3_OUT_HIGH GPIO_WriteBit(GPIOB,GPIO_Pin_15,Bit_SET)#endif

    串口的接線與矩陣鍵盤的接線

  • 首先我們先接串口,把串口的VCC和GND分別接到主板上的3.3V和GND上(注意要把串口上的插線帽調(diào)整到3.3V,不然容易把板子燒壞,板子燒壞了那可就成大xx了),然后再把串口上的TXD和RXD分別連到主板的RXD和TXD。
  • 然后我們來接矩陣鍵盤,要用到八根線,R1 ~ R4分別連到主板上的PD8 ~ PD11,C1 ~ C4分別連到主板上的PB12 ~ PB15.
  • load與運行調(diào)試

    好啦,所有準(zhǔn)備工作都完成啦!!又到了我們激動人心的時刻啦!!
    運行成功圖如下:

    over。

    總結(jié)

    以上是生活随笔為你收集整理的stm32矩阵键盘学习笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。