STM32 ADC detailed explanation

table of Contents

01. Introduction to ADC

02, STM32 ADC peripherals

03, STM32ADC block diagram explanation

04. Trigger source

05, conversion cycle

06, data register

07, interrupt

08, voltage conversion

09. Circuit diagram design

10. Code design


01. Introduction to ADC

ADC is the abbreviation of Analog-to-DigitalConverter. Refers to analog/digital converter or analog/digital converter. Refers to a device that converts a continuous variable analog signal into a discrete digital signal. A typical analog-to-digital converter converts an analog signal into a digital signal representing a certain proportional voltage value.

From the figure below in the STM32F207 data sheet, you can see that STM32F207VC has 3 ADC controllers with a precision of 12bit and 16 external channels. The 144-pin STM32F207Zx and the 176-pin STM32F207Ix have 8 more channels because of the PF pin There are 24 external channels. The A/D conversion of each channel can be executed in a single, continuous, scan or intermittent manner, and the ADC conversion result can be left-aligned or right-aligned and stored in a 16-bit data register.

02, STM32 ADC peripherals

As mentioned above, STM32F207 has three 12-bit ADC controllers, which will be explained below with ADC3 channel 10.

First of all, we confirm the address bus where the ADC peripheral is located. From the figure below in the STM32F207 data manual, we can see that the ADC belongs to the APB2 bus, and the APB2 clock frequency is 60MHz. For specific STM32, if the 60MHz APB2 obtained by an external 25M crystal oscillator, please see " STM32F207 Clock System Analysis ".

Corresponding to GPIO, we see from the STM32F207 data sheet that we can use PC0 as channel 10 of ADC3.

What needs to be explained here is that when using other peripherals in the previous article, such as " STM32PWM output ", when looking for the corresponding pin, we all look for the Alternatefunctionmapping table in the STM32F207 data sheet. This is because the ADC corresponds to the pin. The additional functions are used, and the corresponding pins of PWM use Alternatefunctions.

The difference is:

Additionalfunctions: additional, auxiliary functions, pins are connected to other modules for use, and can be configured directly when used. For example, the ADC uses an input channel and is configured as an analog input.

Alternate functions: Alternate functions , that is, the IO port is used for functions other than ordinary input and output, such as serial port input and output. The multiplexing mode needs to be configured when using it.

 

In the previous article " STM32GPIO Detailed Explanation ", there are the following introductions.

The STM32 standard peripheral library has the following code

typedef enum
{   
    GPIO_Mode_IN   = 0x00, /*!< GPIO Input Mode */  
    GPIO_Mode_OUT  = 0x01, /*!< GPIO Output Mode */  
    GPIO_Mode_AF   = 0x02, /*!< GPIO Alternate function Mode */  
    GPIO_Mode_AN   = 0x03  /*!< GPIO Analog Mode */
}GPIOMode_TypeDef;

Among them, GPIO_Mode_AF corresponds to Alternate functions: multiplexing functions, and GPIO_Mode_AN corresponds to Additional functions: additional, auxiliary functions.

 

03, STM32ADC block diagram explanation

The following figure is a block diagram of STM32ADC, we will divide it into 7 parts to explain.

1. Input voltage range

The voltage range that the ADC can measure is VREF-≤ VIN ≤ VREF+. Connect VSSA and VREF- to ground, and connect VREF+ and VDDA to 3V3 to get the ADC's input voltage range: 0~3.3V.

2. Input channel

The ADC signal enters the microcontroller through the input channel, and the microcontroller converts the analog signal into a digital signal through the ADC module. The part marked ② in the above figure shows the 16 external channels and the connected GPIO. The corresponding relationship is as explained above. You need to find it in the STM32F20xpin and ball definitions table in the STM32F207 data manual. In fact, STM32 also has internal channels. Channel 16 of ADC1 is connected to the temperature sensor inside the chip, and Vrefint is connected to channel 17. The analog channels 16 and 17 of ADC2 are connected to the internal VSS.

3. Conversion channel

The 16 external channels are divided into regular channels and injection channels during conversion. There are up to 16 regular channels and 4 injection channels at most (injection channels seem to be not used much). The two channels are briefly introduced below:

Regular channel

As the name implies, the regular channel is the most common channel and the most commonly used channel, and the usual ADC conversion is implemented by the regular channel. The regular channel and its conversion sequence are selected in the ADC_SQRx register, and the total number of regular group conversions should be written into L[3:0] of the ADC_SQR1 register.

Injection channel

