STM32矩阵键盘实现方法收集

合集下载

单片机 矩阵键盘实验 实验报告

单片机 矩阵键盘实验 实验报告

单片机矩阵键盘实验实验报告一、实验目的本次实验的目的是掌握原理和方法,利用单片机识别矩阵键盘并编程实现键码转换功能,控制LED点亮显示。

二、实验原理矩阵键盘是一种由多路单向控制器输入行选择信号与列选择信号连接而形成的一一对应矩阵排列结构。

它广泛应用于电子游戏机、办公自动化设备、医疗仪器、家电控制及书籍检索机器等方面。

本次实验采用的矩阵键盘是一个4 x 4矩阵,用4段数码管显示按键编码,每个按键都可以输入一个代码,矩阵键盘连接单片机,实现一个软件算法来识别键码转化。

从而将键盘中的按键的按下信号转换成程序能够识别的代码,置于相应的输出结果中,控制LED点亮,从而可以实现矩阵键盘按键的转换功能。

三、实验方法1.硬件搭建:矩阵键盘(4行4列)与单片机(Atmel AT89C51)相连,选择引脚连接,并将数码管和LED与单片机相连以实现显示和点亮的功能。

2.程序设计:先建立控制体系,利用中断服务子程序识别和码值转换,利用中断服务子程序实现从按键的按下信号转换为程序能够识别的代码,然后将该代码段编写到单片机程序中,每次按下矩阵键盘按键后单片机给出相应的按键编码输出,用数码管显示,控制LED点亮。

四、实验结果经过实验,成功实现了矩阵键盘与单片机之间的连接,编写了中断服务子程序,完成了按键编码输出与LED点亮的功能。

实验完成后,数码管显示各种按键的编码,同时LED会点亮。

本次实验介绍了矩阵键盘的原理,论述了键码转换的程序设计步骤,并实验完成矩阵键盘与单片机的连接,实现用LED点亮以及数码管显示按键的编码。

通过本次实验,受益匪浅,使我对使用单片机编写算法与程序有了更深入的认识,同时丰富了课堂学习的内容,也使我更加热爱自己所学的专业。

基于STM32控制的矩阵键盘的仿真设计要点

基于STM32控制的矩阵键盘的仿真设计要点

题目:基于STM32控制的矩阵键盘的仿真设计课程名称:ARM 嵌入式系统学生姓名:张宇学生学号:1314030140系别:电子工程学院专业:通信工程年级:2013级指导教师:权循忠淮南师范学院电气信息工程学院12级电技专业电子线路CAD课程设计电子工程学院制2015年10月目录1摘要 (1)2关键字 (1)3引言 (1)4 STM32控制的矩阵键盘系统方案计制定 (1)4.1 系统总体设计方案 (1)4.2总体设计框图 (1)4.3矩阵键盘简介 (2)5 矩阵键盘设计原理分析 (2)5.1 STM32复位和时钟电路设计 (2)5.2 矩阵键盘电路的设计 (2)5.3按键去抖动 (3)5.4 按键显示电路 (3)6程序流程图 (4)7 总体电路图 (5)8 软件仿真 (5)9 总结 (6)10 参考文献: (6)11 附录 (7)基于STM32控制的矩阵键盘的仿真设计学生:张宇指导老师:权循忠电子工程学院通信工程1摘要矩阵键盘又称行列键盘,它是用四条I/O线作为行线,四条I/O线作为列线组成的键盘。

在行线和列线的每个交叉点上设置一个按键。

这样键盘上按键的个数就为4*4个。

这种行列式键盘结构能有效地提高ARM嵌入式系统中I/O口的利用率。

2关键字矩阵键盘行列键盘ARM嵌入式系统3引言随着人们生活水平的不断提升,ARM嵌入式无疑是人们追求的目标之一,它给人带来的方便也是不可否认的,要为现代人工作、科研、生活、提供更好更方便的设备就需要从ARM嵌入式技术入手,一切向若数字化控制,智能化控制方向发展。

用ARM嵌入式来控制的数码管显示按键也在广泛应用,其控制系统具有极大意义。

展望未来,急速的响应速度将成为个性的ARM嵌入式发展的趋势,越来越多的ARM嵌入式正如雨后春笋般涌现。

4 STM32控制的矩阵键盘系统方案计制定4.1 系统总体设计方案该智能键盘电路由ARM最小系统,矩阵键盘电路和显示电路组成,在常规的4*4矩阵键盘的基础上,通过改进实现了用4个IO口完成4*4矩阵键盘。

stm32F103状态机矩阵键盘

stm32F103状态机矩阵键盘

stm32F103状态机矩阵键盘矩阵键盘程序,作为麦知club小车项目的一部分,从IAR 状态机应用修改而来。

IAR7.4+STM32CUBEMX调试通过。

键盘行4,列3,每条线都有10K上拉电阻。

改到4×4矩阵也很容易。

行线设置为输入,针脚为浮空;列线设置为开漏输出。

不支持长按和组合键,主要是我不会改。

在OS中使用20ms任务周期调用。

以下贴出代码。

