P0功能已实现,按键、LED、过零检测、配网、OTA都已正常实现

This commit is contained in:
2026-09-04 18:49:07 +08:00
parent 2fb61a6458
commit 0de88083ba
47 changed files with 5184 additions and 26 deletions
+265
View File
@@ -0,0 +1,265 @@
/******************************************************************************
* @file key.c
* @brief 按键状态机实现
* @author cyWu <1917507415@qq.com>
* @date 2026.08.25
* @version V1.0.0,首次发布,实现按键短按/长按/释放状态机
******************************************************************************/
#include "key.h"
#include <stddef.h>
static uint32_t s_key_count_time;
static uint8_t s_key_num = USR_KEY_COUNT;
keyCategory_t keyTable[USR_KEY_COUNT];
/**
* @brief 读按键电平到 fsm
* @param key 状态机
* @return 1=已读,0=被屏蔽
*/
static uint8_t get_key_level(keyFSM_t *key)
{
if (key->keyShield == KEY_DISABLE) {
return 0;
}
if (key->keyReadValue == NULL) {
return 0;
}
key->keyLevel = (key->keyReadValue() == key->keyDownLevel) ? Bit_SET : Bit_RESET;
return 1;
}
/**
* @brief 单击 / 双击间隔判定
* @param click 状态机
* @return 1=可以出事件
*/
static uint8_t key_click_frequency(keyFSM_t *click)
{
click->keyInterval++;
switch (click->keyFrequency) {
case CLICK:
if (click->keyInterval >= (KEY_INTERVAL / (DEBOUNCE_TIME * KEY_TIMER_MS))) {
click->eventType = SHORT_Event;
return 1;
}
break;
case DbLCLICK:
if (click->keyInterval >= (KEY_INTERVAL / (DEBOUNCE_TIME * KEY_TIMER_MS))) {
click->eventType = DBCL_Event;
return 1;
}
break;
default:
return 1;
}
return 0;
}
/**
* @brief 按键状态机步进
* @param key_buf 状态机
* @return 1=已处理
*/
static uint8_t read_key_status(keyFSM_t *key_buf)
{
if (!get_key_level(key_buf)) {
return 0;
}
switch (key_buf->keyStatus) {
case KEY_ST_NULL:
if (key_buf->keyLevel == Bit_SET) {
key_buf->keyStatus = KEY_ST_SURE;
}
break;
case KEY_ST_SURE:
if (key_buf->keyLevel == Bit_SET) {
key_buf->eventType = DOWN_Event;
key_buf->keyStatus = KEY_ST_DOWN;
key_buf->keyCount = 0;
key_buf->keyLongFlag = 1;
} else {
key_buf->keyStatus = KEY_ST_NULL;
}
break;
case KEY_ST_DOWN:
if (key_buf->keyLevel != Bit_SET) {
if (key_buf->keyShortFlag == 0) {
key_buf->keyShortFlag = 1;
key_buf->keyFrequency++;
key_buf->keyInterval = 0;
}
if (key_click_frequency(key_buf)) {
key_buf->keyFrequency = 0;
key_buf->keyStatus = KEY_ST_NULL;
}
if ((key_buf->keyCount >= key_buf->keyLongTime / DEBOUNCE_TIME)
&& (key_buf->keyCount < key_buf->keyLastTime / DEBOUNCE_TIME)) {
key_buf->keyFrequency = 0;
key_buf->keyStatus = KEY_ST_NULL;
key_buf->eventType = RELEASE_Event;
}
key_buf->keyCount = 0;
key_buf->keyLongFlag = 1;
} else {
if ((++key_buf->keyCount >= key_buf->keyLastTime / DEBOUNCE_TIME)) {
key_buf->keyCount = 0;
key_buf->keyFrequency = 0;
key_buf->keyStatus = KEY_ST_LONG;
key_buf->eventType = LAST_Event;
key_buf->keyLongFlag = 1;
}
if ((key_buf->keyCount >= key_buf->keyLongTime / DEBOUNCE_TIME)
&& (key_buf->keyCount < key_buf->keyLastTime / DEBOUNCE_TIME)) {
key_buf->keyFrequency = 0;
if (key_buf->keyLongFlag == 1) {
key_buf->eventType = LONG_Event;
key_buf->keyLongFlag = 0;
}
}
key_buf->keyShortFlag = 0;
}
break;
case KEY_ST_LONG:
if (key_buf->keyLevel != Bit_SET) {
key_buf->keyStatus = KEY_ST_NULL;
key_buf->eventType = RELEASE_Event;
}
break;
default:
break;
}
return 1;
}
/**
* @brief 扫描全部按键状态机
* @return 无
*/
static void key_event_process(void)
{
size_t i;
for (i = 0; i < s_key_num; i++) {
(void)read_key_status(&keyTable[i].fsm);
}
}
/**
* @brief 1ms 调用一次;满 DEBOUNCE_TIME 才真正采样
* @return 无
*/
void keyCheckProcess(void)
{
s_key_count_time++;
if (s_key_count_time >= (DEBOUNCE_TIME / KEY_TIMER_MS)) {
s_key_count_time = 0;
key_event_process();
}
}
/**
* @brief 拷贝产品按键表
* @param keys 按键数组,长度 USR_KEY_COUNT
* @return 无
*/
void keyParaInit(keyCategory_t *keys)
{
if (keys == NULL) {
return;
}
if (USR_KEY_COUNT >= KEY_MAX_NUMBER) {
s_key_num = KEY_MAX_NUMBER;
}
memcpy(keyTable, keys, sizeof(keyCategory_t) * s_key_num);
}
/**
* @brief 运行中改长按/连按时长并复位状态
* @param key_event 按键索引
* @param key_param 新参数
* @return 无
*/
void setKeyEventParams(uint8_t key_event, keyCategory_t key_param)
{
if (key_event >= s_key_num) {
return;
}
keyTable[key_event].fsm.keyShield = key_param.fsm.keyShield;
keyTable[key_event].fsm.keyLongTime = key_param.fsm.keyLongTime;
keyTable[key_event].fsm.keyLastTime = key_param.fsm.keyLastTime;
keyTable[key_event].fsm.keyStatus = KEY_ST_NULL;
keyTable[key_event].fsm.eventType = NULL_Event;
keyTable[key_event].fsm.keyCount = 0;
}
/**
* @brief 派发按键事件回调
* @return 无
*/
void keyHandle(void)
{
size_t i;
for (i = 0; i < s_key_num; i++) {
if (keyTable[i].fsm.eventType == NULL_Event) {
continue;
}
switch (keyTable[i].fsm.eventType) {
case RELEASE_Event:
if (keyTable[i].func.releasePressCb != NULL) {
keyTable[i].func.releasePressCb();
}
keyTable[i].fsm.eventType = NULL_Event;
break;
case SHORT_Event:
if (keyTable[i].func.ShortPressCb != NULL) {
keyTable[i].func.ShortPressCb();
}
keyTable[i].fsm.eventType = NULL_Event;
break;
case DOWN_Event:
if (keyTable[i].func.downPressCb != NULL) {
keyTable[i].func.downPressCb();
}
keyTable[i].fsm.eventType = NULL_Event;
break;
case LONG_Event:
if (keyTable[i].func.longPressCb != NULL) {
keyTable[i].func.longPressCb();
}
keyTable[i].fsm.eventType = NULL_Event;
break;
case LAST_Event:
if (keyTable[i].func.lastPressCb != NULL) {
keyTable[i].func.lastPressCb();
}
break;
case DBCL_Event:
if (keyTable[i].func.dbclPressCb != NULL) {
keyTable[i].func.dbclPressCb();
}
keyTable[i].fsm.eventType = NULL_Event;
break;
default:
break;
}
}
}
/**
* @brief 复位指定按键状态机
* @param key_index 按键索引
* @return 无
*/
void reset_key_Status(keyList key_index)
{
if (key_index >= USR_KEY_COUNT) {
return;
}
keyTable[key_index].fsm.keyStatus = KEY_ST_NULL;
keyTable[key_index].fsm.eventType = NULL_Event;
keyTable[key_index].fsm.keyCount = 0;
}