基于STM32任意键薄膜键盘代码
对于大多数人来说都写过51的按键扫描,但是对于32来说端口配置比较麻烦,对于按键扫描 *要配置相应的IO口模式,每种模式的特性是不一样的,可以通过按键的读写操作,对于各种模式有个深入的了解。
对薄膜键盘来说通过八个IO口进行扫描确认是哪个按键按下,然而一般的方式是采用行和列高低电平的反差来扫描判断的,那么我们对32 的IO口要进行写和读操作,学过32的人都知道,IO口的每一种模式都可读可写,但是对于外电路来说,不是每种模式都可以用来按键扫描。
GPIO_Mode_AIN = 0x0,
模拟输入,应用ADC 模拟输入
GPIO_Mode_IN_FLOATING = 0x04,
浮空输入,在悬空状态电平未知,一般在高低电平判决临界处,
GPIO_Mode_IPD = 0x28,
IO口内部下拉电阻输入
GPIO_Mode_IPU = 0x48,
IO口内部下拉电阻输入
GPIO_Mode_Out_OD = 0x14,
开漏输出,IO输出0接地,输出1悬空
GPIO_Mode_Out_PP = 0x10,
推挽输出 IO输出0接地,输出1接vcc
GPIO_Mode_AF_OD = 0x1C,
复用开漏输出,对于这个实在一些内部外设使用时要使用的,作为小白的我使用还是不太了解具体使用情况,只是知道大概在使用一些外设时需要使用。
GPIO_Mode_AF_PP = 0x18
复用推挽
其实对于上面的这么多模式,对于我们的中心按键扫描,可以配置很懂种模式实现,关键看是否稳定。我选用的扫描方式是以 行/列 输出为推挽输出,而 列/行 以
下拉输入为输入。
一、行/列 四个引脚 输出为推挽输出,输出比较稳定,高低电平分明,不易受外电路的干扰,
二、列/行 以下拉输入为输入,IO口电平状态默认是下拉的 ,及低电平,当外界给IO为高电平时,IO口就会被拉高,读取IO状态为高电平,很好的起到了读取外部IO的作用
之所以使用这种类型的IO配置,是因为它比较稳定,我也是小白,不太会写文字,第一次试着写的,下面粘贴代码吧
主函数
// An highlighted block
#include "stm32f10x.h"
#include "STK_H_Usart.h"
#include "bsp_led.h"
#include "stdio.h"
#include "STK_H_BMkey.h"
#include "bsp_SysTick.h"
int main(void)
{
uint8_t mmp=0;
//串口初始化
usart_config();
//LED 初始化
LED_GPIO_Config();
//按键扫描初始化
key_GPIO_Config(1);
//系统定时器初始化
SysTick_Init();
printf("今天是个好天气");
while(1)
{
mmp=key_seek();
SysTick_Delay_Ms(500);
printf("my world is %d\n",mmp);
}
}
扫描函数 .H文件
重定义了一些IO口名,便于更改引脚
这个文件就只是完成了这个时期,有点呆滞,
#ifndef __STK_H_BMKEY_H__
#define __STK_H_BMKEY_H__
#include "stm32f10x.h"
//第一组 行
//PC 6
#define KEY1_1_GPIO_PORT GPIOA
#define KEY1_1_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY1_1_GPIO_PIN GPIO_Pin_4
#define X1_0 GPIO_ResetBits(KEY1_1_GPIO_PORT, KEY1_1_GPIO_PIN);
#define X1_1 GPIO_SetBits(KEY1_1_GPIO_PORT, KEY1_1_GPIO_PIN);
//PC 8
#define KEY1_2_GPIO_PORT GPIOA
#define KEY1_2_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY1_2_GPIO_PIN GPIO_Pin_5
#define X2_0 GPIO_ResetBits(KEY1_2_GPIO_PORT, KEY1_2_GPIO_PIN);
#define X2_1 GPIO_SetBits(KEY1_2_GPIO_PORT, KEY1_2_GPIO_PIN);
//PA 8
#define KEY1_3_GPIO_PORT GPIOA
#define KEY1_3_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY1_3_GPIO_PIN GPIO_Pin_6
#define X3_0 GPIO_ResetBits(KEY1_3_GPIO_PORT, KEY1_3_GPIO_PIN);
#define X3_1 GPIO_SetBits(KEY1_3_GPIO_PORT, KEY1_3_GPIO_PIN);
//PA 10
#define KEY1_4_GPIO_PORT GPIOA
#define KEY1_4_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY1_4_GPIO_PIN GPIO_Pin_7
#define X4_0 GPIO_ResetBits(KEY1_4_GPIO_PORT, KEY1_4_GPIO_PIN);
#define X4_1 GPIO_SetBits(KEY1_4_GPIO_PORT, KEY1_4_GPIO_PIN);
#define X_0 X1_0 \
X2_0 \
X3_0 \
X4_0
#define X_1 X1_1 \
X2_1 \
X3_1 \
X4_1
//第二组 列
//
//PA 12
#define KEY2_1_GPIO_PORT GPIOA
#define KEY2_1_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY2_1_GPIO_PIN GPIO_Pin_2
#define Y1_0 GPIO_ResetBits(KEY2_1_GPIO_PORT, KEY2_1_GPIO_PIN);
#define Y1_1 GPIO_SetBits(KEY2_1_GPIO_PORT, KEY2_1_GPIO_PIN);
// PA 14
#define KEY2_2_GPIO_PORT GPIOA
#define KEY2_2_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY2_2_GPIO_PIN GPIO_Pin_3
#define Y2_0 GPIO_ResetBits(KEY2_2_GPIO_PORT, KEY2_2_GPIO_PIN);
#define Y2_1 GPIO_SetBits(KEY2_2_GPIO_PORT, KEY2_2_GPIO_PIN);
//PC 10
#define KEY2_3_GPIO_PORT GPIOA
#define KEY2_3_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY2_3_GPIO_PIN GPIO_Pin_11
#define Y3_0 GPIO_ResetBits(KEY2_3_GPIO_PORT, KEY2_3_GPIO_PIN);
#define Y3_1 GPIO_SetBits(KEY2_3_GPIO_PORT, KEY2_3_GPIO_PIN);
//PC 12
#define KEY2_4_GPIO_PORT GPIOA
#define KEY2_4_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY2_4_GPIO_PIN GPIO_Pin_12
#define Y4_0 GPIO_ResetBits(KEY2_4_GPIO_PORT, KEY2_4_GPIO_PIN);
#define Y4_1 GPIO_SetBits(KEY2_4_GPIO_PORT, KEY2_4_GPIO_PIN);
#define Y_0 Y1_0 \
Y2_0;\
Y3_0\
Y4_0
#define Y_1 Y1_1 \
Y2_1;\
Y3_1\
Y4_1
/*初始化函数,*/
void key_GPIO_Config(int a);
uint8_t key_seek(void);
#endif
扫描函数 .C文件
实现IO初始化,还有读取函数的书写,扫描函数的书写
#include "STK_H_BMkey.h"
#include "stdio.h"
#include "bsp_SysTick.h"
//1 k2为浮空输入 (读取Y) 0 k1 为浮空输入(读取X)
/**********************************************************
* 函数名:key_GPIO_Config(int a)
* 参数 :a
* 参数取值:0(第一组配置为推挽,第二组下拉) 1(和前面相反)
*
**********************************************************/
void key_GPIO_Config(int a)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启LED相关的GPIO外设时钟*/
RCC_APB2PeriphClockCmd( KEY1_1_GPIO_CLK| KEY1_2_GPIO_CLK | KEY1_3_GPIO_CLK| KEY1_4_GPIO_CLK |KEY2_1_GPIO_CLK| KEY2_2_GPIO_CLK | KEY2_3_GPIO_CLK| KEY2_4_GPIO_CLK, ENABLE);
//KEY1 按键配置
GPIO_InitStructure.GPIO_Pin = KEY1_1_GPIO_PIN;
if(a)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
else
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(KEY1_1_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = KEY1_2_GPIO_PIN;
GPIO_Init(KEY1_2_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = KEY1_3_GPIO_PIN;
GPIO_Init(KEY1_3_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = KEY1_4_GPIO_PIN;
GPIO_Init(KEY1_4_GPIO_PORT, &GPIO_InitStructure);
//KEY2 按键配置
if(a)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
else
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = KEY2_1_GPIO_PIN;
GPIO_Init(KEY2_1_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = KEY2_2_GPIO_PIN;
GPIO_Init(KEY2_2_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = KEY2_3_GPIO_PIN;
GPIO_Init(KEY2_3_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = KEY2_4_GPIO_PIN;
GPIO_Init(KEY2_4_GPIO_PORT, &GPIO_InitStructure);
// Y_0;//给Y组的IO口置位0
// X_0;//给X组的IO口置位0
}
/***************************************************************************
**函数名 :READ_Date
**参数 :a
**参数取值:0(读取X(行)的IO口的数据) 1(读取Y(列)的IO口的数据)
**返回值 :八位 第四位表示读取IO电平状态,通过移位相或实现
****************************************************************************/
uint8_t READ_Date(int a)
{
if(a) {
return 0x0f&((GPIO_ReadInputDataBit(KEY2_1_GPIO_PORT, KEY2_1_GPIO_PIN))<<3 | GPIO_ReadInputDataBit(KEY2_2_GPIO_PORT, KEY2_2_GPIO_PIN)<<2 \
| GPIO_ReadInputDataBit(KEY2_3_GPIO_PORT, KEY2_3_GPIO_PIN)<<1| GPIO_ReadInputDataBit(KEY2_4_GPIO_PORT, KEY2_4_GPIO_PIN)); }
else {
return 0x0f&((GPIO_ReadInputDataBit(KEY1_1_GPIO_PORT, KEY1_1_GPIO_PIN))<<3 | GPIO_ReadInputDataBit(KEY1_2_GPIO_PORT, KEY1_2_GPIO_PIN)<<2 \
| GPIO_ReadInputDataBit(KEY1_3_GPIO_PORT, KEY1_3_GPIO_PIN)<<1| GPIO_ReadInputDataBit(KEY1_4_GPIO_PORT, KEY1_4_GPIO_PIN)); }
}
//扫描函数
uint8_t key_seek(void)
{
int mm,key_date=0;
key_GPIO_Config(0);
X_0; Y_1;
SysTick_Delay_Ms(2);
mm=READ_Date(0); //变量为0 ,表示返回的是key1的数据及X的数据
if(mm!=0x00){
//printf("进入了第一个判断\n");
SysTick_Delay_Ms(10);
mm=READ_Date(0);
if(mm!=0x00){
switch(mm)
{
case(0x08): key_date=0;
break;
case(0x04): key_date=4;
break;
case(0x02): key_date=8;
break;
case(0x01): key_date=12;
break;
}
key_GPIO_Config(1);
X_1;Y_0;
SysTick_Delay_Ms(2);
mm=READ_Date(1);
switch(mm)
{
case(0x08): key_date=key_date+1;
break;
case(0x04): key_date=key_date+2;
break;
case(0x02): key_date=key_date+3;
break;
case(0x01): key_date=key_date+4;
break;
}
printf("等待按键谈起");
printf("(uint8_t)key_date is %d\n",(uint8_t)key_date);
printf("READ_Date(1) is %d\n",READ_Date(1));
while(0x00!=READ_Date(1)); //等待按键弹起
return (uint8_t)key_date;
}
}
return 0;
}
自己用过,是可以使用的,有什么错误或不足的地方还请指出,第一次写,也是刚入大学的小菜鸟,刚开始学习,希望各位大佬指导,也希望能给予需要人的帮助