我想将stm32 l053r8中的键盘与计时器中断连接起来。我有一个SysTick_Handler函数,我在那里处理,按钮的开关卸载,每次按钮计数器等于10,我使用一个标志,以检查按钮何时被按下。所以现在我把键盘的所有行作为输入,所有的键区的列作为输出。我的想法是
我有一个实现,但它不是主函数中的working.For示例,我有一个条件来检查是否按下key1 (expect 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 ++;
}
}
//------------------------------
}发布于 2022-03-03 21:49:00
首先,标题是4x4,但代码似乎是3x3的代码。
接下来,电信号几乎可以瞬间地通过密钥矩阵传播。你应该一个接一个地做每一列,你不需要计时器。只需做:列高,读行,列低,下一列高,等等。
在此之后,您只会读取键的状态,如果它尚未按下。你试图攻克上升的边缘,但一旦键被按下,它似乎永远保持按压,你永远不会寻找下降的边缘,当钥匙被释放。下降的边缘也可以反弹,所以你也需要有一个计数。
此外,您正在检查只使用if(x && !y && !z)激活一行的状态。如果用户一次按多个按钮会怎样?对于每个标志,只需检查一个输入。
这些点并不能解决所有问题,但希望能让你走得更远!
发布于 2022-03-04 00:17:55
我怀疑下面的代码会导致一些问题。
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;
}处理完毕后,不要忘记重置标志。
发布于 2022-03-07 15:22:06
我找到了解决办法。首先,谢谢你们给我提了个建议,并提出了一个问题。我使用了计时器(TIM2),每隔1ms就创建一个中断。对于我在3列中给出的每一个中断,这是我的输出端口,一个二进制数字序列,而我的所有输入端口(行)都被接地了。第一个序列是1 0 0,第2 0 1 0和第3 0 0 1。在该序列之后,我读取输入(行),以检测哪个输入(行)被设置为高(“1”),从而能够通过重选一个标志来检测哪个键被按下。所有这些都类似于我发布的代码,但我使用了不同的寄存器,使输出(列)从高(逻辑"1")到地面(逻辑"0"),即BSRR寄存器。为了检测是否按下按钮,我使用了debounce方法。
https://stackoverflow.com/questions/71343794
复制相似问题