第一版代码,为了在EEPROM保存参数的时候走STM32的CRC,让Codex修改了一下,现在的效果是无法存储,codex表示原因是CRC方法不同,修改到一半今天的额度使用完了,有待后续解决CRC的bug

This commit is contained in:
2026-02-28 17:36:05 +08:00
commit b2fedd58b2
212 changed files with 208290 additions and 0 deletions

148
Interface/Int_Key.c Normal file
View File

@@ -0,0 +1,148 @@
#include "Int_Key.h"
#include <stddef.h>
/* 单个按键扫描上下文:
* raw_level 原始采样电平
* stable_level 去抖后的稳定电平
* long_started 是否已上报过长按开始事件
*/
typedef struct
{
GPIO_TypeDef *port;
uint16_t pin;
Key_t key;
uint8_t stable_level;
uint8_t raw_level;
uint8_t long_started;
uint32_t last_change_ms;
uint32_t press_ms;
} KeyScanCtx_t;
#define KEY_COUNT (5u)
#define KEY_SCAN_PERIOD_MS (5u)
#define KEY_DEBOUNCE_MS (20u)
#define KEY_LONG_MS (400u)
#define KEY_QUEUE_SIZE (12u)
static KeyScanCtx_t s_keys[KEY_COUNT] = {
{KEY1_GPIO_Port, KEY1_Pin, KEY_1, 1u, 1u, 0u, 0u, 0u},
{KEY2_GPIO_Port, KEY2_Pin, KEY_2, 1u, 1u, 0u, 0u, 0u},
{KEY3_GPIO_Port, KEY3_Pin, KEY_3, 1u, 1u, 0u, 0u, 0u},
{KEY4_GPIO_Port, KEY4_Pin, KEY_4, 1u, 1u, 0u, 0u, 0u},
{KEY5_GPIO_Port, KEY5_Pin, KEY_5, 1u, 1u, 0u, 0u, 0u},
};
static KeyAction_t s_queue[KEY_QUEUE_SIZE];
static uint8_t s_q_head = 0u;
static uint8_t s_q_tail = 0u;
static uint32_t s_last_scan_ms = 0u;
static uint8_t queue_next(uint8_t v)
{
/* 环形队列下标递增。 */
v++;
if (v >= KEY_QUEUE_SIZE)
{
v = 0u;
}
return v;
}
static void push_action(Key_t key, KeyEvt_t evt)
{
/* 队列满时丢弃新事件,避免阻塞主循环。 */
uint8_t next = queue_next(s_q_head);
if (next == s_q_tail)
{
return;
}
s_queue[s_q_head].key = key;
s_queue[s_q_head].evt = evt;
s_q_head = next;
}
void Int_Key_Task(void)
{
uint32_t now = HAL_GetTick();
/* 固定周期扫描避免过高频率浪费CPU。 */
if ((uint32_t)(now - s_last_scan_ms) < KEY_SCAN_PERIOD_MS)
{
return;
}
s_last_scan_ms = now;
for (uint8_t i = 0u; i < KEY_COUNT; i++)
{
KeyScanCtx_t *k = &s_keys[i];
uint8_t raw = (HAL_GPIO_ReadPin(k->port, k->pin) == GPIO_PIN_RESET) ? 0u : 1u;
if (raw != k->raw_level)
{
k->raw_level = raw;
k->last_change_ms = now;
}
if ((uint32_t)(now - k->last_change_ms) >= KEY_DEBOUNCE_MS)
{
if (k->stable_level != k->raw_level)
{
k->stable_level = k->raw_level;
if (k->stable_level == 0u)
{
/* 稳定按下:记录按下时间,等待长按判断。 */
k->press_ms = now;
k->long_started = 0u;
}
else
{
/* 稳定释放若未触发长按则上报CLICK否则上报RELEASE。 */
push_action(k->key, k->long_started ? KEY_EVT_RELEASE : KEY_EVT_CLICK);
}
}
}
if (k->stable_level == 0u)
{
uint32_t hold_ms = (uint32_t)(now - k->press_ms);
if (hold_ms >= KEY_LONG_MS)
{
if (k->long_started == 0u)
{
/* 长按开始事件只上报一次。 */
k->long_started = 1u;
push_action(k->key, KEY_EVT_LONG_START);
}
}
}
}
}
bool Int_Key_PopAction(KeyAction_t *action)
{
/* 从事件队列弹出一个事件供上层消费。 */
if (action == NULL)
{
return false;
}
if (s_q_tail == s_q_head)
{
return false;
}
*action = s_queue[s_q_tail];
s_q_tail = queue_next(s_q_tail);
return true;
}
Key_t Int_key_read(void)
{
/* 兼容旧接口:仅返回按键编号,不区分事件类型。 */
KeyAction_t action;
if (Int_Key_PopAction(&action))
{
return action.key;
}
return KEY_NONE;
}