void BoardButtons_Init(void)
{
GPIO_InitTypeDef gpio;
ADC_CommonInitTypeDef common;
ADC_InitTypeDef adc;
if (s_initialized) return;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA |
RCC_AHB1Periph_GPIOF, ENABLE);
gpio.GPIO_Pin = GPIO_Pin_0;
gpio.GPIO_Mode = GPIO_Mode_AN; //配置为模拟引脚
gpio.GPIO_OType = GPIO_OType_PP;
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
gpio.GPIO_Speed = GPIO_Low_Speed;
GPIO_Init(GPIOA, &gpio);
gpio.GPIO_Pin = GPIO_Pin_9;
gpio.GPIO_Mode = GPIO_Mode_IN;
gpio.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOF, &gpio);
PeripheralEnable(PeripheralADC1, true);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
ADC_CommonStructInit(&common);
common.ADC_Mode = ADC_Mode_Independent;
common.ADC_Prescaler = ADC_Prescaler_Div8;
common.ADC_DMAAccessMode = 0U;
common.ADC_TwoSamplingDelay = 0U;
ADC_CommonInit(&common);
ADC_StructInit(&adc);
adc.ADC_Resolution = ADC_Resolution_12b;
adc.ADC_ScanConvMode = DISABLE;
adc.ADC_ContinuousConvMode = DISABLE;
adc.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
adc.ADC_ExternalTrigConv = 0U;
adc.ADC_DataAlign = ADC_DataAlign_Right;
adc.ADC_NbrOfConversion = 1U;
ADC_Init(KEY_ADC, &adc);
ADC_RegularChannelConfig(KEY_ADC, ADC_Channel_0, 1U,
ADC_SampleTime_56Cycles);
ADC_Cmd(KEY_ADC, ENABLE);
}
static uint16_t adc_read_average(void)
{
uint32_t total = 0U;
uint32_t sample_index;
for (sample_index = 0U; sample_index < 4U; ++sample_index) {
uint32_t timeout = 100000U; //读取过程超时时间
ADC_ClearFlag(ADC1, ADC_FLAG_EOC | ADC_FLAG_STRT | ADC_FLAG_OVR);
ADC_SoftwareStartConv(ADC1);
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET && timeout-- != 0U) {}
if (timeout == 0U) return 4095U;
total += ADC_GetConversionValue(ADC1);
}
return (uint16_t)(total / 4U);
}
typedef enum {
BOARD_BUTTON_NONE = 0,
BOARD_BUTTON_UP,
BOARD_BUTTON_DOWN,
BOARD_BUTTON_OK,
BOARD_BUTTON_PHOTO,
BOARD_BUTTON_BACK,
BOARD_BUTTON_POWER
} BoardButtonEvent;
static BoardButtonEvent decode_adc(uint16_t raw)
{
if (raw < 493U) return BOARD_BUTTON_UP;
if (raw < 1485U) return BOARD_BUTTON_DOWN;
if (raw < 2414U) return BOARD_BUTTON_OK;
if (raw < 3449U) return BOARD_BUTTON_PHOTO;
return BOARD_BUTTON_NONE;
}
bool BoardButtons_Scan(uint32_t now_ms, BoardButtonEvent *event)
{
BoardButtonEvent decoded;
bool power_low;
if (!s_initialized || event == NULL) return false; //是否初始化
*event = BOARD_BUTTON_NONE;
/* PF9 short release is BACK; a continuous 3-second press is POWER. */
power_low = GPIO_ReadInputDataBit(GPIOF, GPIO_Pin_9) == Bit_RESET;
if (power_low) {
if (s_power_debounce < 2U) ++s_power_debounce;
if (!s_power_pressed && s_power_debounce >= 2U) { //防抖
s_power_pressed = true;
s_power_pressed_at = now_ms;
s_power_long_sent = false;
}
if (s_power_pressed && !s_power_long_sent &&
(uint32_t)(now_ms - s_power_pressed_at) >= 3000U) { //电源触发长按
s_power_long_sent = true;
*event = BOARD_BUTTON_POWER;
return true;
}
} else {
s_power_debounce = 0U;
if (s_power_pressed) {
s_power_pressed = false;
if (!s_power_long_sent) {
*event = BOARD_BUTTON_BACK;
return true;
}
}
}
decoded = decode_adc(adc_read_average());
if (decoded != s_candidate) {
s_candidate = decoded;
s_candidate_count = 1U;
return false;
}
if (s_candidate_count < 2U) { //防抖
++s_candidate_count;
return false;
}
if (decoded != s_stable) {
s_stable = decoded;
if (decoded != BOARD_BUTTON_NONE) {
*event = decoded;
return true;
}
}
return false;
}