keypad.h[cpp] view plain copy /* * * Name: keypad.h */ #ifndef KEYPAD_H #define KEYPAD_H #include"stm32f1xx_hal.h" #include "pinname.h" #definePORT_KEY GPIOD #define COLS(GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6) // 读pin//#define In(GPIO_Pin) (PORT_KEY->IDR &GPIO_Pin) #define In(GPIO_Pin)HAL_GPIO_ReadPin(PORT_KEY, GPIO_Pin) // 写1到Pin //#define High(GPIO_Pin) PORT_KEY->BSRR = GPIO_Pin #define High(GPIO_Pin) HAL_GPIO_WritePin(PORT_KEY, GPIO_Pin, GPIO_PIN_SET) // 写0到Pin //#defineLow(GPIO_Pin) PORT_KEY->BSRR = (uint32_t)GPIO_Pin << 16 #define Low(GPIO_Pin)HAL_GPIO_WritePin(PORT_KEY, GPIO_Pin,GPIO_PIN_RESET) /* * 0 1 2 3 * 4 5 67 * 8 9 10 11 * 12 13 14 15 */ typedef enum { Key_Up = 0x02, Key_Left = 0x03,Key_Right = 0x04, Key_Down = 0x08, Key_On = 0x09, Key_Mode = 0x0a, Key_None = 0xFF } KeyPressed; static const int row_count = 4; static const int col_count = 3; uint16_t bus_out(void); void Keypad(void); char AnyKey(void); char SameKey(void); char ScanKey(void); void FindKey(void); voidClearKey(void); void Read(void); /** Start the keypad interrupt routines */ void Start(void); /** Stop the keypad interrupt routines */ void Stop(void); void Cols_out(uint16_t v); void Scan_Keyboard(void); KeyPressed getKey(void); #endif // KEYPAD_Hkeypad.c[cpp] view plain copy /* * * Name: keypad.cpp * */#include "keypad.h" // State: char KeyState; // Bit pattern after each scan: char KeyCode; // Output value fromthe virtual 74HC922: KeyPressed KeyValue; // KeyDown is set if key is down: char KeyDown; // KeyNew is set every time a new key is down: char KeyNew; // 映射表char KeyTable[12][2]; // Pin of Row uint16_t _rows[] = {KEYx0, KEYx1, KEYx2, KEYx3}; uint16_t _cols[] = {KEYy0, KEYy1, KEYy2}; //构造函数voidKeypad(void) { Stop(); KeyState = 0; // 按键状态初始0 } //扫描键盘voidScan_Keyboard(void){ switch (KeyState) { case 0:{ if (AnyKey()) { char scankey = ScanKey(); if (scankey != 0xff) KeyCode = scankey; KeyState = 1; } break; } case 1: { if (SameKey()) { FindKey(); KeyState = 2; } else KeyState = 0; break; } case 2: { if (SameKey()) { } elseKeyState = 3; break; } case 3:{ if (SameKey()) { KeyState = 2; } else { ClearKey(); KeyState = 0; } break; } } // func end } // 有键按下char AnyKey(void) { //Start(); //拉低int r = -1; for (r = 0; r < row_count; r++) { if (In(_rows[r]) == 0) // In macro break; } //Stop(); //恢复if (!(0 <= r && r < row_count)) return 0; else return 1; } // 键按下,键值相同char SameKey(void) { // char KeyCode_new = KeyCode; char KeyCode_new = ScanKey(); if (KeyCode == KeyCode_new) return 1; else return 0; }// 扫描键char ScanKey(void) { /* 行扫描*/ int r = -1; for (r = 0; r < row_count; r++) { if (In(_rows[r]) == 0) // In macro break; } /* 若没有找到有效行,返回*/ if (!(0 <= r&& r < row_count)) { return0xff; } /* 列扫描,找出行上哪个被拉低*/ int c = -1; for (c = 0; c < col_count;c++) { // 轮流输出列线Cols_out(~(1<< c)); if (In(_rows[r]) == 0) //In macro break; } /* 给所有的列重新充电*/ Start(); /* 若没有找到有效列,返回*/ if (!(0 <= c && c < col_count)) return 0xff; return r * col_count + c; } // FindKey compares KeyCode to values in KeyTable. // If match, KeyValue, KeyDown and KeyNew are updated. void FindKey(void) { KeyValue = (KeyPressed)KeyCode; KeyDown = 1; KeyNew = 1; } void ClearKey(void){ KeyDown = 0; } KeyPressed getKey(void){ if(KeyNew) { KeyNew = 0; return KeyValue; } else return Key_None; } void Start(void) { /* 列输出0,拉低行*/PORT_KEY->BRR = COLS; } void Stop(void){ /* 列输出1,使行不被拉低*/PORT_KEY->BSRR = COLS; } // cols bus output void Cols_out(uint16_t v) { if ((v & 0x01) > 0) //0b001 High(_cols[0]); else Low(_cols[0]); if ((v & 0x02) > 0) //0b010 High(_cols[1]);else Low(_cols[1]); if ((v & 0x04) > 0) //0b100 High(_cols[2]); elseLow(_cols[2]);} 按键操作可以改到寄存器操作,提高速度。

STM32矩阵键盘实现方法收集

STM32矩阵键盘实现方法收集

STM32矩阵键盘实现方法收集STM32用矩阵键盘,不带外部中断,可以多个按键同时按下C代码: STM32用矩阵键盘,不带外部中断,可以多个按键同时按下/**************矩阵键盘.h文件*********************************/#ifndef __COMMON_H#define __COMMON_H#include "stm32f10x.h"/* 4*4矩阵键盘*/void keyboard_init(void);void update_key(void);extern unsigned char key[4][4];#endif/**************矩阵键盘.c文件*****************************/ #include "common.h"struct io_port {GPIO_TypeDef *GPIO_x;unsigned short GPIO_pin;};static struct io_port key_output[4] = {{GPIOD, GPIO_Pin_0}, {GPIOD, GPIO_Pin_1},{GPIOD, GPIO_Pin_2}, {GPIOD, GPIO_Pin_3}};static struct io_port key_input[4] = {{GPIOD, GPIO_Pin_4}, {GPIOD, GPIO_Pin_5},{GPIOD, GPIO_Pin_6}, {GPIOD, GPIO_Pin_7}};unsigned char key[4][4];void keyboard_init(void){GPIO_InitTypeDef GPIO_InitStructure;unsigned char i;/* 键盘行扫描输出线输出高电平*//* PA0 PA1 PA2 PA3 输出*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOD, &GPIO_InitStructure);/* 键盘列扫描输入线键被按时输入高电平放开输入低电平*//* PA4 PA5 PA6 PA7 输入*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(GPIOD, &GPIO_InitStructure);for(i = 0; i < 4; i++){GPIO_SetBits(key_output[i].GPIO_x, key_output[i].GPIO_pin);}}void update_key(void){unsigned char i, j;for(i = 0; i < 4; i++) //i是输出口,依次置低电平{GPIO_ResetBits(key_output[i].GPIO_x,key_output[i].GPIO_pin);for(j = 0; j < 4; j++) //j是输入口,当键按下时导通被置为低电平{if(GPIO_ReadInputDataBit(key_input[j].GPIO_x,key_input[j].GPIO_pin) == 0){key[i][j] = 1;}else{key[i][j] = 0;}}GPIO_SetBits(key_output[i].GPIO_x, key_output[i].GPIO_pin);}}stm32 矩阵键盘这是硬件上的键盘规划// | 1 | 2 | 3 | 4 | ---line 1 PE6 //// --------------------------- //// | 5 | 6 | 7 | 8 | ---line 2 PE5 //// --------------------------- //// | 9 | 10| 11| 12| ---line 3 PE4 //// --------------------------- //// | 13| 14| 15| 16| ---line 4 PE3 //// --------------------------- //// | 17| 18| 19| 20| ---line 5 PE2 //// --------------------------- //// | | | | //// col1 col2 col3 col4 //// PE0 PB5 PB8 PB9 ////_________________________________________________//参考了下基于avr的矩阵键盘程序,耐着性子移植到符合上面硬件规划的stm32板子上。

stm32矩阵键盘原理

stm32矩阵键盘原理

