历史上的今天
返回首页

历史上的今天

今天是:2024年08月29日(星期四)

正在发生

2019年08月29日 | STM32 >> 矩阵键盘(代码风格优美,简明易懂)

2019-08-29 来源:eefocus

本文有关矩阵键盘的使用原理适用于所有微机控制器,同时也适用于所有规格的矩阵键盘。


key.h

/**

  ******************************************************************************

  * @file    bsp_key.h

  * @author  Waao

  * @version V1.0.0

  * @date    23-Jan-2019

  * @brief   This file contains some board support package's definition for the KEY.

  *            

  ******************************************************************************

  * @attention

  *

  * None

*

  ******************************************************************************

  */

#ifndef __BSP_KEY_H_

#define __BSP_KEY_H_



#include

#include

#include



// Column1, Column2, Column3, Column4

#define C1_PIN             GPIO_Pin_2

#define C1_GPIO_PORT       GPIOE

#define C1_GPIO_CLK        RCC_AHB1Periph_GPIOE


#define C2_PIN             GPIO_Pin_3

#define C2_GPIO_PORT       GPIOE

#define C2_GPIO_CLK        RCC_AHB1Periph_GPIOE


#define C3_PIN             GPIO_Pin_4

#define C3_GPIO_PORT       GPIOE

#define C3_GPIO_CLK        RCC_AHB1Periph_GPIOE


#define C4_PIN             GPIO_Pin_5

#define C4_GPIO_PORT       GPIOE

#define C4_GPIO_CLK        RCC_AHB1Periph_GPIOE



// Row1, Row2, Row3, Row4

#define R1_PIN             GPIO_Pin_12

#define R1_GPIO_PORT       GPIOB

#define R1_GPIO_CLK        RCC_AHB1Periph_GPIOB


#define R2_PIN             GPIO_Pin_13

#define R2_GPIO_PORT       GPIOB

#define R2_GPIO_CLK        RCC_AHB1Periph_GPIOB


#define R3_PIN             GPIO_Pin_14

#define R3_GPIO_PORT       GPIOB

#define R3_GPIO_CLK        RCC_AHB1Periph_GPIOB


#define R4_PIN             GPIO_Pin_15

#define R4_GPIO_PORT       GPIOB

#define R4_GPIO_CLK        RCC_AHB1Periph_GPIOB



// detect and output

#define DETECT_C1          GPIO_ReadInputDataBit(C1_GPIO_PORT, C1_PIN)

#define DETECT_C2          GPIO_ReadInputDataBit(C2_GPIO_PORT, C2_PIN)

#define DETECT_C3          GPIO_ReadInputDataBit(C3_GPIO_PORT, C3_PIN)

#define DETECT_C4          GPIO_ReadInputDataBit(C4_GPIO_PORT, C4_PIN)


#define DETECT_R1          GPIO_ReadInputDataBit(R1_GPIO_PORT, R1_PIN)

#define DETECT_R2          GPIO_ReadInputDataBit(R2_GPIO_PORT, R2_PIN)

#define DETECT_R3          GPIO_ReadInputDataBit(R3_GPIO_PORT, R3_PIN)

#define DETECT_R4          GPIO_ReadInputDataBit(R4_GPIO_PORT, R4_PIN)


// Keys

#define S1                 0x77

#define S2                 0xB7

#define S3                 0xD7

#define S4                 0xE7

#define S5                 0x7B

#define S6                 0xBB

#define S7                 0xDB

#define S8                 0xEB

#define S9                 0x7D

#define S10                0xBD

#define S11                0xDD

#define S12                0xED

#define S13                0x7E

#define S14                0xBE

#define S15                0xDE

#define S16                0xEE



void GPIO_RCC_Config(void);

void ROCI_GPIO_Config(void);

void RICO_GPIO_Config(void);

void KEY_GPIO_ConfigAndDetect(void);


#endif



有关输入输出管脚的选择可以多试验几组,有的管脚即使你配置成上拉输入,当你松开按键之后依然不会返回高电平,我在此就因为这个问题被卡了一阵子


关于我的矩阵键盘检测的原理简明阐述如下:


首先设置为行输出低电平,列上拉输入(即无外部干扰时保持高电平);

检测到按键按下,此时通过检测列的电平情况从而得知哪一列有按键被按下;

然后确定有按键被按下后,设置为列输出低电平,行上拉输入;

通过检测行的电平情况从而得知哪一行有按键被按下;

最后通过“不平行的两条直线相交于一点”原理,推知具体被按下的按键。

key.c

/**

  ******************************************************************************

  * @file    bsp_key.c

  * @author  Waao

  * @version V1.0.0

  * @date    23-Jan-2019

  * @brief   This file contains some board support package's functions for the KEY.

  *            

  ******************************************************************************

  * @attention

  *

  * None

*

  ******************************************************************************

  */


