0 Abstract
This (short) lesson will cover the advanced usage of the Analog-Digital-Converter (ADC) in the STM32F4 MCU. We will access multiple ADC input pins, here we are going to use PA4 and PA5 alternately as an example. No DMA is used in this code. This example is mainly for those who have read ADC values in 8-bit machines as it uses the same technique.
1 Setup sequence
This setup sequence is the same like in the unit covering the basic ADC usage. It starts, as usual, with the correct port initialisation:
///////////////////////// //ADC1 Init // ///////////////////////// //Port config and GPIOA power up RCC->AHB1ENR |= (1 << 0); GPIOA->MODER |= (3 << (4 << 1)); //Set PA4 to analog mode GPIOA->MODER |= (3 << (5 << 1)); //Set PA5 to analog mode
followed by ADC configuration:
//ADC config sequence RCC->APB2ENR |= (1 << 8); //Enable ADC1 clock (Bit8) ADC1->CR1 &= ~(1 << 8); //SCAN mode disabled (Bit8) ADC1->CR1 &= ~(3 << 24); //12bit resolution (Bit24,25 0b00) ADC1->SQR1 &= ~(0x0F << 20); //Set number of conversions projected (L[3:0] 0b0000) ADC1->SQR3 &= ~(0x3FFFFFFF); //Clear whole 1st 30bits in register ADC1->SQR3 |= (4 << 0); //First conversion in regular sequence: PB4 as ADC1_4 (-> select ADC channel 4 as first (and only) conversion) ADC1->CR2 &= ~(1 << 1); //Single conversion ADON=1 ADC1->CR2 &= ~(1 << 11); //Right alignment of data bits bit12....bit0 ADC1->SMPR2 |= (7 << 0); //Sampling rate 480 cycles. 16MHz bus clock for ADC. 1/16MHz = 62.5ns. 480*62.5ns=30us ADC1->CR2 |= (1 << 0); //Switch on ADC1 //ADC ready for use
There is also one dummy conversion of the PA4 input but that is not necessary.
2 Reading multiple ADC related pins
Next we define a function that maps ADC1 to different channels:
int get_adc(int adc_channel) { int adc_val = 0; switch(adc_channel) { case 1: ADC1->SQR3 &= ~(0x3FFFFFFF); ADC1->SQR3 |= (4 << 0); //Connect to ADC channel 4 (PA4) break; case 2: ADC1->SQR3 &= ~(0x3FFFFFFF); ADC1->SQR3 |= (5 << 0); //Connect to ADC channel 5 (PA5) break; } ADC1->CR2 |= (1 << 30); //Start conversion using SWSTART bit while(!(ADC1->SR & (1 << 1))); //Wait until conversion is complete adc_val = ADC1->DR; //Read value from register return adc_val; }
Please note that the SQR3 register must be reset first before writing the new value to SQ1[4:0] bits! We write 0 into bits 29:0 by using the negation of ADC1->SQR3 &= ~(0x3FFFFFFF);