c-4x4矩阵键盘stm32无法连接它



我想在stm32 l053r8中用定时器中断连接一个键盘。我有一个SysTick_Handler功能,我在那里处理按钮的开关抖动,每次按钮计数器等于10时,我都会使用一个标志来检查按钮何时按下。所以现在我把键盘上的所有行都作为输入,把键盘上所有列都作为输出。我的想法是

  1. 每个定时器int,它都会激活一个新列并读取4行输入
  2. 检查按钮标志是否为"0";1〃;并将适当的消息发送到屏幕

我有一个实现,但它不起作用。例如,在主函数中,我有一个条件,检查键1(在屏幕中输出为1(是否被按下,但它什么都不做。任何建议都很好。

void TIM2_IRQHandler(void) {
if (TIM2->SR & TIM_SR_UIF ) {
//Clear Timer 2 Flag
CLEAR_BIT(TIM2->SR, TIM_SR_UIF);
if (column_counter==4)
column_counter=0;
column_counter++;
keypad_scanning(column_counter); // activate col=1 or 2 or 3 depends on counter.
}
}
void keypad_scanning(uint8_t column_pos) {
switch (column_pos) {
case 1:
SET_BIT(GPIOC->ODR,GPIO_ODR_OD15);   // C1 HIGH
CLEAR_BIT(GPIOA->ODR,GPIO_ODR_OD1);  // C2 LOW
CLEAR_BIT(GPIOA->ODR,GPIO_ODR_OD4);  // C3 LOW
if (flag0.fl.f5 && !(flag0.fl.f6) && !(flag0.fl.f7)) {
key0.fl.f1 = 1; // key 1 is pressed.
}
if (!(flag0.fl.f5) && flag0.fl.f6 && !(flag0.fl.f7)) {
key0.fl.f4 = 1; // key 4 is pressed.
}
if (!(flag0.fl.f5) && !(flag0.fl.f6) && flag0.fl.f7) {
key0.fl.f7 = 1; // key 7 is pressed.
}
break;
case 2:
CLEAR_BIT(GPIOC->ODR,GPIO_ODR_OD15);   // C1 LOW
SET_BIT(GPIOA->ODR,GPIO_ODR_OD1);  // C2 HIGH
CLEAR_BIT(GPIOA->ODR,GPIO_ODR_OD4);  // C3 LOW
if (flag0.fl.f5 && !(flag0.fl.f6) && !(flag0.fl.f7)) {
key0.fl.f2 = 1; // key 2 is pressed.
}
if (!(flag0.fl.f5) && flag0.fl.f6 && !(flag0.fl.f7)) {
key0.fl.f5 = 1; // key 5 is pressed.
}
if (!(flag0.fl.f5) && !(flag0.fl.f6) && flag0.fl.f7) {
key0.fl.f8 = 1; // key 8 is pressed.
}
break;
case 3:
CLEAR_BIT(GPIOC->ODR,GPIO_ODR_OD15);   // C1 LOW
CLEAR_BIT(GPIOA->ODR,GPIO_ODR_OD1);  // C2 LOW
SET_BIT(GPIOA->ODR,GPIO_ODR_OD4);  // C3 HIGH
if (flag0.fl.f5 && !(flag0.fl.f6) && !(flag0.fl.f7)) {
key0.fl.f3 = 1; // key 3 is pressed.
}
if (!(flag0.fl.f5) && flag0.fl.f6 && !(flag0.fl.f7)) {
key0.fl.f6 = 1; // key 6 is pressed.
}
if (!(flag0.fl.f5) && !(flag0.fl.f6) && flag0.fl.f7) {
key0.fl.f9 = 1; // key 9 is pressed.
}
break;
}
}
void SysTick_Handler(void) {
//------------------------------
//key 1 sampling ( ROW 1 FLAG)
if(!flag0.fl.f5) {
if(!KEY1_READ()) {
if(key1_counter == 10)
flag0.fl.f5 = 1; // R1 is HIGH
key1_counter = 0;
} else {
if(key1_counter < 10) //10 ms sampling
key1_counter ++;
}
}
//------------------------------
//------------------------------
//key 2 sampling (ROW 2 FLAG)
if(!flag0.fl.f6) {  
if(!KEY2_READ()) {
if(key2_counter == 10)
flag0.fl.f6 = 1; // R2 is HIGH
key2_counter = 0;
} else {  
if(key2_counter < 10) //10 ms sampling
key2_counter ++;
}
}
//------------------------------
//------------------------------
//key 3 sampling (ROW 3 FLAG)
if(!flag0.fl.f7) {
if(!KEY3_READ()) {
if(key3_counter == 10)
flag0.fl.f7 = 1; // R3 is HIGH
key3_counter = 0;
} else {
if(key3_counter < 10) //10 ms sampling
key3_counter ++;
}
}
//------------------------------
}

首先,您的标题是4x4,但代码似乎是3x3。

接下来,电信号可以几乎在瞬间传播通过键矩阵。你应该一个接一个地做每一列,你不需要定时器。只需:列高,读取行,列低,下一列高,等等

之后,只有在尚未按下键的情况下,才能读取键的状态。你试图消除上升沿,但一旦按下该键,它似乎永远都会被按下,当松开该键时,你永远不会寻找下降沿。下降的边缘也会反弹,所以你也需要计算一下。

此外,您正在使用if(x && !y && !z)检查只有一行处于活动状态的状态。如果用户一次按下多个按钮怎么办?对于每个标志,您只需要检查一个输入。

这些要点并不能解决所有问题,但希望能让你一路走得更远!

我怀疑以下代码会给您带来一些问题。

if(!KEY1_READ()){
if(key1_counter == 10)

当计数器正好为10时,您松开按钮的可能性有多大?

你似乎想要一个发布事件,所以我会这样写扫描代码:

if (KEY1_READ()) {
key1_counter++;
} else {
if (key1_counter > 10) {
flag0.fl.f5 = 1;
}
key1_counter = 0;
}

不要忘记在处理完后重置标志。

我找到了解决方案。首先,感谢所有给我建议并提出问题的人。我使用定时器(TIM2(,每1ms创建一个中断。对于我在3列中给出的每个中断,这是我的输出端口,一系列二进制数字,同时使我的所有输入端口(行(接地。第一个序列是1 0 0,第二个是0 1 0,第三个是0 0 1。在那个序列之后,我读取输入(行(,以检测哪一个被设置为高("1"(,这样我就能够通过发出标志来检测按下了哪个键。所有这些都类似于我发布的代码,但我使用了不同的寄存器来使输出(列(从高(逻辑"1"(变为地(逻辑"0"(,即BSRR寄存器。为了检测是否按下了按钮,我使用了去抖动方法。

最新更新