4x4矩阵键盘stm32无法连接
我想用定时器中断连接 stm32 l053r8 中的键盘。我有一个 SysTick_Handler 函数,我正在处理按钮的开关去抖,每次按钮计数器等于 10 时,我都会使用一个标志来检查按钮何时被按下。所以现在我将键盘的所有行作为输入,将键盘的所有列作为输出。我的想法是
- 每个计时器 int,它都会激活一个新列并读取 4 行输入
- 检查按钮标志是否为“1”并将适当的消息发送到屏幕。
我有一个实现,但它不起作用。例如,在主函数中,我有一个条件,检查是否按下了 key1(期望 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 ++;
}
}
//------------------------------
}
I want to interface a keypad in stm32 l053r8 with timer interrupt. I have a SysTick_Handler function which I am handling there the switch debouncing of push buttons and every time the push button counter gets equal to 10 I am using a flag in order to check when the button is pressed. So now I have all the rows of the keypad as input and all the columns of the keypad as output. My idea is
- Every timer int, it activates a new column and reads the 4 row inputs
- Check if a button flag is "1" and send the appropriate message to the screen.
I have an implementation but it is not working.For example in main function I have a condition that checks if the key1 (expect 1 as output in screen) is pressed but it doesn't do anything. Any advice would be great.
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 ++;
}
}
//------------------------------
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,您的标题显示为 4x4,但代码似乎适用于 3x3。
接下来,电信号几乎可以立即通过按键矩阵传播。你应该一个接一个地完成每一列,你不需要计时器来做到这一点。只需执行:列高、读取行、列低、下一列高等。
之后,您仅读取按键尚未按下的状态。您尝试对上升沿进行去抖,但是一旦按下按键,它似乎就永远保持按下状态,当松开按键时,您永远不会寻找下降沿。下降沿也可能反弹,因此您也需要在那里进行计数。
此外,您还可以使用
if(x && !y && !z)
检查只有一行处于活动状态的状态。如果用户一次按下多个按钮怎么办?对于每个标志,您只需要检查一个输入。这些要点并不能解决所有问题,但希望能让您走得更远!
First, your title says 4x4 but the code appears to be for 3x3.
Next, an electrical signal can propagate through a key matrix almost instantaneously. You should do do every column one straight after the other, you don't need a timer to do that. Just do: column high, read row, column low, next column high, etc.
After that, you only read the state of the key if it is not already pressed. You try to debounce the rising edge, but once the key is pressed it seems to stay pressed for ever, you never look for the falling edge when the key is released. Falling edges can bounce too, so you need to have a count there too.
Also, you are checking for the state where only one row is active with
if(x && !y && !z)
. What if the user presses more than one button at a time? For each flag you only need to check for one input.These points won't fix everything, but hopefully will get you further along the way!
我怀疑以下代码会给您带来一些问题。
当计数器恰好为 10 时,您释放按钮的机会有多大?
您似乎想要一个释放事件,所以我会像这样编写扫描代码:
处理完后不要忘记重置标志。
I suspect the following code to cause you some problems.
What are the chances that you will release the button when counter is exactly 10?
You seem to want an on-release event, so I would write the scanning code like so:
Don't forget to reset the flag after you're done processing it.
我找到了解决方案。首先感谢所有给我建议并提出问题的人。我使用定时器(TIM2)并每 1ms 创建一个中断。对于每个中断,我在第 3 列(即我的输出端口)中给出一系列二进制数,同时将所有输入端口(行)接地。第一个序列是 1 0 0,第二个是 0 1 0,第三个是 0 0 1。在该序列之后,我读取输入(行)以检测哪一个被设置为高(“1”),这样我就能够通过升起标志来检测按下了哪个键。所有这些都与我发布的代码类似,但我使用了不同的寄存器来使输出(列)从高(逻辑“1”)到地(逻辑“0”),即 BSRR 寄存器。为了检测是否按下按钮,我使用去抖方法。
I found the solution for that. First of all thank all of you that gave me an advice and post a question. I used the timer (TIM2) and created an interrupt every 1ms. For each interrupt I was giving in the 3 column, which was my output ports, a sequence of binary numbers, while having all my input ports(rows) grounded. First sequence was 1 0 0, second 0 1 0 and third 0 0 1. After that sequence I was reading the inputs(rows) in order to detect which one was set at high("1"), with that I was able to detect which key was pressed by rasing a flag. All of that is similar to the code I 've posted but I used different register for make the outputs(columns) goes from high(logic "1") to ground(logic "0"), that is the BSRR register. For detection if a button is pressed I use the debounce method.