STM32矩阵键盘原理详解引言矩阵键盘是一种常见的输入设备,广泛应用于电子产品中。

在STM32微控制器中,利用GPIO引脚实现矩阵键盘控制相对简单,本文将详细介绍STM32矩阵键盘的基本原理。

基本原理矩阵键盘由多个按键组成,通常采用行列式排列。

每个按键都由一个触点和一个按键外壳组成,触点一般为弹簧式结构,按下按键时触点接通,释放按键时触点断开。

矩阵键盘的连接方式矩阵键盘的每个按键都被分配一个行号和列号,通过行线和列线来连接按键和控制芯片。

STM32通过GPIO来控制行线和列线的电平,实现按键的扫描和检测。

在STM32中,行线和列线可以连接到不同的GPIO引脚上。

行线连接到输出引脚,列线连接到输入引脚。

这样,通过对行线的输出和对列线的输入,可以实现对矩阵键盘的扫描和检测。

矩阵键盘的扫描原理矩阵键盘的扫描原理可以简单描述为以下几个步骤:1.将所有行线设置为高电平,所有列线设置为输入模式。

2.逐个将行线设置为低电平,并同时检测列线引脚的电平状态。

3.如果某一列的输入引脚检测到低电平,表示该列对应的按键被按下。

4.通过行线和列线的对应关系,确定被按下的按键的行号和列号。

矩阵键盘的按键映射通过扫描后,可以得到被按下的按键的行号和列号,STM32可以根据行列号的映射关系将按键信息转化为相应的按键值。

通常,矩阵键盘的按键映射是通过二维数组来实现的。

数组的行号对应行线,列号对应列线。

数组中的元素对应按键的键值。

例如,要实现一个4x4的矩阵键盘,可以通过以下数组表示按键的映射关系:uint8_t keyMap[4][4] = {{ '1', '2', '3', 'A' },{ '4', '5', '6', 'B' },{ '7', '8', '9', 'C' },{ '*', '0', '#', 'D' }};通过行列号可以确定数组中的元素,从而得到按键的键值。

单片机矩阵键盘

单片机矩阵键盘

按键在闭合和断开时,触点会存在抖动现象:

数码管前三位显示一个跑表,从000到999之间以1%秒速度运行,当按下一个独立键盘时跑表停止,松开手后跑表继续运行。(用定时器设计表)。
在上题的基础上,用另外三个独立键盘实现按下第一个时计时停止,按下第二个时计时开始,按下第三个是计数值清零从头开始。
键盘处理程序就作这么一个简单的介绍,实际上,键盘、显示处理是很复杂的,它往往占到一个应用程序的大部份代码,可见其重要性,但说到,这种复杂并不来自于单片机的本身,而是来自于操作者的习惯等等问题,因此,在编写键盘处理程序之前,最好先把它从逻辑上理清,然后用适当的算法表示出来,最后再去写代码,这样,才能快速有效地写好代码
ANL A,#0FH
CJNE A,#0FH,KCODE;
MOV A,R1
SETB C RLC A JC NEXT2 NEXT3: MOV R0,#00H RET KCODE: MOV B,#0FBH NEXT4: RRC A INC B JC NEXT4 MOV A,R1 SWAP A NEXT5: RRC A INC B INC B INC B INC B 。
按下16个矩阵键盘依次在数码管上显示1-16的平方。如按下第一个显示1,第二个显示4...
识别方法
04
03
01
02
3、若有键被按下,应识别出是哪一个键闭合。方法是对键盘的行线进行扫描。P1.4-P1.7按下述4种组合依次输出: P1.7 1 1 1 0 P1.6 1 1 0 1 P1.5 1 0 1 1 P1.4 0 1 1 1 在每组行输出时读取P1.0-P1.3,若全为“1”,则表示为“0”这一行没有键闭合,否则有键闭合。由此得到闭合键的行值和列值,然后可采用计算法或查表法将闭合键的行值和列值转换成所定义的键值 4、为了保证键每闭合一次CPU仅作一次处理,必须去除键释放时的抖动。

STM32_实用矩阵键盘

STM32_实用矩阵键盘

实用矩阵键盘程序// PA0~PA3行控制线// PA4~PA7列控制线#include <stm32f10x_lib.h>#include "Delay.h"#include "key_4x4.h"#define KEY_X (0X0F << 0)#define KEY_Y (0XF0 << 0)unsigned char const Key_Tab[4][4]=//键盘编码表{{'D','C','B','A'},{'#','9','6','3'},{'0','8','5','2'},{'*','7','4','1'}};//没有得到键值返回0,否则返回相应的键值unsigned char Get_KeyValue(void){//使用线反转法u8 i=5,j=5;u16 temp1,temp2;RCC->APB2ENR|=1<<2; //使能PORTA时钟RCC->APB2ENR|=1<<0; //开启辅助时钟AFIO->MAPR&=0XF8FFFFFF; //清除MAPR的[26:24]AFIO->MAPR|=0X04000000; //关闭JTAGGPIOA->CRL&=0XFFFF0000;GPIOA->CRL|=0X00003333; //PA0~PA3 推挽输出GPIOA->CRL&=0X0000FFFF; //PA4~PA7 输入GPIOA->CRL|=0X44440000; //PA4~PA7默认上拉GPIOA->ODR&=~KEY_X ; //PA0~PA3置0if(((GPIOA->IDR >> 4) & 0X0F)<0x0f) // 读取PA12~PA15的值{delay_ms(70); //按键消抖if((GPIOA->IDR >>4 & 0x0f)<0x0f)temp1=(GPIOA->IDR >>4 & 0x0f);switch(temp1){case 0x0e:j=0;break;case 0x0d:j=1;break;case 0x0b:j=2;break;case 0x07:j=3;break;default:break;}}GPIOA->CRL&=0X0000FFFF;GPIOA->CRL|=0X33330000; //PA4~PA7 推挽输出GPIOA->CRL&=0XFFFF0000; //PA0~PA3 输入GPIOA->CRL|=0X00004444; //PA0~PA4 默认下拉GPIOA->ODR&=~KEY_Y; //PA4~PA7置0if((GPIOA->IDR & 0x0f)<0x0f){temp2=(GPIOA->IDR & 0x0f);switch(temp2){case 0x0e:i=0;break;case 0x0d:i=1;break;case 0x0b:i=2;break;case 0x07:i=3;break;default:break;}}if((i==5)||(j==5))return 0;elsereturn (Key_Tab[i][j]);}。

基于STM32的_矩阵键盘_驱动(中断方式)

基于STM32的_矩阵键盘_驱动(中断方式)

