这几天事情比较多,所以就一直没有更新,呵呵,今天早上没课,把之前写好代码整理一下,顺便说下思路,发上来,供大家参考参考。
首先,本矩阵键盘硬件连接如下:
思路:
我的思路如下,首先,把纵向三线设置为推挽输出,然后把横向三线设置为下拉输入,然后读取横向三线的值,如果有接口的读数为1,说明有按键按下了,把该值与0x07相与后放到scana,然后左移4位放到result中,这之后把横向三线设置为推挽输出,纵向三线设置为下拉输入,然后读取纵向三线的值,把相应的键值保存到scanb中,然后通过移位使得低四位表示的是相应的按键所在横向的值,然后与result相或放到result的低四位,这样得到的result高四位就是按键所在纵向的值,低四位就是按键所在横向的值,由此就可以检测到那个按键被按下了。
效果:按下相应的键盘,四个led灯会显示各种不同的状态,hoho,一共有9种状态。
#include "stm32f10x_lib.h"
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void delay(void);
u8 KEY_GPIO_Scanning(void);
int main(void)
{
#ifdef DEBUG
debug();
#endif
RCC_Configuration();//配置系统时钟
NVIC_Configuration(); //配置 NVIC 和 Vector Table
GPIO_Configuration(); //使用的GPIO口
//主循环
while (1)
{
//循环扫描按键 按键按下时 对应的LED亮
switch ( KEY_GPIO_Scanning() )
{
case(0x18):
GPIO_SetBits(GPIOB, GPIO_Pin_12);
GPIO_ResetBits(GPIOB, GPIO_Pin_13);
GPIO_ResetBits(GPIOB, GPIO_Pin_14);
GPIO_ResetBits(GPIOB, GPIO_Pin_15);
break;
case(0x12):
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
GPIO_SetBits(GPIOB, GPIO_Pin_13);
GPIO_ResetBits(GPIOB, GPIO_Pin_14);
GPIO_ResetBits(GPIOB, GPIO_Pin_15);
break;
case(0x14):
GPIO_SetBits(GPIOB, GPIO_Pin_12);
GPIO_SetBits(GPIOB, GPIO_Pin_13);
GPIO_ResetBits(GPIOB, GPIO_Pin_14);
GPIO_ResetBits(GPIOB, GPIO_Pin_15);
break;
case(0x28):
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
GPIO_ResetBits(GPIOB, GPIO_Pin_13);
GPIO_SetBits(GPIOB, GPIO_Pin_14);
GPIO_ResetBits(GPIOB, GPIO_Pin_15);
break;
case(0x24):
GPIO_SetBits(GPIOB, GPIO_Pin_12);
GPIO_ResetBits(GPIOB, GPIO_Pin_13);
GPIO_SetBits(GPIOB, GPIO_Pin_14);
GPIO_ResetBits(GPIOB, GPIO_Pin_15);
break;
case(0x48):
GPIO_SetBits(GPIOB, GPIO_Pin_12);
GPIO_SetBits(GPIOB, GPIO_Pin_13);
GPIO_SetBits(GPIOB, GPIO_Pin_14);
GPIO_ResetBits(GPIOB, GPIO_Pin_15);
break;
case(0x42):
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
GPIO_ResetBits(GPIOB, GPIO_Pin_13);
GPIO_ResetBits(GPIOB, GPIO_Pin_14);
GPIO_SetBits(GPIOB, GPIO_Pin_15);
break;
case(0x44):
GPIO_SetBits(GPIOB, GPIO_Pin_12);
GPIO_ResetBits(GPIOB, GPIO_Pin_13);
GPIO_ResetBits(GPIOB, GPIO_Pin_14);
GPIO_SetBits(GPIOB, GPIO_Pin_15);
break;
case(0x22):
GPIO_SetBits(GPIOB, GPIO_Pin_12);
GPIO_SetBits(GPIOB, GPIO_Pin_13);
GPIO_SetBits(GPIOB, GPIO_Pin_14);
GPIO_SetBits(GPIOB, GPIO_Pin_15);
break;
}
}
}
void RCC_Configuration(void)
{
ErrorStatus HSEStartUpStatus;
RCC_DeInit(); //将外设 RCC寄存器重设为缺省值
RCC_HSEConfig(RCC_HSE_ON); //设置外部高速晶振(HSE)
HSEStartUpStatus = RCC_WaitForHSEStartUp();//等待 HSE 起振
if(HSEStartUpStatus == SUCCESS)
{
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//预取指缓存使能
FLASH_SetLatency(FLASH_Latency_2);//设置代码延时值 FLASH_Latency_2 2 延时周期
RCC_HCLKConfig(RCC_SYSCLK_Div1); //设置 AHB 时钟(HCLK) RCC_SYSCLK_Div1 AHB 时钟 = 系统时钟
RCC_PCLK2Config(RCC_HCLK_Div2);//设置高速 AHB 时钟(PCLK2) RCC_HCLK_Div2 APB1 时钟 = HCLK / 2
RCC_PCLK1Config(RCC_HCLK_Div2); //设置低速 AHB 时钟(PCLK1)RCC_HCLK_Div2 APB1 时钟 = HCLK / 2
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); // PLLCLK = 8MHz * 9 = 72 MHz 设置 PLL 时钟源及倍频系数
RCC_PLLCmd(ENABLE);//使能或者失能 PLL
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) //等待指定的 RCC 标志位设置成功 等待PLL初始化成功
{
}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//设置系统时钟(SYSCLK) 设置PLL为系统时钟源
while(RCC_GetSYSCLKSource() != 0x08) //等待PLL成功用作于系统时钟的时钟源 0x00:HSI 作为系统时钟 0x04:HSE作为系统时钟 0x08:PLL作为系统时钟
{
}
}
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能或者失能 APB2 外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//LED端口设置为 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//键盘 横向 三线
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//键盘 纵向 三线
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void GPIO_Reconfiguration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//键盘 横向 三线
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//键盘 纵向 三线
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/*******************************************************************************
* Function Name : KEY_GPIO_Scanning
* Description : 依次扫描4个按键 使用一个u8变量的低4位存储扫描结果
* Input : None
* Output : None
* Return : 扫描的结果 有效数据是低4位
*******************************************************************************/
u8 KEY_GPIO_Scanning(void)
{
u8 result;
u8 scana; //单个按键扫描变量
u8 scanb; //四个按键总的情况变量 scan_sum低四位的每一位对应一个按键
scana = 0;
scanb = 0;
result = 0;
GPIO_SetBits( GPIOA, GPIO_Pin_3);
GPIO_SetBits( GPIOB, GPIO_Pin_1);
GPIO_SetBits( GPIOB, GPIO_Pin_2);
//扫描按键
scana = GPIO_ReadInputData(GPIOA);
scana = scana & 0x07;
//如果按键按下 则延迟 再扫描 然后根据判断处理
if(scana)
{
delay();
scana = GPIO_ReadInputData(GPIOA);
scana = scana & 0x07;
//翻转,二次读取
GPIO_Reconfiguration();
GPIO_SetBits( GPIOA, GPIO_Pin_0);
GPIO_SetBits( GPIOA, GPIO_Pin_1);
GPIO_SetBits( GPIOA, GPIO_Pin_2);
GPIO_ResetBits( GPIOA, GPIO_Pin_3);
GPIO_ResetBits( GPIOB, GPIO_Pin_1);
GPIO_ResetBits( GPIOB, GPIO_Pin_2);
scanb = GPIO_ReadInputData(GPIOA);
scanb = scanb & (1<<3);
scanb |= ( GPIO_ReadInputData(GPIOB) & ( (1<<1) | (1<<2) ) ) ;
result = scana << 4;
result |= scanb;
GPIO_Configuration();
}
return result;
}
void NVIC_Configuration(void)
{
#ifdef VECT_TAB_RAM
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else /* VECT_TAB_FLASH */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
}
void delay()
{
int i;
for (i=0; i<0xffff; i++)
;
}
#ifdef DEBUG
void assert_failed(u8* file, u32 line)
{
while (1)
{
}
}
#endif