|
如下图,是我做的一个键盘矩阵(原本是6x6的,这里为说明精减了),想用中断的方式来完成。如下图,列线PC11-13先置为0,一旦有键按下,就会产生下降沿中断。然后在中断中置相关标志位,再进行按键扫描。程序大致如下:
struct io_port {
GPIO_TypeDef *GPIO_x;
uint16_t GPIO_pin;
};
static struct io_port key_input[2] = {
{GPIOC, GPIO_Pin_5},
{GPIOC, GPIO_Pin_6},
};
static struct io_port key_output[3] = {
{GPIOC, GPIO_Pin_11},
{GPIOC, GPIO_Pin_12},
{GPIOC, GPIO_Pin_13}
};
volatile uint8_t it_flag = 0;
volatile uint8_t key[3][2];
void gpio_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //输出
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_ResetBits(GPIOC, GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13); //输出全置低,以便按键按下产生下降沿中断
}
void nvic_init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //外部中断9-5
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能
NVIC_Init(&NVIC_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource5 | GPIO_PinSource6);
EXTI_InitStructure.EXTI_Line = EXTI_Line5 | EXTI_Line6; //PC5,PC6 作为键盘检测状态
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line5) != RESET) //判别是否有键按下
{
EXTI_ClearITPendingBit(EXTI_Line5); //清除中断请求标志
it_flag = 1; //置标志位
}
//EXTI_Line6以下略
...
}
void key_scan(void)
{
uint8_t i;
if (1 == it_flag)
{
it_flag = 0; //清标志位
for (i = 0; i < 3; i++)
{
GPIO_SetBits(key_output.GPIO_x, key_output.GPIO_pin); //输出引脚依次置1
if (Bit_SET == GPIO_ReadInputDataBit(key_input[0].GPIO_x, key_input[0].GPIO_pin))
{
key[0] = 1; //按下的键位置1
}
else
{
key[0] = 0;
}
GPIO_ResetBits(key_output.GPIO_x, key_output.GPIO_pin); //重新置0,以便下次按下扫描
}
}
//EXTI_Line6以下略
......
}
void main(void)
{
gpio_init();
nvic_init();
while(1)
{
//去抖先不理了,只是说明下
key_scan(); //扫描按键
}
}
现在问题是,一按下某个按键后,在按键扫描中,
会先GPIO_SetBits(key_output.GPIO_x, key_output.GPIO_pin); //输出引脚依次置1
再GPIO_ResetBits(key_output.GPIO_x, key_output.GPIO_pin); //重新置0,以便下次按下扫描
这样不是又会在行线PC5上再次产生下降沿么?从而又重新置标置位,又从新扫描了?是不是我的这个处理过程有问题呢?大家是怎么处理键盘中断扫描的? |
|