hc32l13x实现4x5矩阵键盘,一个ch455实现按键灯光,端口复用,具体实现代码
时间: 2023-11-18 21:04:47 浏览: 82
以下是基于HC32L13X的4x5矩阵键盘和按键灯光的实现代码:
```c
#include "hc32l13x.h"
#include "hc32_gpio.h"
#define KEY_PORT GpioPortA
#define KEY_PIN0 GpioPin0
#define KEY_PIN1 GpioPin1
#define KEY_PIN2 GpioPin2
#define KEY_PIN3 GpioPin3
#define KEY_PIN4 GpioPin4
#define KEY_PIN5 GpioPin5
#define KEY_PIN6 GpioPin6
#define KEY_PIN7 GpioPin7
#define LED_PORT GpioPortB
#define LED_PIN0 GpioPin0
#define LED_PIN1 GpioPin1
#define LED_PIN2 GpioPin2
#define LED_PIN3 GpioPin3
#define KEY_SCAN_INTERVAL 20 // 按键扫描间隔(ms)
#define KEY_LONG_PRESS_TIME 1000 // 长按时间(ms)
#define KEY_PRESS 0 // 按键按下
#define KEY_RELEASE 1 // 按键释放
#define LED_ON 0 // 灯亮
#define LED_OFF 1 // 灯灭
// 矩阵键盘状态类型定义
typedef struct
{
uint8_t key_state; // 按键状态:KEY_PRESS-按下,KEY_RELEASE-释放
uint8_t key_cnt; // 按键计数器
} key_state_t;
// 按键灯光状态类型定义
typedef struct
{
uint8_t led_state; // 灯光状态:LED_ON-亮,LED_OFF-灭
uint8_t led_cnt; // 灯光计数器
} led_state_t;
// 矩阵键盘状态数组
static key_state_t key_state[4][5];
// 按键灯光状态数组
static led_state_t led_state[4];
// 矩阵键盘按键映射表
static const uint8_t key_map[4][5] = {
{1, 2, 3, 10, 11},
{4, 5, 6, 12, 13},
{7, 8, 9, 14, 15},
{0, 16, 17, 18, 19}
};
// 矩阵键盘扫描函数
void KeyScan(void)
{
static uint8_t key_cnt = 0;
static uint8_t key_state_before[4][5] = {0}; // 上一次按键状态
uint8_t key_state_now[4][5] = {0}; // 当前按键状态
uint8_t i, j;
// 配置键盘列为输出
Gpio_InitIO(KEY_PORT, KEY_PIN0, GpioDirOut);
Gpio_InitIO(KEY_PORT, KEY_PIN1, GpioDirOut);
Gpio_InitIO(KEY_PORT, KEY_PIN2, GpioDirOut);
Gpio_InitIO(KEY_PORT, KEY_PIN3, GpioDirOut);
Gpio_InitIO(KEY_PORT, KEY_PIN4, GpioDirOut);
// 配置键盘行为输入
Gpio_InitIO(KEY_PORT, KEY_PIN5, GpioDirIn);
Gpio_InitIO(KEY_PORT, KEY_PIN6, GpioDirIn);
Gpio_InitIO(KEY_PORT, KEY_PIN7, GpioDirIn);
// 扫描键盘
for (i = 0; i < 5; i++)
{
// 每次只有一列输出,其余列为高阻态
switch (i)
{
case 0:
Gpio_SetIO(KEY_PORT, KEY_PIN0, GpioPinStateLow);
break;
case 1:
Gpio_SetIO(KEY_PORT, KEY_PIN1, GpioPinStateLow);
break;
case 2:
Gpio_SetIO(KEY_PORT, KEY_PIN2, GpioPinStateLow);
break;
case 3:
Gpio_SetIO(KEY_PORT, KEY_PIN3, GpioPinStateLow);
break;
case 4:
Gpio_SetIO(KEY_PORT, KEY_PIN4, GpioPinStateLow);
break;
}
// 等待一段时间,让电平稳定
HAL_Delay(1);
// 检测每行的按键状态
if (Gpio_GetIO(KEY_PORT, KEY_PIN5) == GpioPinStateLow)
{
key_state_now[0][i] = KEY_PRESS;
}
if (Gpio_GetIO(KEY_PORT, KEY_PIN6) == GpioPinStateLow)
{
key_state_now[1][i] = KEY_PRESS;
}
if (Gpio_GetIO(KEY_PORT, KEY_PIN7) == GpioPinStateLow)
{
key_state_now[2][i] = KEY_PRESS;
}
// 恢复所有列为高阻态
Gpio_SetIO(KEY_PORT, KEY_PIN0, GpioPinStateHigh);
Gpio_SetIO(KEY_PORT, KEY_PIN1, GpioPinStateHigh);
Gpio_SetIO(KEY_PORT, KEY_PIN2, GpioPinStateHigh);
Gpio_SetIO(KEY_PORT, KEY_PIN3, GpioPinStateHigh);
Gpio_SetIO(KEY_PORT, KEY_PIN4, GpioPinStateHigh);
// 等待一段时间,让电平稳定
HAL_Delay(1);
}
// 检测按键状态变化
for (i = 0; i < 4; i++)
{
for (j = 0; j < 5; j++)
{
if (key_state_now[i][j] != key_state_before[i][j])
{
key_state[i][j].key_state = key_state_now[i][j];
key_state[i][j].key_cnt = 0;
}
else
{
if (key_state[i][j].key_cnt < 255)
{
key_state[i][j].key_cnt++;
}
}
}
}
// 保存本次按键状态
for (i = 0; i < 4; i++)
{
for (j = 0; j < 5; j++)
{
key_state_before[i][j] = key_state_now[i][j];
}
}
// 计算按键事件
if (key_cnt < KEY_SCAN_INTERVAL)
{
key_cnt++;
}
else
{
key_cnt = 0;
for (i = 0; i < 4; i++)
{
for (j = 0; j < 5; j++)
{
// 检测按键按下事件
if (key_state[i][j].key_state == KEY_PRESS && key_state[i][j].key_cnt >= 2)
{
// 根据按键码执行相应操作
switch (key_map[i][j])
{
case 0:
// 处理按键0的按下事件
break;
case 1:
// 处理按键1的按下事件
break;
case 2:
// 处理按键2的按下事件
break;
// ...
default:
break;
}
}
// 检测按键长按事件
if (key_state[i][j].key_state == KEY_PRESS && key_state[i][j].key_cnt >= KEY_LONG_PRESS_TIME / KEY_SCAN_INTERVAL)
{
// 根据按键码执行相应操作
switch (key_map[i][j])
{
case 0:
// 处理按键0的长按事件
break;
case 1:
// 处理按键1的长按事件
break;
case 2:
// 处理按键2的长按事件
break;
// ...
default:
break;
}
}
}
}
}
}
// 按键灯光控制函数
void LedCtrl(void)
{
static uint8_t led_cnt = 0;
uint8_t i;
if (led_cnt < KEY_SCAN_INTERVAL)
{
led_cnt++;
}
else
{
led_cnt = 0;
for (i = 0; i < 4; i++)
{
// 处理按键灯光亮度
if (led_state[i].led_cnt < 255)
{
led_state[i].led_cnt++;
}
// 处理按键灯光开关
if (led_state[i].led_state == LED_ON)
{
Gpio_SetIO(LED_PORT, i, GpioPinStateLow);
}
else
{
Gpio_SetIO(LED_PORT, i, GpioPinStateHigh);
}
}
}
}
int main(void)
{
// 初始化GPIO
Gpio_InitIO(KEY_PORT, KEY_PIN5, GpioDirIn);
Gpio_InitIO(KEY_PORT, KEY_PIN6, GpioDirIn);
Gpio_InitIO(KEY_PORT, KEY_PIN7, GpioDirIn);
Gpio_InitIO(LED_PORT, LED_PIN0, GpioDirOut);
Gpio_InitIO(LED_PORT, LED_PIN1, GpioDirOut);
Gpio_InitIO(LED_PORT, LED_PIN2, GpioDirOut);
Gpio_InitIO(LED_PORT, LED_PIN3, GpioDirOut);
// 矩阵键盘和按键灯光初始化
memset(key_state, 0, sizeof(key_state));
memset(led_state, LED_OFF, sizeof(led_state));
// 主循环
while (1)
{
// 扫描键盘
KeyScan();
// 控制按键灯光
LedCtrl();
}
}
```
上面的代码实现了4x5矩阵键盘和按键灯光的功能。其中,按键扫描和灯光控制函数分别在主循环中调用,可以根据实际需求自行调整调用频率。同时,根据具体硬件的接口定义,需要修改代码中的GPIO端口和引脚定义。
阅读全文