用中断写stm32矩阵键盘代码
时间: 2024-01-29 11:04:24 浏览: 139
以下是一个简单的基于中断的STM32矩阵键盘代码示例。假设我们使用的是4x4的矩阵键盘。
```c
#include "stm32f10x.h"
#define KEYPAD_PORT GPIOA
#define ROW_1 GPIO_Pin_0
#define ROW_2 GPIO_Pin_1
#define ROW_3 GPIO_Pin_2
#define ROW_4 GPIO_Pin_3
#define COL_1 GPIO_Pin_4
#define COL_2 GPIO_Pin_5
#define COL_3 GPIO_Pin_6
#define COL_4 GPIO_Pin_7
void Keypad_Init(void);
void Keypad_Scan(void);
uint8_t Keypad_Buffer; // 存储按下的键值
int main(void)
{
Keypad_Init();
while (1) {
// 在主循环中不需要做任何事情,因为中断会处理按键事件。
}
}
void Keypad_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = ROW_1 | ROW_2 | ROW_3 | ROW_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(KEYPAD_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = COL_1 | COL_2 | COL_3 | COL_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(KEYPAD_PORT, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
EXTI_ClearITPendingBit(EXTI_Line0 | EXTI_Line1 | EXTI_Line2 | EXTI_Line3);
EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1 | EXTI_Line2 | EXTI_Line3;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
void Keypad_Scan(void)
{
uint8_t row, col;
static uint8_t last_key = 0xFF; // 上一次按下的键值,初始值为无效值
// 扫描行
for (row = 0; row < 4; row++) {
GPIO_ResetBits(KEYPAD_PORT, ROW_1 << row);
for (col = 0; col < 4; col++) {
if (!GPIO_ReadInputDataBit(KEYPAD_PORT, COL_1 << col)) {
// 检测到按键按下
uint8_t key = row * 4 + col;
if (key != last_key) {
// 避免重复按键
Keypad_Buffer = key;
last_key = key;
}
}
}
GPIO_SetBits(KEYPAD_PORT, ROW_1 << row);
}
}
// 中断处理函数
void EXTI0_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line0) != RESET) {
Keypad_Scan();
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
void EXTI1_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line1) != RESET) {
Keypad_Scan();
EXTI_ClearITPendingBit(EXTI_Line1);
}
}
void EXTI2_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line2) != RESET) {
Keypad_Scan();
EXTI_ClearITPendingBit(EXTI_Line2);
}
}
void EXTI3_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line3) != RESET) {
Keypad_Scan();
EXTI_ClearITPendingBit(EXTI_Line3);
}
}
```
在初始化函数中,我们设置了4个行引脚为输入上拉模式,4个列引脚为推挽输出模式。然后我们初始化了4个外部中断线,并将它们映射到4个按键上。在中断处理函数中,我们调用了Keypad_Scan()函数来扫描矩阵键盘,检测是否有按键按下,如果有,将按键值存储在Keypad_Buffer变量中。
在主循环中,我们不需要做任何事情,因为中断会处理按键事件。我们只需要在需要的时候读取Keypad_Buffer变量即可。
阅读全文