The injection channel is relative to the regular channel. The injection channel can be forcibly inserted into the conversion when the regular channel is converted, which is equivalent to an "interrupt channel". When there is an injection channel that needs to be converted, the conversion of the regular channel will stop, and the conversion of the injection channel will be executed first. When the conversion of the injection channel is completed, it will return to the previous regular channel for conversion. Up to 4 channels, the injection group and its conversion sequence are selected in the ADC_JSQR register. The total number of conversions in the injection group should be written into L[1:0] of the ADC_JSQR register.

An ADC controller has multiple channels, which involves the use of multiple channels for conversion, which involves a sequence of issues. After all, the regular conversion channel has only one data register. The order of using multiple channels is divided into two cases: the conversion order of regular channels and the conversion order of injection channels.

Regular channel conversion sequence

The conversion sequence in the regular channel is controlled by three registers: SQR1, SQR2, SQR3, which are all 32-bit registers. The SQR register controls the number of conversion channels and the conversion sequence. As long as the corresponding channel is written in the corresponding register bit SQx, this channel is the xth conversion. The realization of the conversion sequence on the register can be understood through the SQR1 register.

Injection channel conversion sequence

Like the control of the regular channel conversion sequence, the conversion of the injection channel is also controlled by the injection register, except that there is only one JSQR register to control. The control relationship is as follows:

It should be noted that only when JL=4, the conversion sequence of the injection channel will be executed in the order of JSQ1, JSQ2, JSQ3, and JSQ4. When JL<4, the conversion sequence of the injection channel is exactly the opposite, that is, the execution sequence is: JSQ4, JSQ3, JSQ2, JSQ1.

Function to configure the conversion order

void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel,uint8_t Rank, uint8_t ADC_SampleTime)

04. Trigger source

The input, channel, and conversion sequence of ADC conversion have been explained, but how is ADC conversion triggered? Just like the communication protocol, a start signal must be specified to transmit information, and the ADC also needs a trigger signal to perform analog-to-digital conversion.

One is to trigger by directly configuring the register. By configuring the ADON bit of the control register CR2, the conversion starts when 1 is written, and the conversion is stopped when 0 is written. As long as the library function is called during the running of the program, the conversion can be performed by setting the ADON bit of the CR2 register to 1, which is easier to understand.

In addition, the conversion can also be triggered by an internal timer or external IO, that is to say, the internal clock can be used to make the ADC perform periodic conversion, and the external IO can also be used to make the ADC convert when needed. The specific trigger is determined by the control register CR2.

 

05, conversion cycle

The sampling time of each channel can be set independently

The ADC will sample the input voltage in several ADCCLK cycles, ADC_SMPR1 and ADC_SMPR2 can be used

The SMP[2:0] bits in the register modify the number of cycles. Each channel can be sampled with a different sampling time.

The calculation formula for the total conversion time is as follows:

    Tconv = sampling time + 12 cycles

Example:

    When ADCCLK = 30 MHz and sampling time = 3 cycles:

    Tconv = 3+12=15 cycles=0.5us (when APB2 is 60MHz)

The minimum sampling time is 0.42us (ADC clock=36MHz, and the sampling period is 3 cycles).

 

06, data register

The data after the conversion is stored in the data register, but the storage of the data is also divided into regular channel conversion data and injection channel conversion data.

Regular data register

The regular data register is responsible for storing the data converted by the regular channel, which is stored through the 32-bit register ADC_DR.

Inject data register

There are 4 data registers for injection channel conversion. Since there are at most 4 injection channels, the data for injection channel conversion has a fixed storage location, which will not cause data coverage problems like regular registers. ADC_JDRx is 32 bits, the lower 16 bits are valid, and the upper 16 bits are reserved. The data is also divided into left-justified and right-justified. The specific method of storage is set by the 11-bit ALIGN of ADC_CR2.

07, interrupt

4 kinds of interrupts can be generated

DMA overflow interrupt

When the DMA is configured and the DMA overflows, an interrupt is generated

②The regular channel conversion is completed and interrupted

After the rule channel data conversion is completed, an interrupt can be generated, and the value of the rule data register can be read in the interrupt function. This is also a way to read data in a single channel.

③The injection channel conversion is completed and interrupted

After the injection channel data conversion is completed, an interrupt can be generated, and the value of the injected data register can also be read in the interrupt to achieve the effect of reading data.

④Simulate watchdog events

When the input analog quantity (voltage) is no longer within the threshold range, a watchdog event will be generated, which is used to monitor whether the input analog quantity is normal.

08, voltage conversion

The converted data is a 12-bit binary number, and we need to digitally represent the analog quantity (voltage) represented by this binary number. For example, the measured voltage range is 0~3.3V, and the converted binary number is x, because the 12-bit ADC divides the voltage range (that is, 3.3) into 4096 (2^12) parts during conversion, so the converted The calculation method of the true voltage represented by the binary number x is:

