The aim of this recipe is to configure the ADC in single-conversion mode and then convert the voltage set by the thumbwheel into a 12-bit digital value. We'll configure the ADC to generate an interrupt at the end of each conversion and write an interrupt handler to read the ADC and initiate a new conversion. The only task for our main function to perform is to output the ADC value to the LEDs, but as there are only 8 LEDs we can only display the most-significant 8-bits of the ADC value. We'll call this recipe adcISR_c5v0
.
To set up the ADC follow the steps outlined:
adcISR_c5v0
and create a new project named adcISR.uvprojx
.adcISR.c
file (the main function) and enter the source code that is shown next. Remember to include the boilerplate code (hidden by the editor folds):/*-------------------------------------------------- * Recipe: adcISR_c5v0 * Name: adcISR.c * Purpose: A/D Conversion Demo for MCBSTM32F400 * using IRQ *-------------------------------------------------- * Modification History * 16.04.14 created * 22.12.15 updated uVision5.17 + DFP2.6.0 * * Dr Mark Fisher, UEA, Norwich *--------------------------------------------------*/ #include ""stm32f4xx_hal.h"" #include ""Board_LED.h"" #include ""Custom_ADC.h"" #define wait_delay HAL_Delay /* Globals */ uint32_t adcValue; #ifdef __RTX ______________________________________________________ /* Function Prototypes */ void SystemClock_Config(void); /** * System Clock Configuration */ void SystemClock_Config(void) { ______________________________________________________
void ADC_IRQHandler (void) { ADC3->SR &= ~2; /* Clear EOC interrupt flag */ adcValue = (ADC3->DR); /* Get converted value */ ADC3->CR2 |= (1 << 30); /* Start next conversion */ }
main ()
function:int main (void) { HAL_Init ( ); SystemClock_Config ( ); LED_Initialize (); /* LED Initialization */ ADC_Initialize_and_Set_IRQ ();/* ADC Special Init */ while (1) { /* output 8-bit adcValue */ LED_SetOut (adcValue >> 4); /* to LEDs */ wait_delay ( 100 ); /* wait */ } }
Custom_ADC.c
file and enter code to set up the ADC:#include ""stm32f4xx_hal.h"" /* STM32F4xx Definitions */ #include ""Custom_ADC.h"" /*-------------------------------------------------- * ADC_Initialize_and_Set_IRQ: Initialize Analog to * Digital Converter and Enable IRQ *--------------------------------------------------*/ void ADC_Initialize_and_Set_IRQ (void) { /* Setup potentiometer pin PF9 (ADC3_7) and ADC3 */ RCC->APB2ENR |= (1UL << 10); /* En. ADC3 clk */ RCC->AHB1ENR |= (1UL << 5); /* En. GPIOF clk */ GPIOF->MODER |= (3UL << 2*9);/* PF9 is Analog mde */ ADC3->SQR1 = 0; ADC3->SQR2 = 0; ADC3->SQR3 = (7UL << 0); /* SQ1 = channel 7 */ ADC3->SMPR1 = 0; /* Channel 7 smple */ ADC3->SMPR2 = (7UL << 18); /* time = 480 cyc. */ ADC3->CR1 = (1UL << 8); /* Scan mode on */ ADC3->CR2 &= ~2; /* single conv. mode */ ADC3->CR1 |= ( 1UL << 5); /* En. EOC IRQ */ ADC3->CR2 |= ( 1UL << 0); /* ADC enable */ NVIC_EnableIRQ( ADC_IRQn ); /* En. IRQ */ ADC3->CR2 |= (1 << 30); /* Start 1st conversion */ }
adcISR.c
and Custom_ADC.c
files to the project.ADC_Initialize
_and_Set_IRQ ()
in the Custom_ADC.h
file.The STM32F407xx features 3 × 12-bit successive approximation ADCs, each sharing up to 16 external channels and performing conversions in single-shot or scan mode. A simplified schematic showing the architecture of each converter is presented next (please note that a more detailed diagram is included in STM's RM0090 Reference manual at http://www.st.com).
The 16 multiplexed input channels are organized in two groups comprising regular and injected channels. A subset of GPIO port pins can be connected to the ADC multiplexer by configuring the pin as a high-impedance analog input. The pin/input channel mapping is device-dependent. Details for the STM32F407IG device used by the ARM MCBSTM32F400 evaluation board can be found in the STM32F405xx and STM32F407xx Datasheet (http://www.st.com), and a simplified form is given in the following table. The ADC can be configured to carry out a sequence of up to 16 conversions on each group, each triggered separately by either an external-or-timed start signal.
ADC1 Input Channel |
GPIO Port |
ADC2 Input Channel |
GPIO Port |
ADC3 Input Channel |
GPIO Port |
---|---|---|---|---|---|
IN_0 |
PA0 |
IN_0 |
PA0 |
IN_0 |
PA0 |
IN_1 |
PA1 |
IN_1 |
PA1 |
IN_1 |
PA1 |
IN_2 |
PA2 |
IN_2 |
PA2 |
IN_2 |
PA2 |
IN_3 |
PA3 |
IN_3 |
PA3 |
IN_3 |
PA3 |
IN_4 |
PA4 |
IN_4 |
PA4 |
IN_4 |
PF6 |
IN_5 |
PA5 |
IN_5 |
PA5 |
IN_5 |
PF7 |
IN_6 |
PA6 |
IN_6 |
PA6 |
IN_6 |
PF8 |
IN_7 |
PA7 |
IN_7 |
PA7 |
IN_7 |
PF9 |
IN_8 |
PB0 |
IN_8 |
PB0 |
IN_8 |
PF10 |
IN_9 |
PB1 |
IN_9 |
PB1 |
IN_9 |
PF3 |
IN_10 |
PC0 |
IN_10 |
PC0 |
IN_10 |
PC0 |
IN_11 |
PC1 |
IN_11 |
PC1 |
IN_11 |
PC1 |
IN_12 |
PC2 |
IN_12 |
PC2 |
IN_12 |
PC2 |
IN_13 |
PC3 |
IN_13 |
PC3 |
IN_13 |
PC3 |
IN_14 |
PC4 |
IN_14 |
PC4 |
IN_14 |
PF4 |
IN_15 |
PC5 |
IN_15 |
PC5 |
IN_15 |
PF5 |
The GPIO ports used by the ADC must be configured as analog inputs by writing appropriate values to MODERy[1:0] bits of the Mode Register that is shown as follows:
31 |
30 |
29 |
28 |
27 |
26 |
25 |
24 |
MODER15[1:0] |
MODER14[1:0] |
MODER13[1:0] |
MODER12[1:0] | ||||
rw |
rw |
rw |
rw |
rw |
rw |
rw |
rw |
23 |
22 |
21 |
20 |
19 |
18 |
17 |
16 |
MODER11[1:0] |
MODER10[1:0] |
MODER09[1:0] |
MODER08[1:0] | ||||
rw |
rw |
rw |
rw |
rw |
rw |
rw |
rw |
15 |
14 |
13 |
12 |
11 |
10 |
09 |
08 |
MODER07[1:0] |
MODER06[1:0] |
MODER05[1:0] |
MODER04[1:0] | ||||
rw |
rw |
rw |
rw |
rw |
rw |
rw |
rw |
07 |
06 |
05 |
04 |
03 |
02 |
01 |
00 |
MODER03[1:0] |
MODE02[1:0] |
MODER01[1:0] |
MODER00[1:0] | ||||
rw |
rw |
rw |
rw |
rw |
rw |
rw |
rw |
The Mode Register bits are defined as follows:
MODERy[1:0] |
I/O Mode |
---|---|
00 : |
Input |
01 : |
General Purpose output |
10 : |
Alternate Function |
11 : |
Analog Input |
The ADC is configured by an initialization function named ADC_Initialize_and_Set_IRQ()
that has been written specially for this recipe. The following description should be read with reference to STM''s RM0090 Reference manual (http://www.st.com).
The thumbwheel labelled
ADC1 on the evaluation board provides a variable voltage input connected to GPIO port F pin 9 (ADC3 channel 7). To sample this voltage, we first configure GPIOF
pin 9 as an analog input by writing to the port mode register (GPIOF_MODER
). Statements in ADC_Initialize_and_Set_IRQ()
are explained as follows:
GPIOF->MODER |= (3UL << 2*9);
ADC3
and GPIOF
:RCC->APB2ENR |= (1UL << 10); RCC->AHB1ENR |= (1UL << 5);
ADC_SQR3
). As PF9 maps to ADC3 channel 7, we write 7
to this register and 0
to ADC_SQR1
and ADC_SQR2
:ADC3->SQR1 = 0; ADC3->SQR2 = 0; ADC3->SQR3 = (7UL << 0);
SMPR1
and SMPR2
). In this case, as the input voltage is derived from a potentiometer, the sample frequency can be quite low, and so, a long Sample/Hold time of 480 cycles can be set:ADC3->SMPR1 = 0; ADC3->SMPR2 = (7UL << 18);
8
of Control Register 1:ADC3->CR1 = (1UL << 8);
ADC3->CR2 &= ~2; ADC3->CR1 |= ( 1UL << 5); ADC3->CR2 |= ( 1UL << 0);
SWSTART
(bit-30), as follows:NVIC_EnableIRQ( ADC_IRQn ); ADC3->CR2 |= (1 << 30);
The ADC_IRQHandler ()
interrupt handler needs to clear the interrupt, read the ADC data, and start another conversion cycle. The super-loop in the main function calls the LED_SetOut ()
function to display the most significant 8-bits of the ADC output on the LEDs.
18.223.196.211