#define ADC_ADC_PRESCALER (RCC->CFGR & RCC_CFGR_ADCPRE_Msk) #define ADC_TWO_CLOCK_CYCLES 2 void adc_init(ADC_TypeDef *adc, uint32_t cr2) { uint8_t cycles; adc->CR2 |= cr2; adc->CR2 |= ADC_CR2_ADON; // wake up // P.223: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’) for at least two ADC clock cycles. cycles = ADC_TWO_CLOCK_CYCLES * ((1 + ADC_ADC_PRESCALER) * 2); // SysClk != AdcClk while (cycles--) { // more than 2 ADC clock cycles __NOP(); } adc->CR2 |= ADC_CR2_CAL; while (adc->CR2 & ADC_CR2_CAL); } void adc_init_channel(ADC_TypeDef *adc, uint8_t channel, enum ADC_NB_CYCLES nb_cycle) { ... } uint16_t adc_read(ADC_TypeDef *adc) { /* Note: If any other bit in this register apart from ADON is changed at the same time, then conversion is not triggered. This is to prevent triggering an erroneous conversion. adc->CR2 |= ADC_CR2_SWSTART | ADC_CR2_ADON; # => Fail !!! */ adc->CR2 |= ADC_CR2_ADON; adc->CR2 |= ADC_CR2_SWSTART; while (!(adc->SR & ADC_SR_EOC)); // wait for End Of Conversion return (uint16_t)adc->DR; }Le canal correspond à la PIN du GPIO sur laquelle est connectée le capteur:
... #define POTENTIOMETER_ADC ADC1 #define POTENTIOMETER_CHANNEL 1 ... adc_init(POTENTIOMETER_ADC, POTENTIOMETER_CR2); adc_init_channel(POTENTIOMETER_ADC, POTENTIOMETER_CHANNEL, ADC_239_5); POTENTIOMETER_ADC->SQR3 |= POTENTIOMETER_CHANNEL << 0;L'initialisation du canal consiste à passer la broche en entrée analogique et à définir le temps d'échantillonage en nombre de cycle. Je n'ai pas beaucoup de raison d'utiliser le maximum de cycles, la précision n'ayant aucune importance ici.
Le code complet: https://gitlab.com/dsx/blue-pill/-/tree/master/stm32f103c8t6/04_adc