//==========================Keyboard.h===============================///*----------------------------------------------本程序实现4*5键盘的扫描从左到右,从上到下,键值依次为1-20------------------------------------------------*/#ifndef __KEYBOARD_H#define __KEYBOARD_H#include "stm32f10x_lib.h"//选择扫描模式#define Interrupt_Scan //中断扫描模式,要在NVIC在中打开对应中断/*可以自己定义其它扫描方式*/#define DELAY_COUNT 0x0FFFF/* 键盘控制引脚定义*/#define Keyboard_Control_Port GPIOD#define Keyboard_Line_1 GPIO_Pin_0#define Keyboard_Line_2 GPIO_Pin_1#define Keyboard_Line_3 GPIO_Pin_2#define Keyboard_Line_4 GPIO_Pin_3#define Keyboard_Line_5 GPIO_Pin_4#define Keyboard_Row_1 GPIO_Pin_5#define Keyboard_Row_2 GPIO_Pin_6#define Keyboard_Row_3 GPIO_Pin_7#define Keyboard_Row_4 GPIO_Pin_8#define Keyboard_LineBase Keyboard_Line_1#define Keyboard_RowBase Keyboard_Row_1#define Keyboard_Line (Keyboard_Line_1 | Keyboard_Line_2 | Keyboard_Line_3 | Keyboard_Line_4 | Keyboard_Line_5)#define Keyboard_Row (Keyboard_Row_1 | Keyboard_Row_2 | Keyboard_Row_3 | Keyboard_Row_4)#ifdef Interrupt_Scan /* 中断扫描模式宏定义*/#define Keyboard_EXTI_Row1 EXTI_Line5#define Keyboard_EXTI_Row2 EXTI_Line6#define Keyboard_EXTI_Row3 EXTI_Line7#define Keyboard_EXTI_Row4 EXTI_Line8#define Keyboard_EXTI_PortSource GPIO_PortSourceGPIOD#define Keyboard_EXTI_PinSource1 GPIO_PinSource5#define Keyboard_EXTI_PinSource2 GPIO_PinSource6#define Keyboard_EXTI_PinSource3 GPIO_PinSource7#define Keyboard_EXTI_PinSource4 GPIO_PinSource8#define Keyboard_IRQ_Channel EXTI9_5_IRQChannel#define Keyboard_EXTI_Line (Keyboard_EXTI_Row1 | Keyboard_EXTI_Row2 | Keyboard_EXTI_Row3 | Keyboard_EXTI_Row4)#endif /* 中断扫描模式宏定义*//* 键盘全局变量声明*/extern unsigned int Keyboard_Val ; //当前键值extern unsigned char Keyboard_Change_Flag ; //键值改变标志,读取新的键值后由主程序清零/* 键盘接口函数声明*/#ifdef Interrupt_Scanextern void Init_Keyboard_Interrupt(void) ;//键盘初始化为键盘扫描模式#endifextern void Delay(vu32 nCount) ; //用于延时消抖#endif /* KEYBOARD_H *///=================================================================////============================Keyboard.c=============================//#include "stm32f10x_lib.h"#include "Keyboard.h"unsigned int Keyboard_Val = 0 ; //保存键值unsigned char Keyboard_Change_Flag = 0 ; //键值改变标志,读取键值后清零/****************************************************************函数名称: Init_Keyboard_Interrupt功能: 键盘初始化为中断扫描模式初始化键盘需要的IO,Line1-Line5设为输出低Row1-Row4 接上拉电阻,使能下降沿中断参数: 无返回值: 无*****************************************************************/void Init_Keyboard_Interrupt(void){GPIO_InitTypeDef GPIO_InitStructure ;EXTI_InitTypeDef EXTI_InitStructure ;EXTI_DeInit() ;//Line1-Line5设为输出高GPIO_InitStructure.GPIO_Pin = Keyboard_Line ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;GPIO_Init(Keyboard_Control_Port ,&GPIO_InitStructure) ;GPIO_SetBits(Keyboard_Control_Port ,Keyboard_Line) ;//Row1-Row4设置为下拉输入,用来接收上升沿中断GPIO_InitStructure.GPIO_Pin = Keyboard_Row;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD ; //下拉输入GPIO_Init(Keyboard_Control_Port ,&GPIO_InitStructure) ;EXTI_ClearITPendingBit(Keyboard_EXTI_Row1) ; //清除中断标志位GPIO_EXTILineConfig(Keyboard_EXTI_PortSource ,Keyboard_EXTI_PinSource1 ); //Pinsource不能取或EXTI_ClearITPendingBit(Keyboard_EXTI_Row2) ; //清除中断标志位GPIO_EXTILineConfig(Keyboard_EXTI_PortSource ,Keyboard_EXTI_PinSource2 );EXTI_ClearITPendingBit(Keyboard_EXTI_Row3) ; //清除中断标志位GPIO_EXTILineConfig(Keyboard_EXTI_PortSource ,Keyboard_EXTI_PinSource3 );EXTI_ClearITPendingBit(Keyboard_EXTI_Row4) ; //清除中断标志位GPIO_EXTILineConfig(Keyboard_EXTI_PortSource ,Keyboard_EXTI_PinSource4 );//设置Row1-Row4为上升沿中断EXTI_InitStructure.EXTI_Line = Keyboard_EXTI_Line;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt ;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising ;EXTI_InitStructure.EXTI_LineCmd = ENABLE ;EXTI_Init(&EXTI_InitStructure) ;}/****************************************************************函数名称: Delay功能: 在扫描按键时,用于延时消抖参数: nCount -- 延时长度返回值: 无*****************************************************************/void Delay(vu32 nCount){for(; nCount!= 0;nCount--);}//==============================================================////=========================stm32f10x_it.c============================//void EXTI9_5_IRQHandler(void){unsigned long tmpFlag=0 ; //保存需要的中断标志位unsigned char i = 0 ; //循环标量tmpFlag = EXTI->PR & Keyboard_EXTI_Line ; //只取设定过的标志位EXTI->PR = tmpFlag ;switch(tmpFlag) //判断是哪个标志位置位{case Keyboard_EXTI_Row1:GPIO_ResetBits(Keyboard_Control_Port ,Keyboard_Line) ;for(i=0 ;i<5 ;i++) //扫描方式判断按键{GPIO_SetBits(Keyboard_Control_Port ,(Keyboard_LineBase<<i)) ;if(GPIO_ReadInputDataBit(Keyboard_Control_Port ,Keyboard_Row_1)) {Delay(DELAY_COUNT) ; //延时消抖if(GPIO_ReadInputDataBit(Keyboard_Control_Port ,Keyboard_Row_1)) {Keyboard_Val = 1+i ;Keyboard_Change_Flag = 1 ;break ;}}}GPIO_SetBits(Keyboard_Control_Port ,Keyboard_Line) ;EXTI->PR = Keyboard_EXTI_Row1 ; //清除中断标志break ;case Keyboard_EXTI_Row2:GPIO_ResetBits(Keyboard_Control_Port ,Keyboard_Line) ;for(i=0 ;i<5 ;i++)//扫描方式判断按键{GPIO_SetBits(Keyboard_Control_Port ,(Keyboard_LineBase<<i)) ;if(GPIO_ReadInputDataBit(Keyboard_Control_Port ,Keyboard_Row_2)) {Delay(DELAY_COUNT) ; //延时消抖if(GPIO_ReadInputDataBit(Keyboard_Control_Port ,Keyboard_Row_2)) {Keyboard_Val = 6+i ;Keyboard_Change_Flag = 1 ;break ;}}}GPIO_SetBits(Keyboard_Control_Port ,Keyboard_Line) ;EXTI->PR = Keyboard_EXTI_Row2 ; //清除中断标志break ;case Keyboard_EXTI_Row3:GPIO_ResetBits(Keyboard_Control_Port ,Keyboard_Line) ;for(i=0 ;i<5 ;i++) //扫描方式判断按键{GPIO_SetBits(Keyboard_Control_Port ,(Keyboard_LineBase<<i)) ;if(GPIO_ReadInputDataBit(Keyboard_Control_Port ,Keyboard_Row_3)) {Delay(DELAY_COUNT) ; //延时消抖if(GPIO_ReadInputDataBit(Keyboard_Control_Port ,Keyboard_Row_3)) {Keyboard_Val = 11+i ;Keyboard_Change_Flag = 1 ;break ;}}}GPIO_SetBits(Keyboard_Control_Port ,Keyboard_Line) ;EXTI->PR = Keyboard_EXTI_Row3 ; //清除中断标志break ;case Keyboard_EXTI_Row4:GPIO_ResetBits(Keyboard_Control_Port ,Keyboard_Line) ;for(i=0 ;i<5 ;i++) //扫描方式判断按键{GPIO_SetBits(Keyboard_Control_Port ,(Keyboard_LineBase<<i)) ;if(GPIO_ReadInputDataBit(Keyboard_Control_Port ,Keyboard_Row_4)) {Delay(DELAY_COUNT) ; //延时消抖if(GPIO_ReadInputDataBit(Keyboard_Control_Port ,Keyboard_Row_4)) {Keyboard_Val = 16+i ;Keyboard_Change_Flag = 1 ;break ;}}}GPIO_SetBits(Keyboard_Control_Port ,Keyboard_Line) ;EXTI->PR = Keyboard_EXTI_Row4 ; //清除中断标志break ;default:break ;}}//注:使用时要使能AFIO时钟和EXTI9_5IRQ //。

