用stm32实现定时器中断方式扫描键盘的实例代码
时间: 2023-05-28 22:02:44 浏览: 466
STM32F103单片机外设开发经典应用实例软件源码合集(76个).zip
这是一个基于STM32的定时器中断方式扫描键盘的实例代码:
```c
// 定义键盘4x4的按键矩阵
uint8_t keys[4][4] = {
{1, 2, 3, 10},
{4, 5, 6, 11},
{7, 8, 9, 12},
{14, 0, 15, 13},
};
// 定义键盘的行和列的GPIO端口和引脚
GPIO_TypeDef* rowGPIO[4] = {GPIOA, GPIOA, GPIOA, GPIOA};
uint16_t rowPin[4] = {GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3};
GPIO_TypeDef* colGPIO[4] = {GPIOA, GPIOA, GPIOA, GPIOA};
uint16_t colPin[4] = {GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_6, GPIO_PIN_7};
// 定义当前按下的键的行和列
int8_t currRow = -1;
int8_t currCol = -1;
// 定义定时器的周期和计数
uint32_t timerPeriod = 100; // 100ms
volatile uint32_t timerCounter = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) {
if (htim->Instance == TIM2) {
// 模拟按键的消抖和长按检测
if (timerCounter >= 3) { // 消抖时间:300ms
int8_t pressedRow = -1;
int8_t pressedCol = -1;
for (int8_t r = 0; r < 4; r++) {
HAL_GPIO_WritePin(rowGPIO[r], rowPin[r], GPIO_PIN_RESET);
for (int8_t c = 0; c < 4; c++) {
if (HAL_GPIO_ReadPin(colGPIO[c], colPin[c]) == GPIO_PIN_RESET) {
pressedRow = r;
pressedCol = c;
break;
}
}
HAL_GPIO_WritePin(rowGPIO[r], rowPin[r], GPIO_PIN_SET);
if (pressedRow >= 0 && pressedCol >= 0) break;
}
if (pressedRow != currRow || pressedCol != currCol) { // 不是同一个按键
currRow = pressedRow;
currCol = pressedCol;
timerCounter = 0;
} else {
timerCounter++; // 长按检测时间:300ms * 3 = 900ms
if (timerCounter >= 9) {
timerCounter = 0;
// 发送长按事件(可选)
}
}
// 发送按键事件
if (pressedRow >= 0 && pressedCol >= 0) {
uint8_t key = keys[pressedRow][pressedCol];
// 发送键码(可选)
}
} else {
timerCounter++;
}
}
}
int main() {
// 初始化GPIO端口
for (int8_t r = 0; r < 4; r++) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = rowPin[r];
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(rowGPIO[r], &GPIO_InitStruct);
HAL_GPIO_WritePin(rowGPIO[r], rowPin[r], GPIO_PIN_SET);
}
for (int8_t c = 0; c < 4; c++) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = colPin[c];
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(colGPIO[c], &GPIO_InitStruct);
}
// 初始化定时器
TIM_HandleTypeDef htim2 = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = (HAL_RCC_GetPCLK1Freq() / 1000000) - 1; // 预分频:1MHz
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = timerPeriod * 10 - 1; // 计数周期:1000 * 100us = 100ms
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim2);
HAL_TIM_Base_Start_IT(&htim2);
while (1) {
// 主循环代码(可选)
}
return 0;
}
```
注:以上代码是一个示例,仅供参考,具体实现方式可能因实际情况而异。需要根据实际需求进行修改和完善。
阅读全文