190 lines
5.4 KiB
C
190 lines
5.4 KiB
C
/**
|
|
* 按键输入与 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);
|
|
}
|