Stm32 ADC Analog-to-digital conversion ADC multi-channel ADC DMA

Source: Internet
Author: User
Tags volatile



Change the ad conversion value and voltage value by adjusting the potentiometer



stm32f1 ADC Configuration steps



1. Enable Gpio clock and ADC clock
2. Configure PIN mode for analog input
3. Configure the ADC's divide factor
4. Initialize the ADC parameters, Adc_inittypedef
5. Enable ADC
6. Perform ADC calibration
7. Set the ADC software to start
8. Read ADC conversion values
9. Set ADC rules, sampling time, etc.
10. Convert software to enable ADC
11. Read ADC Conversion results



Example


u16 ADC_value (u8 time)
{
    u8 i = 0;
    u16 value;

    for (i = 0; i <time; i ++)
    {
        ADC_SoftwareStartConvCmd (ADC1, ENABLE); // Enable ADC software conversion

        while (ADC_GetFlagStatus (ADC1, ADC_FLAG_EOC)! = SET);

        value + = ADC_GetConversionValue (ADC1); // Read ADC conversion result
    }

    return value / time;
}

typedef struct
{
    uint32_t ADC_Mode; // Dual mode selection
    FunctionalState ADC_ScanConvMode; // Scan mode
    FunctionalState ADC_ContinuousConvMode; // Continuous conversion
    uint32_t ADC_ExternalTrigConv; // External trigger conversion mode for injection channel
    uint32_t ADC_DataAlign; // Data alignment
    uint8_t ADC_NbrOfChannel; // Regular channel sequence length
} ADC_InitTypeDef;

void ADC_init ()
{
    GPIO_InitTypeDef gpio =
    {
        GPIO_Pin_1,
        GPIO_Speed_50MHz,
        GPIO_Mode_AIN // Analog input
    };

    ADC_InitTypeDef adc =
    {
        ADC_Mode_Independent, // Independent mode
        DISABLE, // Turn off scan mode
        DISABLE, // Single conversion mode
        ADC_ExternalTrigConv_None, // start conversion without external events
        ADC_DataAlign_Right, // Right alignment
        1, // Number of channels 1
    };

    RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); // Enable GPIO clock and ADC clock

    GPIO_Init (GPIOA, & gpio); // Configure pin mode

    RCC_ADCCLKConfig (RCC_PCLK2_Div6); // Configure ADC divide factor 72/6 = 12 (usually)

    ADC_RegularChannelConfig (ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5); // Set ADC rule, sampling period

    ADC_Init (ADC1, & adc); // Initialize ADC parameters

    ADC_Cmd (ADC1, ENABLE); // Enable ADC

    ADC_ResetCalibration (ADC1); // Perform ADC reset calibration
    while (ADC_GetResetCalibrationStatus (ADC1) == SET); // wait for calibration to complete

    ADC_StartCalibration (ADC1); // Perform ADC calibration
    while (ADC_GetCalibrationStatus (ADC1) == SET);

    ADC_SoftwareStartConvCmd (ADC1, ENABLE); // ADC software starts
}

int main (void)
{
    ADC_init ();

    while (1)
    {
        adc = ADC_value (15); // 15 times average
        printf ("ADC_value is% d. \ n", adc);
        printf ("vol is% .3fV. \ n", adc * (3.3 / 4096)); // Voltage value
        delay_ms (500);
        led1 = ~ led1;
    }
}


Voltage Calculation


vol = ADC * (3.3/4096);


The ADC has a reference voltage of vref+ 3.3V. ADC is 12-bit conversion accuracy, 2^12 is 4096



DMA Mode
Adc_dmacmd turn on DMA, after ADC initialization
Adc_regularchannelconfig Channel Configuration after initialization of the ADC
Dma_memoryinc to be set to dma_memoryinc_enable, memory address incremented



Dma_buffersize size is the size of the DMA_MEMORYBASEADDR memory that is defined. Based on dma_memorydatasize memory data width, Halfword is 16bit


#define CHANNEL_NUM 4

volatile u16 AD_Bufer [4];
volatile u8 adc1_ok;

// Multi-channel configuration. 4 inputs
void ADC_init ()
{
    ...

    ADC_InitTypeDef adc =
    {
        ADC_Mode_Independent, // Independent mode
        ENABLE, // Enable scan mode
        ENABLE, // Enable continuous conversion mode
        ADC_ExternalTrigConv_None, // start conversion without external events
        ADC_DataAlign_Right, // Right alignment
        CHANNEL_NUM, // Number of channels 4
    };

    ADC_Init (ADC1, & adc);

    ADC_RegularChannelConfig (ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);
    ADC_RegularChannelConfig (ADC1, ADC_Channel_2, 2, ADC_SampleTime_55Cycles5);
    ADC_RegularChannelConfig (ADC1, ADC_Channel_3, 3, ADC_SampleTime_55Cycles5);
    ADC_RegularChannelConfig (ADC1, ADC_Channel_4, 4, ADC_SampleTime_55Cycles5);

    DMA_adc_init (ADC1, (u32) AD_Bufer, CHANNEL_NUM);

    ...
}

void DMA_adc_init (ADC_TypeDef * ADCx, u32 mem_addr, u32 size)
{
   DMA_InitTypeDef DMA_InitStructure;
   NVIC_InitTypeDef NVIC_InitStructure;

   RCC_AHBPeriphClockCmd (RCC_AHBPeriph_DMA1, ENABLE); // Enable DMA controller clock

   NVIC_PriorityGroupConfig (NVIC_PriorityGroup_1);
   NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init (& NVIC_InitStructure);

   DMA_InitStructure.DMA_PeripheralBaseAddr = (u32) & ADCx-> DR; // peripheral address
   DMA_InitStructure.DMA_MemoryBaseAddr = mem_addr; // Memory address
   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
   DMA_InitStructure.DMA_BufferSize = size; // 4 buffer sizes
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // Circular mode
   DMA_InitStructure.DMA_Priority = DMA_Priority_High;
   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
   DMA_Init (DMA1_Channel1, & DMA_InitStructure);

   DMA_ITConfig (DMA1_Channel1, DMA1_IT_TC1, ENABLE); // Enable interrupt

   DMA_Cmd (DMA1_Channel1, ENABLE);

   ADC_DMACmd (ADCx, ENABLE); // Enable ADC1 DMA acquisition
}

void DMA1_Channel1_IRQHandler (void)
{
    if (DMA_GetITStatus (DMA1_IT_TC1)! = RESET)
    {
        DMA_ClearITPendingBit (DMA1_IT_TC1);
        adc1_ok = 1;
    }
}

int main (void)
{
    ADC_init ();

    while (1)
    {
        if (adc1_ok == 1)
        {
            v0 = AD_Bufer [0];
            v1 = AD_Bufer [1];
            v2 = AD_Bufer [2];
            v3 = AD_Bufer [3];

            printf ("v0 is% .3fV. \ n", v0 * (3.3 / 4096)); // Voltage value
            printf ("v1 is% .3fV. \ n", v1 * (3.3 / 4096));
            printf ("v2 is% .3fV. \ n", v2 * (3.3 / 4096));
            printf ("v3 is% .3fV. \ n", v3 * (3.3 / 4096));

            led1 = ~ led1;
            adc1_ok = 0;
        }

        delay_ms (500);
    }
} 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.