这几天事情比较多,所以就一直没有更新,呵呵,今天早上没课,把之前写好代码整理一下,顺便说下思路,发上来,供大家参考参考。
首先,本矩阵键盘硬件连接如下:
思路:
我的思路如下,首先,把纵向三线设置为推挽输出,然后把横向三线设置为下拉输入,然后读取横向三线的值,如果有接口的读数为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
|