hc32l13x实现4x5矩阵键盘,一个ch455实现按键灯光,端口复用,具体实现代码
时间: 2023-11-18 13:04:47 浏览: 146
基于STM32的基于行扫描法的4*4矩阵键盘的实现代码
以下是基于HC32L13X和CH455的4x5矩阵键盘按键灯光实现代码:
```c
#include "hc32l13x.h"
#define KEY_PORT GpioPortA
#define KEY_PIN GpioPin1
#define LED_PORT GpioPortB
#define LED_PIN GpioPin0
/* 矩阵键盘按键对应的行列 */
static const uint8_t matrix_key[4][5] = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10},
{11, 12, 13, 14, 15},
{16, 17, 18, 19, 20}
};
/* 矩阵键盘按键扫描函数 */
static uint8_t scan_key(void)
{
uint8_t i, j;
uint8_t key_val = 0;
/* 遍历每一列 */
for (i = 0; i < 5; i++) {
/* 将当前列置低 */
Gpio_WriteOutputIO(KEY_PORT, KEY_PIN + i, GpioPinReset);
/* 延时一段时间,等待列稳定 */
delay_us(10);
/* 遍历每一行 */
for (j = 0; j < 4; j++) {
/* 判断当前行是否有按键按下 */
if (!Gpio_GetInputIO(KEY_PORT, KEY_PIN + 5 + j)) {
/* 根据行列计算出按键对应的值 */
key_val = matrix_key[j][i];
/* 等待按键松开 */
while (!Gpio_GetInputIO(KEY_PORT, KEY_PIN + 5 + j));
}
}
/* 将当前列置高 */
Gpio_WriteOutputIO(KEY_PORT, KEY_PIN + i, GpioPinSet);
}
return key_val;
}
int main(void)
{
stc_gpio_config_t led_cfg;
uint8_t key_val = 0;
/* 使能GPIO外设时钟 */
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
/* 配置矩阵键盘的行为输入,列为输出 */
for (uint8_t i = 0; i < 5; i++) {
Gpio_Init(KEY_PORT, KEY_PIN + i, GpioDirOut);
Gpio_WriteOutputIO(KEY_PORT, KEY_PIN + i, GpioPinSet);
}
for (uint8_t i = 0; i < 4; i++) {
Gpio_Init(KEY_PORT, KEY_PIN + 5 + i, GpioDirIn);
Gpio_WriteOutputIO(KEY_PORT, KEY_PIN + 5 + i, GpioPinSet);
}
/* 配置LED灯为输出 */
led_cfg.enDir = GpioDirOut;
led_cfg.enDrv = GpioDrvH;
led_cfg.enPuPd = GpioPuPdUp;
led_cfg.enOD = GpioOdDisable;
Gpio_Init(LED_PORT, LED_PIN, &led_cfg);
Gpio_WriteOutputIO(LED_PORT, LED_PIN, GpioPinSet);
/* 配置定时器 */
TmrCfg();
/* 配置中断 */
IntCfg();
while (1) {
/* 扫描矩阵键盘按键 */
key_val = scan_key();
if (key_val != 0) {
/* 点亮对应的LED灯 */
Gpio_WriteOutputIO(LED_PORT, LED_PIN, GpioPinReset);
/* 发送按键值到串口 */
Uart_SendData(UARTCH1, key_val);
} else {
/* 熄灭LED灯 */
Gpio_WriteOutputIO(LED_PORT, LED_PIN, GpioPinSet);
}
}
}
/* 定时器配置函数 */
static void TmrCfg(void)
{
stc_tmr3_init_t init_struct;
/* 使能定时器3时钟 */
Sysctrl_SetPeripheralGate(SysctrlPeripheralTmr3, TRUE);
/* 配置定时器3为定时模式,计数时钟为fLRC/256,计数周期为10ms */
init_struct.enWorkMode = Tmr3WorkModeTimer;
init_struct.enCT = Tmr3Timer;
init_struct.enPRS = Tmr3PCLKDiv256;
init_struct.u16CmpValue = 2000;
Tmr3_Init(&init_struct);
/* 启动定时器3 */
Tmr3_Start();
}
/* 中断配置函数 */
static void IntCfg(void)
{
stc_irq_regi_config_t irq_config;
/* 使能外部中断INT001_IRQn */
NVIC_ClearPendingIRQ(INT001_IRQn);
NVIC_SetPriority(INT001_IRQn, DDL_IRQ_PRIORITY_DEFAULT);
NVIC_EnableIRQ(INT001_IRQn);
/* 配置INT1引脚为下降沿触发 */
Gpio_SetFunc_INT01_1(Gpio_INT01_1);
stc_gpio_intern_data_t stcGpioInternData;
stcGpioInternData.bTouchNvic = TRUE;
stcGpioInternData.enIntf = Gpio_IntFallEdge;
Gpio_InitInt(KEY_PORT, KEY_PIN + 5, &stcGpioInternData);
/* 配置定时器3中断 */
irq_config.enIRQn = Int001_IRQn;
irq_config.enIntSrc = INT_TMR3_GC;
irq_config.pfnCallback = Tmr3GCIntCallback;
Int_RegisterIRQ(&irq_config);
/* 使能定时器3中断 */
Tmr3_EnableIrq();
}
/* 定时器3中断回调函数 */
void Tmr3GCIntCallback(void)
{
static uint32_t cnt = 0;
/* 计数器值加1 */
cnt++;
/* 每500ms翻转一次LED灯 */
if (cnt >= 50) {
cnt = 0;
Gpio_ToggleOutIO(LED_PORT, LED_PIN);
}
}
```
以上代码中,`scan_key()` 函数为矩阵键盘按键扫描函数,通过遍历每一列和每一行来检测是否有按键按下。如果检测到按键按下,则根据行列计算出按键对应的值。
在主函数中循环调用 `scan_key()` 函数,如果返回值不为0,则表示有按键按下,点亮对应的LED灯,并将按键值发送到串口。如果返回值为0,则表示没有按键按下,熄灭LED灯。
另外,为了实现LED灯的闪烁效果,还使用了定时器和中断。在定时器中断回调函数 `Tmr3GCIntCallback()` 中,每500ms翻转一次LED灯。同时,为了实现按键灯光与LED灯的闪烁效果,将LED灯的控制与定时器中断回调函数中的代码合并。
需要注意的是,以上代码中使用到了一些宏定义和函数,如 `delay_us()`、`Sysctrl_SetPeripheralGate()`、`Gpio_Init()`、`Gpio_WriteOutputIO()`、`Gpio_GetInputIO()`、`Uart_SendData()`、`Tmr3_Init()`、`Tmr3_Start()`、`Tmr3_EnableIrq()` 等,这些需要根据具体的开发板和外设进行修改和适配。
阅读全文