y = 3.3 * x / 4096

 

09. Circuit diagram design

The circuit diagram is very simple, you can input different voltages on the ADC pins, or you can directly and conveniently use the sliding rheostat to achieve different voltage changes.

 

10. Code design

ADC peripheral configuration structure

typedef struct
{
  uint32_t ADC_Resolution;                /*!< Configures the ADC resolution dual mode. 
                                               This parameter can be a value of @ref ADC_resolution */                                   
  FunctionalState ADC_ScanConvMode;       /*!< Specifies whether the conversion 
                                               is performed in Scan (multichannels) 
                                               or Single (one channel) mode.
                                               This parameter can be set to ENABLE or DISABLE */ 
  FunctionalState ADC_ContinuousConvMode; /*!< Specifies whether the conversion 
                                               is performed in Continuous or Single mode.
                                               This parameter can be set to ENABLE or DISABLE. */
  uint32_t ADC_ExternalTrigConvEdge;      /*!< Select the external trigger edge and
                                               enable the trigger of a regular group. 
                                               This parameter can be a value of 
                                               @ref ADC_external_trigger_edge_for_regular_channels_conversion */
  uint32_t ADC_ExternalTrigConv;          /*!< Select the external event used to trigger 
                                               the start of conversion of a regular group.
                                               This parameter can be a value of 
                                               @ref ADC_extrenal_trigger_sources_for_regular_channels_conversion */
  uint32_t ADC_DataAlign;                 /*!< Specifies whether the ADC data  alignment
                                               is left or right. This parameter can be 
                                               a value of @ref ADC_data_align */
  uint8_t  ADC_NbrOfConversion;           /*!< Specifies the number of ADC conversions
                                               that will be done using the sequencer for
                                               regular channel group.
                                               This parameter must range from 1 to 16. */
}ADC_InitTypeDef;

ADC_Resolution: ADC working mode selection, ADC resolution

ADC_ScanConvMode: ADC scan (multi-channel) or single (single channel) mode selection

ADC_ContinuousConvMode: ADC single conversion or continuous conversion selection

ADC_ExternalTrigConvEdge: ADC external trigger polarity configuration

ADC_ExternalTrigConv: ADC conversion trigger signal selection

ADC_DataAlign: ADC data register alignment format

ADC_NbrOfConversion: ADC conversion channel number

 

typedef struct
{
    uint32_t ADC_Mode;//多重ADC模式选择
    uint32_t ADC_Prescaler;  //ADC预分频                             
    uint32_t ADC_DMAAccessMode;   //DMA访问模式       
    uint32_t ADC_TwoSamplingDelay; //2个采样阶段之间的延迟      
}ADC_CommonInitTypeDef;

ADC_CommonInitTypeDef is used to configure the relevant parameters of the ADC_CCR register

ADC peripheral and DMA configuration code

/**
  * @brief  ADC3 channel10 with DMA configuration
  * @param  None
  * @retval None
  */
void ADC3_CH10_DMA_Config(void)
{
  ADC_InitTypeDef       ADC_InitStructure;
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
  DMA_InitTypeDef       DMA_InitStructure;
  GPIO_InitTypeDef      GPIO_InitStructure;

  /* Enable ADC3, DMA2 and GPIO clocks ****************************************/
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);

  /* DMA2 Stream0 channel2 configuration **************************************/
  DMA_InitStructure.DMA_Channel = DMA_Channel_2;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_BufferSize = 1;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA2_Stream0, &DMA_InitStructure);
  DMA_Cmd(DMA2_Stream0, ENABLE);

  /* Configure ADC3 Channel10 pin as analog input ******************************/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* ADC Common Init **********************************************************/
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
  ADC_CommonInit(&ADC_CommonInitStructure);

  /* ADC3 Init ****************************************************************/
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfConversion = 1;
  ADC_Init(ADC3, &ADC_InitStructure);

  /* ADC3 regular channel7 configuration *************************************/
  ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);

 /* Enable DMA request after last transfer (Single-ADC mode) */
  ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);

  /* Enable ADC3 DMA */
  ADC_DMACmd(ADC3, ENABLE);

  /* Enable ADC3 */
  ADC_Cmd(ADC3, ENABLE);
}

Code download verification test

 

Hardware and software open source address:

https://github.com/strongercjd/STM32F207VCT6

 

Click to view the album where this article is located, STM32F207 tutorial

 

Pay attention to the official account, and receive article updates as soon as possible . The comment area cannot be seen in time, you can go to the official account to communicate if you need to communicate

Guess you like

Origin blog.csdn.net/Firefly_cjd/article/details/108614415