fix(led): relight the key board after hot-plug or late insert

TM1629 drops display-on when the board loses power, while key reads still work. Re-enable the display and rewrite the current pattern when the board is seen again.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yuquanjun 2026-10-09 17:28:15 +08:00
parent 3fab5024a9
commit 71f14f69f9
1 changed files with 60 additions and 18 deletions

View File

@ -36,17 +36,35 @@ static void TM1629D_DIO_Output(void)
gpio_init(TM1629D_DIO_PORT, &g);
}
/* DIO 引脚切换为输入模式(读按键) */
/* DIO 引脚切换为输入模式(读按键)。上拉:板子拔掉时读到全 1,用来识别未插入。 */
static void TM1629D_DIO_Input(void)
{
gpio_init_type g;
gpio_default_para_init(&g);
g.gpio_mode = GPIO_MODE_INPUT;
g.gpio_pull = GPIO_PULL_NONE;
g.gpio_pull = GPIO_PULL_UP;
g.gpio_pins = TM1629D_DIO_PIN;
gpio_init(TM1629D_DIO_PORT, &g);
}
/* 显示模式 + 开显示。芯片掉电(拔插/后插入)后必须重发,否则显存写了也不亮。 */
static void TM1629D_DisplayOn(void)
{
TM1629D_STB_L();
TM1629D_Delay1us();
TM1629D_SendByte(0x40);
TM1629D_STB_H();
TM1629D_Delay1us();
TM1629D_STB_L();
TM1629D_Delay1us();
TM1629D_SendByte(0x8F);
TM1629D_STB_H();
TM1629D_Delay1us();
}
static void TM1629D_OnKeySample(const uint8_t *keyBuf);
/* GPIO初始化 */
void TM1629D_Key_LED_Init(void)
{
@ -74,23 +92,8 @@ void TM1629D_Key_LED_Init(void)
TM1629D_CLK_H();
TM1629D_DIO_H();
// 清寄存器
TM1629D_AllLedOff();
// 配置TM1629D为“普通显示模式”(无译码,8个GRID)
TM1629D_STB_L();
TM1629D_Delay1us();
TM1629D_SendByte(0x40); // 普通模式命令(文档1-46)
TM1629D_STB_H();
TM1629D_Delay1us();
// 配置亮度(示例:中亮度)
TM1629D_STB_L();
TM1629D_Delay1us();
TM1629D_SendByte(0x8F); // 0x88(最暗)~0x8F(最亮)
TM1629D_STB_H();
TM1629D_Delay1us();
TM1629D_AllLedOn(COLOR_OTHER);
TM1629D_DisplayOn();
TM1629D_UpdateDisplay(0);
}
@ -190,6 +193,13 @@ Key_TypeDef TM1629D_GetKey(void)
{
uint8_t keyBuf[4] = {0};
TM1629D_ReadKeyData(keyBuf); // 读取原始按键数据(与原逻辑一致)
TM1629D_OnKeySample(keyBuf);
/* 拔掉时上拉读到全 1,不能当成按键 */
if (keyBuf[0] == 0xFF && keyBuf[1] == 0xFF &&
keyBuf[2] == 0xFF && keyBuf[3] == 0xFF)
{
return KEY_NONE;
}
// 遍历映射表匹配按键(C语言循环写法)
for (uint8_t i = 0; i < KEY_MAP_LEN; i++)
@ -291,6 +301,8 @@ void TM1629D_SetGridSeg(uint8_t grid, uint8_t seg, uint8_t on)
void TM1629D_UpdateDisplay(uint8_t u8LH)
{
uint8_t grid;
/* 每次刷灯都重开显示,后插入的板子不用等下一次拔插检测 */
TM1629D_DisplayOn();
TM1629D_STB_L();
TM1629D_Delay1us();
@ -310,6 +322,36 @@ void TM1629D_UpdateDisplay(uint8_t u8LH)
TM1629D_Delay1us();
}
/* 连续全 0xFF 视为板子不在;重新读到键值后把当前灯态刷回去,闪烁逻辑不用重来。 */
static uint8_t s_board_present;
static uint8_t s_absent_cnt;
static uint8_t s_present_cnt;
static void TM1629D_OnKeySample(const uint8_t *keyBuf)
{
int absent = (keyBuf[0] == 0xFF && keyBuf[1] == 0xFF &&
keyBuf[2] == 0xFF && keyBuf[3] == 0xFF);
if (absent)
{
s_present_cnt = 0;
if (s_absent_cnt < 8)
s_absent_cnt++;
if (s_absent_cnt >= 3)
s_board_present = 0;
return;
}
s_absent_cnt = 0;
if (s_present_cnt < 8)
s_present_cnt++;
if (!s_board_present && s_present_cnt >= 2)
{
s_board_present = 1;
TM1629D_UpdateDisplay(0);
}
}
// 向指定地址写入1字节数据(单独调用调试用)
void TM1629D_WriteDisplayByte(uint8_t addr, uint8_t data)
{