基于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_CLKRCC_APB2Periph_GPIOA #define KEY1_1_GPIO_PINGPIO_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_CLKRCC_APB2Periph_GPIOA #define KEY1_2_GPIO_PINGPIO_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_CLKRCC_APB2Periph_GPIOA#define KEY1_3_GPIO_PINGPIO_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_CLKRCC_APB2Periph_GPIOA #define KEY1_4_GPIO_PINGPIO_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_CLKRCC_APB2Periph_GPIOA #define KEY2_1_GPIO_PINGPIO_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_CLKRCC_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_CLKRCC_APB2Periph_GPIOA #define KEY2_3_GPIO_PINGPIO_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_CLKRCC_APB2Periph_GPIOA #define KEY2_4_GPIO_PINGPIO_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;elseGPIO_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;elseGPIO_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;}
自己用过,是可以使用的,有什么错误或不足的地方还请指出,第一次写,也是刚入大学的小菜鸟,刚开始学习,希望各位大佬指导,也希望能给予需要人的帮助
如果觉得《基于STM32任意键薄膜键盘代码》对你有帮助,请点赞、收藏,并留下你的观点哦!