STM32F4单片机上实现双路ADC的同步采样(超详细,手把手教学)

在嵌入式开发中,STM32F4系列单片机由于其性能优越、资源丰富,广泛应用于各类工业和消费电子项目中。在许多应用场景中,ADC(模数转换器)功能至关重要,尤其是需要对多路信号进行采样时。本文将介绍如何在STM32F4单片机上实现双路ADC的同步采样,并详细解释代码的关键点。

前言

STM32F4系列微控制器具备多个ADC模块,每个模块支持多个通道的模拟输入。本例子中,我们将使用STM32F407微控制器的两个ADC模块(ADC1和ADC2),并通过DMA实现双路ADC的同步采样。这样可以有效减少CPU负载,并且确保ADC采样的实时性。

硬件和软件环境

硬件:STM32F407开发板,两个模拟输入信号源(如电位器或传感器)
软件:Keil MDK或IAR等IDE,STM32固件库

系统架构

系统架构如下:

1、使用两个ADC模块(ADC1和ADC2)来进行双路模拟信号的采样。
2、通过DMA(Direct Memory Access)将采样结果传输到内存,减轻CPU负载。
3、ADC在循环模式下工作,不断进行采样和数据传输。

ADC采样基本原理

STM32F4的ADC具备以下特点:
1.分辨率最高为12位
2.支持多通道采样
3.支持DMA,极大提升数据传输效率
4.支持双ADC同步模式
在本项目中,我们使用双路ADC同步采样模式,并结合DMA实现数据自动传输。通过DMA,数据将直接存入内存,避免CPU占用,提升系统效率。

代码实现

  1. 配置系统时钟和外设时钟
    在STM32开发中,首先需要配置系统时钟和外设时钟,以确保ADC模块和DMA模块能够正确工作。可以通过以下代码来配置时钟:
void RCC_Configuration(void)
{
    /* 启用ADC1、ADC2和DMA时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);  // DMA2时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);  // ADC1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);  // ADC2时钟
}

  1. 配置GPIO引脚
    ADC的输入通常需要配置对应的GPIO引脚为模拟模式。以下是示例代码,假设我们使用的是PA0和PA1作为ADC的输入引脚:
void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    /* 启用GPIOA时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

    /* 配置PA0和PA1为模拟输入模式 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

  1. 配置DMA
    DMA用于自动将ADC采样结果传输到内存。以下代码配置了DMA,以支持从ADC1和ADC2传输数据到存储器中。
void DMA_Configuration(void)
{
    DMA_InitTypeDef DMA_InitStructure;

    /* 配置DMA2流0用于ADC1 */
    DMA_DeInit(DMA2_Stream0);
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&adcValues[0];
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_BufferSize = 2;
    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_Word;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_Init(DMA2_Stream0, &DMA_InitStructure);

    /* 启用DMA2流0 */
    DMA_Cmd(DMA2_Stream0, ENABLE);
}

  1. 配置ADC
    ADC模块配置包括通道选择、分辨率、采样时间等。以下示例展示了如何配置ADC1和ADC2。
void ADC_Configuration(void)
{
    ADC_InitTypeDef       ADC_InitStructure;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;

    /* 配置ADC通用配置 */
    ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult;
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    ADC_CommonInit(&ADC_CommonInitStructure);

    /* 配置ADC1 */
    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_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfConversion = 1;
    ADC_Init(ADC1, &ADC_InitStructure);

    /* 配置ADC1的通道0(PA0) */
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles);

    /* 配置ADC2 */
    ADC_Init(ADC2, &ADC_InitStructure);

    /* 配置ADC2的通道1(PA1) */
    ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 1, ADC_SampleTime_3Cycles);

    /* 启用ADC DMA请求 */
    ADC_DMACmd(ADC1, ENABLE);
    ADC_DMACmd(ADC2, ENABLE);

    /* 启用ADC */
    ADC_Cmd(ADC1, ENABLE);
    ADC_Cmd(ADC2, ENABLE);
}

  1. 启动ADC和DMA
    当配置完所有外设后,可以通过启动ADC和DMA进行采样:
void Start_ADC_DMA(void)
{
    /* 启动ADC1的DMA */
    ADC_SoftwareStartConv(ADC1);
}

  1. 主循环
    在主循环中,可以定期读取存储在内存中的ADC采样结果:
int main(void)
{
    RCC_Configuration();   // 时钟配置
    GPIO_Configuration();  // GPIO配置
    DMA_Configuration();   // DMA配置
    ADC_Configuration();   // ADC配置

    /* 启动ADC和DMA */
    Start_ADC_DMA();

    while (1)
    {
        // 此处可以读取 adcValues[] 数组中的数据
        uint32_t adc1_value = adcValues[0];
        uint32_t adc2_value = adcValues[1];

        // 处理采样数据
    }
}

代码解释

1、时钟配置:使用RCC_Configuration函数启用了ADC和DMA的时钟。
2、GPIO配置:将PA0和PA1配置为模拟输入模式,分别连接到ADC1的通道0和ADC2的通道1。
3、DMA配置:通过DMA_Configuration函数设置了DMA,以便将ADC采样结果传输到内存。
4、ADC配置:ADC_Configuration函数配置了ADC1和ADC2,并设置了同步模式。
5、数据采集:Start_ADC_DMA函数启动ADC和DMA的采样过程,主循环中通过访问adcValues[]来获取采样结果。

结论

本文详细介绍了如何使用STM32固件库开发双路ADC采样程序,并通过DMA实现数据的高效传输。在实际项目中,这种方式可以有效减轻CPU负担,适用于需要高效处理多路模拟信号的场景。通过STM32固件库的配置,我们能够更加精细地控制硬件资源,实现高效的嵌入式应用。

作者:一万个W

物联沃分享整理
物联沃-IOTWORD物联网 » STM32F4单片机上实现双路ADC的同步采样(超详细,手把手教学)

发表回复