STM32 矩阵键盘控制
stm32键盘扫描电路原理
stm32键盘扫描电路原理
STM32键盘扫描电路原理是通过使用STM32微控制器的GPIO(通用输入/输出)功能和外部硬件电路,实现对键盘的扫描和检测。
1. 首先需要将键盘的按键连接到STM32微控制器的GPIO引脚上。
可以使用矩阵排列的方式来连接多个按键。
2. 然后将STM32微控制器的GPIO设置为输入模式,需要扫描的按键对应的GPIO引脚设置为输入。
3. 在代码中,设置一个循环,依次对每一个按键进行扫描。
可以使用GPIO外部中断来触发按键的扫描。
4. 在每次扫描过程中,将某一个按键对应的GPIO引脚设置为高电平,并读取引脚的状态。
5. 如果读取到的引脚状态为高电平,则表示该按键被按下。
6. 根据读取到的按键状态,可以执行相应的操作。
需要注意的是,如果使用矩阵排列的方式连接多个按键,还需要使用GPIO引脚的输出模式来控制矩阵的行和列。
总之,STM32键盘扫描电路原理是通过STM32微控制器的GPIO和外部硬件电路,实现对键盘的扫描和检测。
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微控制器中,利用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' }};通过行列号可以确定数组中的元素,从而得到按键的键值。
基于STM32控制的矩阵键盘的仿真设计
成绩课程论文题目:基于STM32控制的矩阵键盘的仿真设计课程名称: ARM 嵌入式系统学生姓名:张宇学生学号: 1314030140 系别:电子工程学院专业:通信工程年级: 2013级指导教师:权循忠电子工程学院制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矩阵键盘。
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的矩阵键盘识别算法研究与实现
陈丙山;侯志伟;张永平;景江鹏
【期刊名称】《电子制作》
【年(卷),期】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中反转法矩阵短按键的应用 测试通过
#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矩阵按键扫描
原理图各位大侠,这是我写的矩阵按键扫描程序,大家可以参考参考思维是和一般的按键扫描一样的,欢迎大家吐槽。
说明:微处理器:STM32F103VET6,开发软件:IAR for ARM。
(本来想复制文本文档的,发现代码层次感全变了,而且看着不舒服,所以采用截图的方式)其中需要注意的是:1、HKey是利用位带定义然后宏定义的,如下:PEin(n)利位带宏定义,(如果不明白可以百度一下stm32 位带操作)。
2、此函数是利用定时器设置30ms进行一次中断,而按键扫描的时间则由KeyScanEn确定3、关于KeyHData=HKey 编译器一直报警告,(但是程序跑起来为发现问题,不知道有没有什么潜在的风险)为了安全起见,大家可以直接去读寄存器也行4、按键消抖是利用计数器的方式,(说白了就是需要检测到两次后再处理)。
5、关于Delay(1)函数,试过不用也行,这里是置输入脚后马上检测输出感觉应该给点反应时间。
6、此函数只取出了键值,判断的话需要在另外的函数,最好不在中断函数里来做判断。
思路:1、首先置行线全为高,然后检测HEKEY这四位是不是全为0(当然,先要把这四个脚设置为下拉输入),如果不全是0,侧说明有按键按下。
2、然后依次将PE12-PE15置高进行扫描,(将一位置高后,然后检测输入引脚,如果输入引脚不是0x00,则说明按键在此行。
如若不是则循环置下一个引脚为高再判断),因为是循环扫描,此时循环次数就说明了在第几行。
所以键值=列键值(读取的键值)+ 循环的次数(行键值)。
3、取出按键的键值依次是:0x11 0x21 0x41 0x810x12 0x22 0x42 0x820x13 0x23 0x43 0x830x14 0x24 0x44 0x844、从上面的键值表可以看出:键值的后四位说明了按键的行数,键值的前四位则说明了按键所在的列数。
stm32矩阵键盘原理图及程序介绍
stm32矩阵键盘原理图及程序介绍STM32F0 系列产品基于超低功耗的ARM Cortex-M0 处理器内核,整合增强的技术和功能,瞄准超低成本预算的应用。
该系列微控制器缩短了采用8 位和16 位微控制器的设备与采用32 位微控制器的设备之间的性能差距,能够在经济型用户终端产品上实现先进且复杂的功能。
本文为大家介绍stm32矩阵键盘原理图及程序stm32矩阵键盘原理图主要实现:扫描矩阵键盘,将检测到的数据通过spi 通信发送到数码管显示。
主要步骤:1:初始化时钟void RCC_Configuration(void){//----------使用外部RC晶振-----------RCC_DeInit(); //初始化为缺省值RCC_HSEConfig(RCC_HSE_ON); //使能外部的高速时钟while(RCC_GetFlagStatus(RCC_FLAG_HSERDY)== RESET); //等待外部高速时钟使能就绪FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //Enable Prefetch Buffer FLASH_SetLatency(FLASH_Latency_2); //Flash 2 wait stateRCC_HCLKConfig(RCC_SYSCLK_Div1); //HCLK = SYSCLKRCC_PCLK2Config(RCC_HCLK_Div1); //PCLK2 = HCLKRCC_PCLK1Config(RCC_HCLK_Div2); //PCLK1 = HCLK/2RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); //PLLCLK = 8MHZ * 9 =72MHZRCC_PLLCmd(ENABLE); //Enable PLLCLKwhile(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)== RESET); //Wait till PLLCLK is ready RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //Select PLL as system clock。
《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_矩阵键盘
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"/*本文件的函数,主要实现矩阵键盘的功能。
基于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 #define Keyboard_Line_2 #define Keyboard_Line_3 #define Keyboard_Line_4 #define Keyboard_Line_5 #define Keyboard_Row_1 #define Keyboard_Row_2 #define Keyboard_Row_3 #define Keyboard_Row_4#define Keyboard_LineBase Keyboard_Line_1#define Keyboard_RowBaseKeyboard_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 #define Keyboard_EXTI_Row2#define Keyboard_EXTI_Row3#define Keyboard_EXTI_Row4EXTI_Line5EXTI_Line6 EXTI_Line7 EXTI_Line8 #define Keyboard_EXTI_PortSource GPIO_PortSourceGPIOD#define Keyboard_EXTI_PinSource1 GPIO_PinSource5#define Keyboard_EXTI_PinSource2 GPIO_PinSource6GPIO_Pin_0GPIO_Pin_1 GPIO_Pin_2 GPIO_Pin_3 GPIO_Pin_4 GPIO_Pin_5 GPIO_Pin_6GPIO_Pin_7 GPIO_Pin_8#define Keyboard_EXTI_PinSource3 GPIO_PinSource7#define Keyboard_EXTI_PinSource4 GPIO_PinSource8 #define Keyboard_IRQ_ChannelEXTI9_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 */ 写得不是很好,拿出来分享一下,希望大家能够提点建议!。
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;}这个程序首先定义了键盘的行列数,以及对应的端口地址。
矩阵式键盘控制数码管显
为了避免按键抖动造成的误判,微 控制器会对检测到的按键状态进行 去抖动处理,确保按键状态的准确 性。
键盘编码方式
行码与列码组合
01
每个按键都有一个唯一的行码和列码组合,用于标识按键的位
置。
编码表
02
建立一个包含所有按键行码和列码组合的编码表,用于将按键
位置映射到对应的编码值。
编码输出
03
键盘扫描程序
根据矩阵式键盘的原理,编写键盘扫描程序,实 现按键的检测与识别。
数码管显示程序
根据数码管的显示原理,编写数码管显示程序, 实现数码管的显示和控制。
主程序
主程序负责调用键盘扫描程序和数码管显示程序, 实现整个系统的控制逻辑。
系统调试与测试
硬件调试
检查硬件电路连接是否正确,确保各模块工作正常。
矩阵式键盘控制数码管显示系 统
目录
CONTENTS
• 矩阵式键盘控制原理 • 数码管显示技术 • 矩阵式键盘控制数码管显示系统设计 • 系统性能优化与改进 • 应用前景与发展趋势
01 矩阵式键盘控制原理
CHAPTER
矩阵式键盘结构
4x4矩阵式键盘结构
由16个按键组成的矩阵,行线和列线 交叉连接,每个按键位于行线和列线 的交叉点上。
根据按键位置在编码表中找到对应的编码值,通过微控制器输
出相应的编码信号,控制数码管显示相应的字符或数字。
02 数码管显示技术
CHAPTER
数码管工作原理
数码管由多个LED段组成,通过控制各段的亮灭来显示数字或字符。
数码管内部有8个LED段,通过电流的通断控制每个段的亮灭,从而显示不同的数字 或字符。
数码管驱动方式
点驱动方式
stm32 按键控制原理
stm32 按键控制原理STM32是一款ARM Cortex-M系列的32位微控制器,具有强大的处理性能和丰富的外设功能。
在STM32中,通过按键可以实现对系统的控制和交互操作。
按键控制原理可以分为硬件原理和软件原理两个方面。
我们来看硬件原理。
在STM32中,按键通常由机械按键、电容触摸按键等构成,不同类型的按键实现原理略有差异。
以机械按键为例,它通常由两个金属片组成,当按键按下时,两个金属片之间的触点会接通,形成一个闭合电路。
这个闭合电路可以由STM32的GPIO引脚监测到,从而产生按键事件。
对于机械按键,我们通常需要使用外部上拉电阻或下拉电阻来保证按键在未按下时保持高电平或低电平,以避免电平浮动。
同时,还需要注意消除按键的抖动问题。
按键的抖动是指当按键按下或释放时,由于机械结构的不稳定性,电路会产生一系列的毫秒级电平变动,造成电平上的干扰。
为了解决抖动问题,我们可以采用硬件消抖电路或者软件消抖算法来对按键信号进行稳定化处理。
在硬件连接方面,通常将按键的一个引脚连接到STM32的GPIO引脚,另一个引脚连接到电源或者地线上。
在软件层面,需要对GPIO引脚进行配置,设置为输入模式,并设置上拉或下拉电阻,以及相应的中断或轮询模式。
通过读取GPIO引脚的电平状态,可以判断按键的按下与释放,并执行相应的操作。
接下来,我们来看软件原理。
在STM32中,可以使用中断和轮询两种方式来检测按键事件。
中断方式是指在按键按下或释放时,通过中断服务函数来响应按键事件,实现对按键的及时处理。
轮询方式则是通过不断地检测GPIO引脚的电平状态,判断按键的状态变化,来实现对按键的处理。
两种方式各有优缺点,根据具体应用场景和系统需求,选择合适的方式进行按键控制。
在软件编程中,需要在初始化时配置GPIO引脚的模式、上拉/下拉电阻等参数,并注册中断回调函数。
如果使用中断方式,需要使能相应的中断,并编写中断服务函数来处理按键事件。
单片机控制的矩阵键盘
引言概述:
单片机控制的矩阵键盘已经成为现代电子设备中常见的输入方式之一。
该键盘具有结构简单、易于实现和使用方便等优点,广泛应用于各种电子产品中。
本文将对单片机控制的矩阵键盘的原理、设计和应用进行详细阐述。
正文内容:
一、矩阵键盘的原理
1.1矩阵键盘的基本结构
1.2矩阵键盘的电路连接方式
1.3矩阵键盘的工作原理
二、单片机控制的矩阵键盘的设计
2.1单片机的选择和配置
2.2键盘扫描算法的设计
2.3矩阵键盘的接口设计
2.4程序的编写和调试
2.5键盘输入的处理和应用
三、单片机控制的矩阵键盘的应用
3.1家电控制系统中的使用
3.2工控设备中的应用
3.3智能家居中的应用
3.4安防系统中的应用
3.5医疗设备中的应用
四、单片机控制的矩阵键盘的优缺点
4.1优点:
4.1.1结构简单,易于实现
4.1.2使用方便,操作灵活
4.1.3成本低廉,适合大规模生产
4.2缺点:
4.2.1键盘数量限制
4.2.2受到干扰可能导致误触发
五、单片机控制的矩阵键盘的发展趋势
5.1多功能键盘的设计
5.2无线键盘与蓝牙技术的结合
5.3舒适性与人机工程学的结合
5.4智能化与技术的应用
总结:
单片机控制的矩阵键盘是一种常见的输入方式,具有结构简单、易于实现和使用方便等优点。
本文对其原理、设计和应用进行
了详细阐述。
随着技术的不断发展,矩阵键盘在功能、无线化、舒适性和智能化方面也有了较大的进步和应用。
相信在未来,单片机控制的矩阵键盘将继续发挥重要作用,并与其他技术相结合,满足人们对输入设备的更高要求。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
// 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; //关闭JTAG
GPIOA->CRL&=0XFFFF0000;
GPIOA->CRL|=0X00003333; //PA0~PA3 推挽输出
GPIOA->CRL&=0X0000FFFF; //PA4~PA7 输入
GPIOA->CRL|=0X44440000; //PA4~PA7默认上拉
GPIOA->ODR&=~KEY_X ; //PA0~PA3置0
if(((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置0
if((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;
else
return (Key_Tab[i][j]);
}。