Add core firmware modules: input, menu, NRF24L01, OLED, protocol, PWM, storage + UI assets

This commit is contained in:
root
2026-06-25 22:55:41 +08:00
parent 97ab93e93d
commit 5c0ff0ce63
22 changed files with 3671 additions and 17 deletions

189
Core/Src/input.c Normal file
View File

@@ -0,0 +1,189 @@
/**
* 按键输入与 ADC 读取模块实现
*/
#include "input.h"
/* 全局数据 */
uint16_t adc_values[ADC_CHANNEL_COUNT];
uint8_t key_values[4];
/* 按键引脚: PB12, PB13, PB14, PB15 */
static const uint16_t key_pins[4] = {GPIO_PIN_12, GPIO_PIN_13, GPIO_PIN_14, GPIO_PIN_15};
/* 按键去抖状态机 */
static uint8_t key_debounce[4]; /* 去抖计数器 */
static uint8_t key_current[4]; /* 当前稳定状态 */
static uint8_t key_prev[4]; /* 上一帧状态 */
static uint32_t key_press_time[4]; /* 按下时刻 (ms) */
static uint8_t key_state[4]; /* 状态: IDLE/PRESS/HOLD/RELEASE */
static uint32_t sys_tick_ms; /* 系统毫秒计数 */
/* ADC 通道映射表 (ADC_INx -> ADC2 channel) */
static const uint32_t adc_channel_map[ADC_CHANNEL_COUNT] = {
ADC_CHANNEL_10, /* ADC_IN0 = PC0 */
ADC_CHANNEL_11, /* ADC_IN1 = PC1 */
ADC_CHANNEL_12, /* ADC_IN2 = PC2 */
ADC_CHANNEL_13, /* ADC_IN3 = PC3 */
ADC_CHANNEL_0, /* ADC_IN4 = PA0 */
ADC_CHANNEL_1, /* ADC_IN5 = PA1 */
ADC_CHANNEL_2, /* ADC_IN6 = PA2 */
ADC_CHANNEL_3, /* ADC_IN7 = PA3 */
ADC_CHANNEL_4, /* ADC_IN8 = PA4 */
ADC_CHANNEL_5, /* ADC_IN9 = PA5 */
ADC_CHANNEL_6, /* ADC_IN10 = PA6 */
ADC_CHANNEL_7, /* ADC_IN11 = PA7 */
ADC_CHANNEL_14, /* ADC_IN12 = PC4 */
ADC_CHANNEL_15, /* ADC_IN13 = PC5 */
ADC_CHANNEL_8, /* ADC_IN14 = PB0 */
ADC_CHANNEL_9, /* ADC_IN15 = PB1 */
};
void Input_Init(void) {
sys_tick_ms = 0;
for (uint8_t i = 0; i < 4; i++) {
key_debounce[i] = 0;
key_current[i] = 0;
key_prev[i] = 0;
key_press_time[i] = 0;
key_state[i] = KEY_STATE_IDLE;
}
for (uint8_t i = 0; i < ADC_CHANNEL_COUNT; i++) {
adc_values[i] = 0;
}
}
/* 由 SysTick 中断调用,更新系统时间 */
void Input_TickInc(void) {
sys_tick_ms++;
}
void Input_Scan(void) {
/* ---- 按键扫描 ---- */
for (uint8_t i = 0; i < 4; i++) {
uint8_t raw = (HAL_GPIO_ReadPin(GPIOB, key_pins[i]) == GPIO_PIN_RESET) ? 1 : 0;
/* 去抖 */
if (raw == key_current[i]) {
key_debounce[i] = 0;
} else {
key_debounce[i]++;
if (key_debounce[i] >= 3) { /* 30ms 去抖 */
key_current[i] = raw;
key_debounce[i] = 0;
}
}
/* 状态机 */
key_prev[i] = key_current[i]; /* 保存上一帧 (在更新前) */
if (key_current[i]) {
/* 按键按下 */
if (key_state[i] == KEY_STATE_IDLE) {
key_state[i] = KEY_STATE_PRESS;
key_press_time[i] = sys_tick_ms;
} else if (key_state[i] == KEY_STATE_PRESS) {
if (sys_tick_ms - key_press_time[i] >= KEY_LONG_PRESS_MS) {
key_state[i] = KEY_STATE_HOLD;
}
}
} else {
/* 按键释放 */
if (key_state[i] == KEY_STATE_PRESS || key_state[i] == KEY_STATE_HOLD) {
key_state[i] = KEY_STATE_RELEASE;
} else {
key_state[i] = KEY_STATE_IDLE;
}
}
key_values[i] = key_current[i];
}
/* ---- ADC 读取 (轮询单通道) ---- */
static uint8_t adc_scan_idx = 0;
/* 配置当前通道并读取 */
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = adc_channel_map[adc_scan_idx];
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES_5;
HAL_ADC_ConfigChannel(&hadc2, &sConfig);
HAL_ADC_Start(&hadc2);
if (HAL_ADC_PollForConversion(&hadc2, 5) == HAL_OK) {
adc_values[adc_scan_idx] = HAL_ADC_GetValue(&hadc2);
}
HAL_ADC_Stop(&hadc2);
adc_scan_idx++;
if (adc_scan_idx >= ADC_CHANNEL_COUNT) adc_scan_idx = 0;
}
/* ---- 按键查询 ---- */
uint8_t Input_GetKey(void) {
for (uint8_t i = 0; i < 4; i++) {
if (key_state[i] == KEY_STATE_PRESS) {
key_state[i] = KEY_STATE_IDLE; /* 消费事件 */
return i;
}
}
return KEY_NONE;
}
uint8_t Input_GetKeyState(uint8_t key) {
if (key > 3) return KEY_STATE_IDLE;
return key_state[key];
}
uint8_t Input_IsKeyPressed(uint8_t key) {
if (key > 3) return 0;
if (key_state[key] == KEY_STATE_PRESS) {
key_state[key] = KEY_STATE_IDLE;
return 1;
}
return 0;
}
uint8_t Input_IsKeyHeld(uint8_t key) {
if (key > 3) return 0;
return (key_state[key] == KEY_STATE_HOLD) ? 1 : 0;
}
uint8_t Input_IsKeyReleased(uint8_t key) {
if (key > 3) return 0;
if (key_state[key] == KEY_STATE_RELEASE) {
key_state[key] = KEY_STATE_IDLE;
return 1;
}
return 0;
}
/* ---- ADC 查询 ---- */
uint16_t Input_GetADC(uint8_t ch) {
if (ch >= ADC_CHANNEL_COUNT) return 0;
return adc_values[ch];
}
uint16_t Input_GetADC_Percent(uint8_t ch) {
if (ch >= ADC_CHANNEL_COUNT) return 0;
uint32_t val = adc_values[ch];
return (uint16_t)(val * 1000 / ADC_RAW_MAX);
}
void Input_ReadAllADC(void) {
/* 已在 Input_Scan 中轮询完成 */
}
/* ---- 引脚编码解码 ---- */
GPIO_TypeDef* Config_GetPort(uint16_t pin_code) {
uint8_t port = (pin_code >> 8) & 0x0F;
switch (port) {
case 0: return GPIOA;
case 1: return GPIOB;
case 2: return GPIOC;
case 3: return GPIOD;
default: return GPIOA;
}
}
uint16_t Config_GetPin(uint16_t pin_code) {
return (uint16_t)1 << (pin_code & 0x0F);
}