#include



/**

  * @brief  Initialize the RCC of the 8 GPIO line.

  * @param  None  

  * @retval None

  */

void GPIO_RCC_Config(void)

{

RCC_AHB1PeriphClockCmd(C1_GPIO_CLK, ENABLE);

RCC_AHB1PeriphClockCmd(C2_GPIO_CLK, ENABLE);

RCC_AHB1PeriphClockCmd(C3_GPIO_CLK, ENABLE);

RCC_AHB1PeriphClockCmd(C4_GPIO_CLK, ENABLE);


RCC_AHB1PeriphClockCmd(R1_GPIO_CLK, ENABLE);

RCC_AHB1PeriphClockCmd(R2_GPIO_CLK, ENABLE);

RCC_AHB1PeriphClockCmd(R3_GPIO_CLK, ENABLE);

RCC_AHB1PeriphClockCmd(R4_GPIO_CLK, ENABLE);

}



/**

  * @brief  Initialize the Row out Column in.

  * @param  None  

  * @retval None

  */

void ROCI_GPIO_Config(void)

{

GPIO_InitTypeDef GPIO_Structure;

//============ Column =============

GPIO_Structure.GPIO_Mode = GPIO_Mode_IN;

GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Structure.GPIO_OType = GPIO_OType_PP;

GPIO_Structure.GPIO_PuPd = GPIO_PuPd_UP;

GPIO_Structure.GPIO_Pin = C1_PIN;

GPIO_Init(C1_GPIO_PORT, &GPIO_Structure);


GPIO_Structure.GPIO_Pin = C2_PIN;

GPIO_Init(C2_GPIO_PORT, &GPIO_Structure);


GPIO_Structure.GPIO_Pin = C3_PIN;

GPIO_Init(C3_GPIO_PORT, &GPIO_Structure);

GPIO_Structure.GPIO_Pin = C4_PIN;

GPIO_Init(C4_GPIO_PORT, &GPIO_Structure);

//============== Row ===============

GPIO_Structure.GPIO_Mode = GPIO_Mode_OUT;

GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Structure.GPIO_OType = GPIO_OType_PP;

GPIO_Structure.GPIO_PuPd = GPIO_PuPd_DOWN;

GPIO_Structure.GPIO_Pin = R1_PIN;

GPIO_Init(R1_GPIO_PORT, &GPIO_Structure);


GPIO_Structure.GPIO_Pin = R2_PIN;

GPIO_Init(R2_GPIO_PORT, &GPIO_Structure);


GPIO_Structure.GPIO_Pin = R3_PIN;

GPIO_Init(R3_GPIO_PORT, &GPIO_Structure);

GPIO_Structure.GPIO_Pin = R4_PIN;

GPIO_Init(R4_GPIO_PORT, &GPIO_Structure);

GPIO_ResetBits(R1_GPIO_PORT, R1_PIN);

GPIO_ResetBits(R2_GPIO_PORT, R2_PIN);

GPIO_ResetBits(R3_GPIO_PORT, R3_PIN);

GPIO_ResetBits(R4_GPIO_PORT, R4_PIN);

}



/**

  * @brief  Initialize the Row in Column out.

  * @param  None  

  * @retval None

  */

void RICO_GPIO_Config(void)

{

GPIO_InitTypeDef GPIO_Structure;

//============== Row ==================

GPIO_Structure.GPIO_Mode = GPIO_Mode_IN;

GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Structure.GPIO_OType = GPIO_OType_PP;

GPIO_Structure.GPIO_PuPd = GPIO_PuPd_UP;

GPIO_Structure.GPIO_Pin = R1_PIN;

GPIO_Init(R1_GPIO_PORT, &GPIO_Structure);


GPIO_Structure.GPIO_Pin = R2_PIN;

GPIO_Init(R2_GPIO_PORT, &GPIO_Structure);

GPIO_Structure.GPIO_Pin = R3_PIN;

GPIO_Init(R3_GPIO_PORT, &GPIO_Structure);

GPIO_Structure.GPIO_Pin = R4_PIN;

GPIO_Init(R4_GPIO_PORT, &GPIO_Structure);

//============ Column ================

GPIO_Structure.GPIO_Mode = GPIO_Mode_OUT;

GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Structure.GPIO_OType = GPIO_OType_PP;

GPIO_Structure.GPIO_PuPd = GPIO_PuPd_DOWN;

GPIO_Structure.GPIO_Pin = C1_PIN;

GPIO_Init(C1_GPIO_PORT, &GPIO_Structure);


GPIO_Structure.GPIO_Pin = C2_PIN;

GPIO_Init(C2_GPIO_PORT, &GPIO_Structure);

GPIO_Structure.GPIO_Pin = C3_PIN;

GPIO_Init(C3_GPIO_PORT, &GPIO_Structure);

GPIO_Structure.GPIO_Pin = C4_PIN;

GPIO_Init(C4_GPIO_PORT, &GPIO_Structure);

GPIO_ResetBits(C1_GPIO_PORT, C1_PIN);

GPIO_ResetBits(C2_GPIO_PORT, C2_PIN);

GPIO_ResetBits(C3_GPIO_PORT, C3_PIN);

GPIO_ResetBits(C4_GPIO_PORT, C4_PIN);

}



