对于大多数人来说都写过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配置,是因为它比较稳定,我也是小白,不太会写文字,第一次试着写的,下面粘贴代码吧
重定义了一些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实现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; }自己用过,是可以使用的,有什么错误或不足的地方还请指出,第一次写,也是刚入大学的小菜鸟,刚开始学习,希望各位大佬指导,也希望能给予需要人的帮助