基于STM32的矩阵键盘识别算法研究与实现

基于STM32的矩阵键盘识别算法研究与实现

基于STM32的矩阵键盘识别算法研究与实现
陈丙山;侯志伟;张永平;景江鹏
【期刊名称】《电子制作》
【年(卷),期】2024(32)5
【摘要】矩阵键盘作为电子设备和仪器装置的人机交互重要媒介,针对数字密码锁、临时存取柜、电梯控制器等多按键应用场景的实际需求,本文采用STM32F103C8
作为主控器,详细介绍了以行列扫描法、行列线反法识别5×4(5行4列)矩阵键盘的优化算法,并提出了以16位并行端口I2C扩展器PCA9555a为纽带的矩阵键盘识
别方法。

实验结果表明,本文识别方法稳定可靠、简洁清晰、通用性好以及效率更高,能够有效满足相关应用场景中对多按键识别的实际应用需求。

【总页数】4页(P96-99)
【作者】陈丙山;侯志伟;张永平;景江鹏
【作者单位】兰州石化职业技术大学电子电气工程学院
【正文语种】中文
【中图分类】TP3
【相关文献】
1.基于STM32芯片的Wi-Fi语音识别风扇控制系统的设计与实现
2.基于STM32
的口罩识别及无接触测温系统的实现3.基于CNN的水表指针读数识别及STM32
实现方案设计4.基于STM32的手写数字识别平台的设计与实现5.基于STM32的农业物联网病虫害图像识别算法研究
因版权原因,仅展示原文概要,查看原文内容请购买。

STM32中反转法矩阵短按键的应用 测试通过

STM32中反转法矩阵短按键的应用 测试通过

