首先,将端口PORT1~PORT5设置为输出,PORT6设置为中断输入,下降沿触发,并从PORT1~PORT5输出“1”。这样,在没有键按下时,三极管截止,PORT6输入“1”。
当有任何键按下时,三极管导通,PORT6输入由“1”变为“0”,也就是有一个下降沿输入,就会触发中断。
进入中断后,将PORT1置为输出,并输出“1”,PORT2~PORT5置为输入,然后读取PORT2~PORT6,
如果与PORT1连接的任一按键按下,PORT6将为“0”,同时:
如果按键S1按下则只有PORT5输入“1”,其余输入为“0”;
如果按键S6按下则只有PORT4输入“1”,其余输入为“0”;
如果按键S11按下则只有PORT3输入“1”,其余输入为“0”;
如果按键S16按下则只有PORT2输入“1”,其余输入为“0”;
如果按键S21按下则所有输入为“0”。
如果与PORT1连接的按键未按下,PORT6输入“1”。
其余的依此类推,这样就可确认是哪个按键按下了
我这样写之后,发现在触发中断后进入中断处理要扫描首先就要重置IO口,我焊的4*4用PA0~3作为IO控制,PA4作为中断IO口,进入中断后将PA0先置为输出高,PA1~3置为输入0,这样判断PA4口是否为0,是的话在进行下一步,不是就直接重置下一个IO口为输出,问题出在重置了IO口之后按照网上以及个人的理解,由于CPU处理速度特别快,假如上图的S16按下,重置后PA0输出高,其他输入都为0,然后由于按键还没松开,所以PA2又会变为1,PA6应该一直为0,但是结果却是重置IO后,PA1的值为1,PA6的值也为1,其他都为0,所以得不到按键值,纠结了两天了,很后悔昨天就该来论坛问的,结果觉得论坛太慢,又耽误一天的时间,我已经用jtag和示波器调试了,结果就是我说的那样,并且用万用表都测过了硬件本身没问题,希望尽快有大神帮助解决。
下面附上源码
[mw_shl_code=c,true]/*
*********************************************************************************************************
* Embedded Systems Building Blocks
* Complete and Ready-to-Use Modules in C
*
* KEY 4*4 Module Driver
*
* (c) Copyright 2014, Fisher
*
* Filename : key44.c
* Programmer : Fisher
*********************************************************************************************************
* DESCRIPTION
*
* 这个模块提供5个IO口组成扩展的4*4键盘的驱动程序,能够很容易地扩展到更大的键盘模块
* 提供的接口:
* 消耗的IO口:PA 0~3 4列下拉输入
* PA 4 中断IO口,上拉输入,下降沿触发
*********************************************************************************************************
*/
/*$PAGE*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#include "key44.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
u8 key = 16;
/*$PAGE*/
/*
*********************************************************************************************************
* 按键扫描函数
*
* 描述: 此函数是按键识别的核心程序
* 参数: 无
* 返回值:按键值
*********************************************************************************************************
*/
u8 MatrixKey_Decode() {
u8 i = 0;
u16 res = 0; /* 暂存读取的寄存器的值 */
for (i = 0; i < 4; i++) {
GPIOA->CRL &= 0XFFFF0000; /* PA0~3设置成输入 */
GPIOA->CRL |= 0X00008888;
GPIOA->ODR &= ~0X0F; /* PA0~3下拉 */
// GPIOA->ODR |= 1 << 4; /* PA4上拉 */
GPIOA->CRL |= 0X03 << (i * 4); /* PA(i)设置为输出模式 */
GPIOA->ODR |= 1 << i; /* PA(i)上拉 */
// delay_ms(1000);
printf("i: %d \n",i);
res = GPIOA->ODR;
printf("res: %x \n",res);
if (PORT_EXIT == 1)
continue; /* 按键不在当前列 */
res &= 0X0F; /* 得到PA0~3的值 */
res &= ~(1 << i); /* 将输出口的值清零 */
switch (res) {
// case 0: return ((3 - i) * 4 + i); /* 行列值相等,处于矩阵键盘对角线上 */
case 1: return (0 * 4 + i); /* 第一行 */
case 2: return (1 * 4 + i); /* 第二行 */
case 4: return (2 * 4 + i); /* 第三行 */
case 8: return (3 * 4 + i); /* 第四行 */
}
}
return 16;
}
/*$PAGE*/
/*
*********************************************************************************************************
* 中断4服务程序
*
* 描述: 此函数为中断4的服务程序
* 参数: 无
* 返回值:无
*********************************************************************************************************
*/
void EXTI4_IRQHandler(void)
{
delay_ms(10); /* 消抖 */
LED_GRE = !LED_GRE;
/* 这里为中断处理的部分 */
key = MatrixKey_Decode();
delay_ms(200);
LED_GRE = !LED_GRE;
/*
** 重新设置中断IO上拉输入 以及其他IO输出高,
** 注意这几句必须放在清除中断标志位之前,否则会出现进入中断后出不去的现象
*/
GPIOA->CRL &= 0XFFF00000;
GPIOA->CRL |= 0XFFF83333; /* PA0~3设置成输出 PA4输入 */
GPIOA->ODR |= 0X1F; /* PA0~3默认输出高 PA4上拉输入 */
EXTI->

R = 1 << 4; /* 清除LINE4上的中断标志位 */
}
/*
*********************************************************************************************************
* 中断初始化程序
*
* 描述: 此函数为中断4初始化程序,初始化PA4为中断输入.
* 参数: 无
* 返回值:无
*********************************************************************************************************
*/
void EXTIX_Init(void)
{
RCC->APB2ENR |= 1 << 2; /* 使能PORTA时钟 */
JTAG_Set(JTAG_SWD_ENABLE); /* 关闭JTAG和SWD */
GPIOA->CRL &= 0XFFF00000;
GPIOA->CRL |= 0XFFF83333; /* PA0~3设置成输出 PA4输入 */
GPIOA->ODR |= 0X1F; /* PA0~3默认输出高 PA4上拉输入 */
Ex_NVIC_Config(GPIO_A, 4, FTIR); /* 下降沿触发 */
MY_NVIC_Init(2, 1, EXTI4_IRQChannel, 2); /* 抢占2,子优先级1,组2 */
}
[/mw_shl_code]
还有就是进入按键处理那个函数的for循环的第一句执行之后,PA4就会由0变为1,我都没设置PA4啊这一步,不知道怎么会影响到它的,希望弄过的帮忙解决一下,唉