/** * 按键输入与 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_IsKeyHeldFor(uint8_t key, uint32_t ms) { if (key > 3) return 0; /* 按键按下且按住时间 >= ms */ if (key_current[key] && (sys_tick_ms - key_press_time[key] >= ms)) return 1; return 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); }