#define ADC_MAX_VALUE 4096 // 2^12
#define SYSTICK_LOAD_MAX 16000000 // 0.625s @24 MHz
#define SYSTICK_LOAD_MIN 1200000 // 0.050s @24 MHz
#define SYSTICK_LOAD_STEP ((SYSTICK_LOAD_MAX - SYSTICK_LOAD_MIN) / ADC_MAX_VALUE)
uint16_t adc_value = ADC_MAX_VALUE / 2;
int
main (void) {
clock_hse(); // 8 MHz
#ifdef USE_PLL
clock_pll(RCC_CFGR_PLLMULL3, 0); // 24 MHz, ADC 12 MHz
#endif
SystemCoreClockUpdate(); // Update globale variable SystemCoreClock
RCC->APB2ENR |= ADC_APB2EN | CFG_APB2EN;
gpio_pin_init(ONBOARD_LED_GPIO, ONBOARD_LED_PIN, O02_GP_PP);
adc_init(POTENTIOMETER_ADC, POTENTIOMETER_CR2 | ADC_CR2_CONT); // software start & CONTinous mode
adc_init_channel(POTENTIOMETER_ADC, POTENTIOMETER_CHANNEL, ADC_239_5);
POTENTIOMETER_ADC->SQR3 |= POTENTIOMETER_CHANNEL << 0;
POTENTIOMETER_ADC->CR1 |= ADC_CR1_EOSIE; // End Of Sequence Interrupt Enable
__disable_irq();
NVIC_EnableIRQ(ADC1_2_IRQn);
__enable_irq();
systick_delay_irq(SystemCoreClock / 2); // 0.5 s @24 MHz
POTENTIOMETER_ADC->CR2 |= ADC_CR2_ADON;
POTENTIOMETER_ADC->CR2 |= ADC_CR2_SWSTART;
return 0;
}
void
ADC1_2_IRQHandler(void) {
adc_value = (uint16_t)POTENTIOMETER_ADC->DR;
}
void
SysTick_Handler(void) {
ONBOARD_LED_GPIO->ODR ^= 1 << ONBOARD_LED_PIN; // toggle state
SysTick->LOAD = SYSTICK_LOAD_MIN + (adc_value * SYSTICK_LOAD_STEP);
}
Comme souvent avec les interruptions on ne trouve pas de boucle infinie (et ça me laisse sur le cul à chaque fois).
Le code complet: https://gitlab.com/dsx/blue-pill/-/tree/master/stm32f103c8t6/04_adc_irq