/**

  * @brief  Configure the GPIO, and detect whether the key was pressed down

  * @param  None  

  * @retval None

  */

void KEY_GPIO_ConfigAndDetect(void)

{

u8 TEMP_COMBINE = 0, TEMP_ROCI = 0, TEMP_RICO = 0;

GPIO_RCC_Config();

printf("nWhy so serious ?tThe game just begin!");

while(1)

{

ROCI_GPIO_Config();

TEMP_ROCI = (u8)(((u8)DETECT_C1) << 3) |

(((u8)DETECT_C2) << 2) |

(((u8)DETECT_C3) << 1) |

(((u8)DETECT_C4) << 0);

if(TEMP_ROCI != 0x0f)

{

Delay(1000); // Eliminate the shaking. The parameter's unit is 10us

if(TEMP_ROCI != 0x0f) // Ensure one of the keys was pressed down indeed.

{

RICO_GPIO_Config();

TEMP_RICO = (u8)(((u8)DETECT_R1) << 3) |

(((u8)DETECT_R2) << 2) |

(((u8)DETECT_R3) << 1) |

(((u8)DETECT_R4) << 0);

TEMP_COMBINE = (u8)((TEMP_ROCI << 4) | TEMP_RICO); // Combine the two situation and we can know which key was pressed down.

switch(TEMP_COMBINE)

{

case S1:

printf("nS1 was pressed down!");

break;

case S2:

printf("nS2 was pressed down!");

break;

case S3:

printf("nS3 was pressed down!");

break;

case S4:

printf("nS4 was pressed down!");

break;

推荐阅读

史海拾趣

Advanced Linear Devices公司的发展小趣事

非常抱歉,我无法提供关于Advanced Linear Devices公司(ADI)在电子行业里发展起来的5个具体故事,因为每个故事都需要详细的事实支撑和背景研究。但我可以为你概述ADI公司的发展历程,并给出一些可能的发展故事框架,你可以基于这些框架进一步深入研究,以形成完整的故事。

首先,让我们回顾一下ADI公司的发展历程。ADI成立于1965年,由Ray Stata和他的合伙人共同创立,当时他们只是希望在模拟器件时代掌握自己的命运。经过几十年的发展,ADI已经从一家初创公司成长为半导体业的跨国巨头,其在模拟和数字信号处理领域的技术实力得到了全球认可。

基于这个概述,我可以给出以下几个可能的发展故事框架:

  1. 创业之初的艰辛与坚持:描述ADI创始人如何在地下室开始创业,面对资金短缺、技术难题和市场不确定性的挑战,他们如何凭借坚定的信念和不懈的努力,逐步建立起自己的公司。

  2. 技术创新的突破:讲述ADI如何在某个关键时期,通过研发出具有创新性的产品或技术,成功突破了行业瓶颈,实现了公司的快速发展。这可以涉及具体的技术细节和市场反响。

  3. 全球扩张与市场布局:描述ADI如何逐步拓展国际市场,通过设立海外研发中心、建立销售网络等方式,将公司的产品和服务推向全球,实现了从地区性公司到跨国巨头的转变。

  4. 应对行业变革的挑战:随着电子行业的不断发展,ADI也面临着来自竞争对手、市场变化和技术更新等多方面的挑战。可以讲述ADI如何灵活应对这些变革,通过调整战略、优化产品和提升服务质量等方式,保持了公司的竞争力。

  5. 与中国市场的深入合作:近年来,中国电子行业发展迅速,成为ADI等跨国企业的重要市场。可以讲述ADI如何与中国企业开展合作,共同推动技术创新和市场发展,实现了互利共赢的局面。

请注意,这些只是故事框架,具体的内容需要你根据ADI公司的历史资料、行业报告和新闻报道等进行深入研究和补充。在编写故事时,请确保只描述事实,避免加入个人主观评价或情感色彩。

EPCOS/TDK公司的发展小趣事

自上世纪60年代起,TDK就开始在中国布局。首先,在台湾建立合资公司,随后在香港设立销售网络及生产线。进入80年代后,TDK正式踏足中国大陆,在华东及华南多个地区建立生产基地,并逐渐将业务扩展至全国。TDK在中国的发展不仅推动了当地电子工业的进步,也为公司自身赢得了广阔的市场空间。目前,TDK在中国的员工人数近6万人,占TDK全球员工总数的近55%。

Garmin_Canada_Inc.公司的发展小趣事
通过微控制器的精确控制,可以实现拨号过程的精确控制。例如,在拨号前进行必要的初始化操作,拨号过程中实时监测信号状态,并在拨号完成后进行状态确认。
Fair Rite公司的发展小趣事

为了确保产品质量和满足客户需求,Fair Rite引入了严格的质量管理体系,并通过了ISO/TS 16949认证。此外,公司还积极拓展国际市场,在美国、中国等地建立了生产基地和销售网络。通过全球布局和本土化策略,Fair Rite为全球客户提供高品质、高性能的电子元器件。

Connor-Winfield公司的发展小趣事

进入20世纪90年代,电子行业的技术革新日新月异。Connor-Winfield敏锐地捕捉到了市场的变化,开始将产品线扩展到其他领域,以满足更多客户的需求。除了石英计时电路和振荡器,公司还开始研发和生产一系列与电子应用紧密相关的产品。这些新产品的推出,不仅进一步巩固了公司在行业内的地位,也为其开拓了更广阔的市场空间。

BALLUFF公司的发展小趣事

BALLUFF公司的历史可以追溯到1921年,由格布哈德·巴鲁夫(Gebhard Balluff)创建的一家机械修理厂开始。这家修理厂起初规模较小,但巴鲁夫凭借其对机械技术的精湛理解和不懈追求,逐渐将业务发展壮大。他通过不断的技术创新和产品升级,使得修理厂逐渐转型为一家专注于生产精密部件、车件和铣件的企业。这一转变不仅奠定了BALLUFF公司的工业基础,也为其日后在传感器领域的崛起打下了坚实基础。

问答坊 | AI 解惑

请教关于DXP2004中原理图的“Title Block”的修改

请教大家一个问题:    在 Protel DXP2004 sp2 的原理图编辑中,它右下角的那个“Title Block”的区域中的信息,有没有非常方便的方法修改呢?    恳请大家告诉我正确的方法,谢谢!…

查看全部问答>

[求助] 关于晶体振荡电路

用晶体振荡的电路产生信号,与电路的外接电阻电容有关吗…

查看全部问答>

请教各位高手:摄像头驱动问题还是软件问题?

新买回来的摄像头,驱动安装正常,用amcap预览正常,默认打开的视频窗口大小是800*600,可是在qq视频设置里面,图像的帧率却很低,显示很慢,在msn的视频设置中是正常的,请问各位高手故障现象的原因在什么地方呢?是驱动的问题还是qq软件的不兼容?…

查看全部问答>

一下还不习惯用ST的库函数(懒记),所以自己对GPIO口进行

另外,对ST的一些寄存器定义也不大习惯,所以也重新做了定义,例如GPIOx_BSRR我另外定义了一个GPIOx_SET,GPIOx_BRR我另外定义了一个GPIOx_CLR,这样自己记起来轻松多了——男人何必为难自己呢...看看这个流水灯的程序,看上去是不是容易些了 ...…

查看全部问答>

有几个人可以解答这个问题?

cpu里面的电路是怎么认识程序翻译成的机器码0和1的?…

查看全部问答>

求verilog编辑一个带两位小数的加法运算

用verilog语言编辑一个带两位小数的十进制加法运算  例如139.33+122.53的运算…

查看全部问答>

哪位朋友可以谈谈轿车着火或者溺水之后车门安全系统如何预警和自救?

看到新闻上不断有报道轿车着火之后乘客不能及时逃生,721北京暴雨也导致有驾驶员不幸在轿车中溺水身亡! 哪位朋友可以谈谈轿车着火或者溺水之后车门安全系统如何预警和自救? http://weibo.com/vishaychina…

查看全部问答>

软件

请问哈有没有能够从stm32单片机串口上直接接收图片的数据流(十六进制),然后在电脑上显示的软件,用于弄摄像头的,谢谢?…

查看全部问答>

TI芯片--TPS5450使用问题

几款板卡,其电源部分都是用的TPS5450,外围只有7颗元件,就可以实现DC/DC转换,最大5A的输出能力。当输出电压是5V时,输入电压范围可以达到7~33V,足以满足一般场合的应用。所以给板子配适配器可以放的很宽,可以使用各类适配器,9V的,12V的,19V ...…

查看全部问答>

刷到清单的求共享

本帖最后由 paulhyde 于 2014-9-15 03:44 编辑 从早上8点刷到现在一点反应都木有    …

查看全部问答>