#include"stm32f10x.h"//反转法测矩阵按键void Delay(__IO uint32_t t);void RCC_Config(void);void GPIO_Config(void);uint32_t Key_Scan(void);void GPIO_RConfig(void);void LED_Config(void);void Delay_ms(__IO uint32_t time);void Time_Delay(void);void GPIO_SetBits_Row(void);void GPIO_ResetBits_Row(void);void GPIO_SetBits_Col(void);void GPIO_ResetBits_Col(void);GPIO_InitTypeDef GPIO_InitStructure;static __IO uint32_t TimingDelay=0;uint32_t num=0;uint8_t j,i; //PA6 PA7 PB7 PA5uint8_t key[4][4]={0x01,0x05,0x09,0x0d, //PE150x02,0x06,0x0a,0x0e, //PE140x03,0x07,0x0b,0x0f, //PE130x04,0x08,0x0c,0x10 }; //PE11struct IO_Port{GPIO_TypeDef *GPIO_X;unsigned short GPIO_Pin;};static struct IO_Port key_row[4]={{GPIOE,GPIO_Pin_15},{GPIOE,GPIO_Pin_14}, {GPIOE,GPIO_Pin_13},{GPIOE,GPIO_Pin_11}};static struct IO_Port key_col[4]={{GPIOA,GPIO_Pin_6},{GPIOA,GPIO_Pin_7},{GPIOB,GPIO_Pin_7},{GPIOA,GPIO_Pin_5}};int main(void){uint32_t key=0;RCC_Config();LED_Config();SysTick_Config(72000);while(1){key=Key_Scan();switch(key){case 0x01:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x02:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x03:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x04:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x05:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x06:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x07:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x08:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x09:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x0a:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x0b:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x0c:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x0d:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x0e:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x0f:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;case 0x10:GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pi n_5)));break;default:break;}}}void GPIO_SetBits_Row(void){uint8_t i;for(i=0;i<4;i++){GPIO_SetBits(key_row[i].GPIO_X,key_row[i].GPIO_Pin);}}void GPIO_ResetBits_Row(void){uint8_t i;for(i=0;i<4;i++){GPIO_ResetBits(key_row[i].GPIO_X,key_row[i].GPIO_Pin);}}void GPIO_SetBits_Col(void){uint8_t i;for(i=0;i<4;i++){GPIO_SetBits(key_col[i].GPIO_X,key_col[i].GPIO_Pin);}}void GPIO_ResetBits_Col(void){uint8_t i;for(i=0;i<4;i++){GPIO_ResetBits(key_col[i].GPIO_X,key_col[i].GPIO_Pin);}}//反转法按键先让行输出低电平列输出高电平然后读列的状态如果为低电平//反转按键即列输出低电平行输出高电平依次检测行的输出如果为低电平则相应按键按下uint32_t Key_Scan(void){num=0;GPIO_Config();GPIO_ResetBits_Row();GPIO_SetBits_Col();for(i=0;i<4;i++){if(GPIO_ReadInputDataBit(key_col[i].GPIO_X,key_col[i].GPIO_Pin)==0){Delay(90000);if(GPIO_ReadInputDataBit(key_col[i].GPIO_X,key_col[i].GPIO_Pin)==0);GPIO_RConfig();GPIO_ResetBits_Col();GPIO_SetBits_Row();for(j=0;j<4;j++){if(GPIO_ReadInputDataBit(key_row[j].GPIO_X,key_row[j].GPIO_Pin)==0){while(GPIO_ReadInputDataBit(key_row[j].GPIO_X,key_row[j].GPIO_Pin)==0);num=key[j][i];}}}}return num;}void RCC_Config(void){SystemInit();RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB 2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO,ENABLE);}void GPIO_RConfig(void){GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;GPIO_Init(GPIOB,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;GPIO_Init(GPIOE,&GPIO_InitStructure);}void GPIO_Config(void){GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOE,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;GPIO_Init(GPIOB,&GPIO_InitStructure);}void LED_Config(void){GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStructure);GPIO_ResetBits(GPIOB,GPIO_Pin_5);}void Delay(__IO uint32_t t){uint32_t T=90000;while(T--);while(t--);}void Delay_ms(__IO uint32_t time){TimingDelay=time;while(TimingDelay!=0);}void Time_Delay(void){if(TimingDelay!=0){TimingDelay--;}}。

《STM32单片机仿真开发实例》教学课件 3.5 矩阵式键盘

《STM32单片机仿真开发实例》教学课件 3.5  矩阵式键盘
(现场操作演示...)
⑵ 字节操作法
与位操作法编程思路完全不同,字节操作法将矩阵式键盘控制行列的8个GPIO引脚 PB0~PB7作为一个字节,通过与流水灯类似的移位算法来实现行线的循环置高电平, 通过“位与”运算符来判定按键是否按下。这里GPIO驱动库选择LL库,与HAL相反, LL库只有对GPIO端口读写的API函数,而没有对某一个GPIO引脚读写的API函数。
3.5 矩阵式键盘
能力目标: 理解矩阵式键盘的电路组成及工作原理,掌握矩阵式键盘程序的编制
方法。 任务要求:
如下图所示是一个4×4的矩阵式键盘仿真电路,要求编程实现当按下 任意一个按钮时,数码管立即显示当前按下按钮对应的键值。
3.5.1 矩阵式键盘的电路组成
● “独立式按钮”,适合于按钮较少的应用场合;
3.5.3 任务程序的编写
即便是行扫描法这一种算法,实际程序的编制方法也不止一种,这里为读者介绍两 种具体的程序实现方法
⑴ 位操作法
位操作法来源于早期MCS-51单片机基于汇编语言的矩阵式键盘程序的实现方法,这 里GPIO的驱动库选择HAL库。由于HAL库中只有对某一个GPIO引脚进行读写的API函数 ,而没有对整个GPIO端口进行读写的API函数,因此在编制矩阵式键盘行扫描程序的 时候很容易,但是在编制数码管驱动程序的时候就很不方便了,下面程序中人为定义 了一个端口输出函数,结合查表法用于驱动数码管。
Y1
BTN E
Y2
BTN F
Y3
3.5.2 矩阵式键盘的行扫描法
行扫描法检测步骤如下: ① 初始化,所有行线均输出高电平; ② 仅行线X0输出低电平,检测按键0~按键3,若其中某个按键被按下,则相应的列 线将检测到低电平; ③ 仅行线X1输出低电平,检测按键4~按键7,若其中某个按键被按下,则相应的列 线将检测到低电平; ④ 仅行线X2输出低电平,检测按键8~按键B,若其中某个按键被按下,则相应的 列线将检测到低电平; ⑤ 仅行线X3输出低电平,检测按键C~按键F,若其中某个按键被按下,则相应的 列线将检测到低电平; ⑥ 回到步骤②,继续循环检测。

stm32 cubeide 矩阵运算

stm32 cubeide 矩阵运算

一、概述在嵌入式系统开发中,矩阵运算是一个非常常见且重要的计算任务。

而针对嵌入式系统的矩阵运算,STM32 CubeIDE是一款非常优秀的开发工具,它提供了丰富的库函数和资源,能够方便快捷地实现矩阵运算的功能。

本文将介绍如何在STM32 CubeIDE环境下进行矩阵运算的相关内容。

二、STM32 CubeIDE简介1. STM32 CubeIDE是STMicroelectronics公司推出的一款集成开发环境,针对STM32系列微控制器的开发而设计。

它基于Eclipse开发评台,集成了STM32CubeMX和GCC编译器,提供了丰富的模板和资源,方便用户进行嵌入式系统的开发和调试。

2. STM32 CubeIDE支持C和C++两种编程语言,能够充分发挥STM32系列微控制器的性能和功能,极大地简化了开发过程。

它还提供了强大的调试功能和丰富的外设库,方便用户进行各种类型的应用开发。

三、矩阵运算的重要性1. 矩阵运算是现代科学和工程领域中非常重要的数学工具,它广泛应用于信号处理、图像处理、控制系统等各个领域。

2. 在嵌入式系统中,由于资源受限的特点,如何高效地实现矩阵运算成为了一个挑战。

使用合适的开发工具和优化算法,能够极大地提高系统的性能和效率,为嵌入式系统的应用提供了强有力的支持。

四、STM32 CubeIDE下的矩阵运算1. 矩阵定义与初始化在STM32 CubeIDE环境下,可以通过调用相应的库函数,定义和初始化需要进行运算的矩阵。

可以使用标准C语言的二维数组来表示矩阵,并通过循环结构对矩阵进行初始化。

2. 矩阵运算的实现a. 加法运算在STM32 CubeIDE中,可以使用库函数实现矩阵的加法运算。

通过遍历矩阵各个元素,并将对应位置的元素相加,即可得到结果矩阵。

b. 乘法运算对于矩阵的乘法运算,STM32 CubeIDE提供了相应的库函数和优化算法,能够高效地实现矩阵的乘法操作。

用户可以直接调用这些函数,完成矩阵乘法运算,并获取结果矩阵。

单片机矩阵键盘编码

单片机矩阵键盘编码

单片机矩阵键盘编码是一种常用的输入设备接口技术,它通过将按键矩阵与单片机相连,实现对按键的识别和操作。

在单片机矩阵键盘编码中,常用的编码方式有行列式编码和扫描式编码等。

本文将介绍一种基于行列式编码的单片机矩阵键盘编码方法,以实现按键的识别和操作。

一、按键矩阵电路设计首先,我们需要设计一个按键矩阵电路,该电路由多个按键组成,并使用行线和列线进行连接。

常见的按键矩阵电路有4x4、5x5等不同规格,其中每个按键都通过行线和列线连接到单片机上。

二、行列式编码原理行列式编码是一种基于矩阵的按键编码方式,它通过将按键矩阵中的行线和列线进行编码,实现对按键的识别和操作。

具体来说,我们将按键矩阵中的行线和列线分别连接到单片机的I/O口上,并使用单片机的软件对I/O口的状态进行检测,从而识别出按键的位置和状态。

在行列式编码中,我们通常将行线划分为上、下两行,并将列线划分为左、右两列。

这样,当一个按键被按下时,其所在的行线和列线将同时发生变化。

通过检测行线和列线的状态变化,我们可以确定按键的位置和状态。

三、编码实现方法在实现单片机矩阵键盘编码时,我们需要编写相应的软件程序,对行线和列线的状态进行检测和判断。

通常,我们使用单片机的中断系统来实现按键的实时检测和响应。

具体来说,我们可以在单片机的I/O口上设置相应的中断请求,并在中断服务程序中对行线和列线的状态进行检测和判断。

当一个按键被按下时,其所在的行线和列线将同时发生变化。

我们可以通过比较当前状态和上一次状态的不同来确定按键的位置和状态。

如果某一行或某一列的状态发生变化,则说明有按键被按下。

我们可以通过判断该行或该列的状态变化来确定是哪个按键被按下。

四、总结单片机矩阵键盘编码是一种常用的输入设备接口技术,通过将按键矩阵与单片机相连,实现对按键的识别和操作。

在单片机矩阵键盘编码中,常用的编码方式有行列式编码和扫描式编码等。

本文介绍了一种基于行列式编码的单片机矩阵键盘编码方法,通过将按键矩阵中的行线和列线进行编码,实现对按键的识别和操作。

STM32_矩阵键盘

STM32_矩阵键盘

STM32 4*4矩阵键盘程序main.c#include "led.h"#include "delay.h"#include "sys.h"#include "key.h"#include "usart.h"#include "stdio.h"int main(void){int x;SystemInit();delay_init(72); //延时初始化NVIC_Configuration();uart_init(9600);LED_Init();KEY_Init(); //初始化与按键连接的硬件接口while(1){x=KEY_Scan(); //得到键值switch(x){case 0:// LED0=0;printf("D\n");break;case 1:printf("C\n");break;case 2:printf("B\n");break;case 3:printf("A\n");break;case 4:printf("#\n");break;case 5:printf("9\n");break;case 6:printf("6\n");break;case 7:printf("3\n");break;case 8:printf("0\n");break;case 9:printf("8\n");break;case 10:printf("5\n");break;case 11:printf("2\n");break;case 12:printf("*\n");break;case 13:printf("7\n");break;case 14:printf("4\n");break;case 15:printf("1\n");break;}}}/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////key.c //按键扫描#include "stm32f10x.h"#include "delay.h"#include "key.h"/*本文件的函数,主要实现矩阵键盘的功能。

32矩阵键盘c语言程序

32矩阵键盘c语言程序

32矩阵键盘c语言程序是一种使用c语言实现的矩阵键盘驱动程序,它是通过扫描键盘的行列来确定按键位置的。

键盘的每一行和每一列都连接到微控制器的端口上,当某个按键被按下时,对应的行和列的端口就会产生一个变化,从而可以确定按键的位置。

32矩阵键盘c语言程序的实现步骤如下:1. 定义键盘的行列数,以及对应的端口地址。

2. 初始化键盘的端口,将其设置为输入端口。

3. 扫描键盘的行列,当某个按键被按下时,对应的行和列的端口就会产生一个变化,从而可以确定按键的位置。

4. 根据按键的位置,执行相应的操作。

下面是一个32矩阵键盘c语言程序的示例:#include <stdio.h>#include <stdlib.h>#include <string.h>#define ROWS 4#define COLS 8#define KEYPAD_PORT 0x3Funsigned char keypad_scan() {unsigned char keypad_state[ROWS][COLS] = {{'1', '2', '3', 'A', '4', '5', '6', 'B'},{'7', '8', '9', 'C', '*', '0', '#', 'D'},{'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'},{'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T'}};unsigned char row, col;unsigned char keypad_value=0;// Set all rows to output and all columns to inputfor (row=0; row<ROWS; row++) {DDRD|= (1<< (row+4));DDRD&=~(1<<row);}// Scan each rowfor (row=0; row<ROWS; row++) {// Set the current row to lowPORTD&=~(1<<row);// Read the columnsfor (col=0; col<COLS; col++) {// If the current column is high, then the corresponding key is pressed if (PIND& (1<<col)) {keypad_value=keypad_state[row][col];break;}}// Set the current row to highPORTD|= (1<<row);}return keypad_value;}int main() {unsigned char keypad_value;// Initialize the keypad portDDRD|=0xF0;PORTD|=0x0F;// Continuously scan the keypadwhile (1) {keypad_value=keypad_scan();// If a key is pressed, print its valueif (keypad_value!=0) {printf("Key pressed: %c\n", keypad_value);}}return0;}这个程序首先定义了键盘的行列数,以及对应的端口地址。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

STM32用矩阵键盘,不带外部中断,可以多个按键同时按下C代码: STM32用矩阵键盘,不带外部中断,可以多个按键同时按下/**************矩阵键盘.h文件*********************************/#ifndef __COMMON_H#define __COMMON_H#include ""/* 4*4矩阵键盘 */void keyboard_init(void);void update_key(void);extern unsigned char key[4][4];#endif/**************矩阵键盘.c文件*****************************/#include ""struct io_port {GPIO_TypeDef *GPIO_x;unsigned short GPIO_pin;};static struct io_port key_output[4] = {{GPIOD, GPIO_Pin_0}, {GPIOD, GPIO_Pin_1},{GPIOD, GPIO_Pin_2}, {GPIOD, GPIO_Pin_3}static struct io_port key_input[4] = {{GPIOD, GPIO_Pin_4}, {GPIOD, GPIO_Pin_5},{GPIOD, GPIO_Pin_6}, {GPIOD, GPIO_Pin_7}};unsigned char key[4][4];void keyboard_init(void){GPIO_InitTypeDef GPIO_InitStructure;unsigned char i;/* 键盘行扫描输出线输出高电平 *//* PA0 PA1 PA2 PA3 输出*/= GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;= GPIO_Mode_Out_PP;= GPIO_Speed_50MHz;GPIO_Init(GPIOD, &GPIO_InitStructure);/* 键盘列扫描输入线键被按时输入高电平放开输入低电平 *//* PA4 PA5 PA6 PA7 输入*/= GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;= GPIO_Mode_IPU;GPIO_Init(GPIOD, &GPIO_InitStructure);for(i = 0; i < 4; i++){GPIO_SetBits(key_output[i].GPIO_x, key_output[i].GPIO_pin);}void update_key(void){unsigned char i, j;for(i = 0; i < 4; i++) PIO_x, key_output[i].GPIO_pin);for(j = 0; j < 4; j++) PIO_x, key_input[j].GPIO_pin) == 0){key[i][j] = 1;}else{key[i][j] = 0;}}GPIO_SetBits(key_output[i].GPIO_x, key_output[i].GPIO_pin);}}stm32 矩阵键盘这是硬件上的键盘规划// | 1 | 2 | 3 | 4 | ---line 1 PE6 //// --------------------------- //// | 5 | 6 | 7 | 8 | ---line 2 PE5 //// --------------------------- //// | 9 | 10| 11| 12| ---line 3 PE4 //// --------------------------- //// | 13| 14| 15| 16| ---line 4 PE3 //// --------------------------- //// | 17| 18| 19| 20| ---line 5 PE2 //// --------------------------- //// | | | | //// col1 col2 col3 col4 //// PE0 PB5 PB8 PB9 ////_________________________________________________//参考了下基于avr的矩阵键盘程序,耐着性子移植到符合上面硬件规划的stm32板子上。

volatile uint8_t key_flag = 0;void key_init(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;//key output= GPIO_Mode_Out_PP;= GPIO_Speed_50MHz;= GPIO_Pin_0;GPIO_Init(GPIOE,&GPIO_InitStructure);= GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9;GPIO_Init(GPIOB,&GPIO_InitStructure);//key input= GPIO_Mode_IPU;//上拉输入= GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6; GPIO_Init(GPIOE,&GPIO_InitStructure);}//判断是否有键按下函数,对键盘进行一次扫描//返回键盘接口状态,有键按下时返回键值;没有键按下返回无效标志位uint8_t Is_Key_PressOn(void){volatile uint8_t i,ScanCode;for(i=0;i<4;i++){switch(i) //扫描信号产生{case 0:GPIOE->BSRR = 0x00010000;//PE0 = 0;GPIOB->BSRR = 0x00000320;//PB5 = 1; PB8 = 1; PB9 = 1;key_flag = 1;break;case 1:GPIOE->BSRR = 0x00000001;//PE0 = 1;GPIOB->BSRR = 0x00200300;//PB5 = 0; PB8 = 1; PB9 = 1;key_flag = 2;break;case 2:GPIOE->BSRR = 0x00000001;//PE0 = 1;GPIOB->BSRR = 0x01000220;//PB5 = 1; PB8 = 0; PB9 = 1;key_flag = 3;break;case 3:GPIOE->BSRR = 0x00000001;//PE0 = 1;GPIOB->BSRR = 0x02000120;//PB5 = 1; PB8 = 1; PB9 = 0;key_flag = 4;break;default: key_flag = 0; break;}if((((uint8_t)GPIOE->IDR)|0x83)!=0xff)return ((uint8_t)GPIOE->IDR | 0x83);}return(PRESS_INVALID);}//找到闭合键,判断延时前后两次键值是否相同,如果相同则返回键值uint8_t Find_Key_PressOn(uint8_t KeyCode_before,uint8_t KeyCode_after) {if(KeyCode_before==KeyCode_after) return(KeyCode_after);else return(PRESS_INVALID);}//计算键值,根据返回的键值计算相应的返回值uint8_t Calc_Key_PressOn(uint8_t KeyCode){uint8_t TempNum; switch(KeyCode){case 0xBF:if(1==key_flag){TempNum = 1;break; }else if(2==key_flag) {TempNum = 2;break; }else if(3==key_flag) {TempNum = 3;break; }else if(4==key_flag) {TempNum = 4;break; }else break;case 0xDF:if(1==key_flag){TempNum = 5;break; }else if(2==key_flag){TempNum = 6;break; }else if(3==key_flag) {TempNum = 7;break; }else if(4==key_flag) {TempNum = 8;break; }else break;case 0xEF:if(1==key_flag){TempNum = 9;break; }else if(2==key_flag) {TempNum = 10;break; }else if(3==key_flag) {TempNum = 11;break; }else if(4==key_flag) {TempNum = 12;break; }else break;case 0xF7:if(1==key_flag){TempNum = 13;break; }else if(2==key_flag) {TempNum = 14;break; }else if(3==key_flag) {TempNum = 15;break; }else if(4==key_flag) {TempNum = 16;break; }else break;case 0xFB:if(1==key_flag){TempNum = 17;break; }else if(2==key_flag){TempNum = 18;break;}else if(3==key_flag){TempNum = 19;break;}else if(4==key_flag){TempNum = 20;break;}else break;default : TempNum=0;break; //发生错误时返回,无效标志}return(TempNum); //正常返回值为1~16}//键盘扫描主程序uint8_t Keyboard(void){uint8_t key_temp; //暂存键值的变量key_temp=Is_Key_PressOn(); //判断是否有键闭合// PORTC=key_temp; 调试过程中使用,正常运行时没用可以删除if (key_temp==PRESS_INVALID) //判断该次扫描中是否有键按下return(PRESS_INVALID); //没有闭合则建立无效标志elsedelay_nus(100); //闭合则延时key_temp=Find_Key_PressOn(key_temp,((uint8_t)GPIOE->IDR | 0x83)); //找到闭合键if (key_temp==PRESS_INVALID)return(key_temp); //若延时前后键值不相等则返回无效标志elsekey_temp=Calc_Key_PressOn(key_temp); //有效则计算键值while((((uint8_t)GPIOE->IDR)|0x83)!=0xff)//等待键放。

相关文档
最新文档