4_通过DMA与ADC对PMSM相电流采样

       代码是直接问GPT生成的,和网上的再简单核对下。感觉“需求”越详细,GPT生成的可能会更好。

       1、stm32f405RGT6 标准外设库 adc1 A6 A7 C4采集 dma2 通道0 配置例子

#include "stm32f4xx.h"  


#define ADC1_DR_ADDRESS ((uint32_t)0x4001204C) 
__IO uint16_t ADCConvertedValues[3];


void RCC_Configuration(void);
void GPIO_Configuration(void);
void ADC_Configuration(void);
void DMA_Configuration(void);


int main(void)
{
    RCC_Configuration();
    GPIO_Configuration();
    DMA_Configuration();
    ADC_Configuration();


    while (1){
        // 在这里添加你的代码
    }
}


void RCC_Configuration(void)
{
    // 使能 ADC1, GPIOA, GPIOC 和 DMA2 时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
}
      
void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    // 配置 GPIOA 引脚 A6 和 A7 为模拟输入模式
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;    
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    // 配置 GPIOC 引脚 C4 为模拟输入模式
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
}


void ADC_Configuration(void)
{
    ADC_InitTypeDef ADC_InitStructure;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    ADC_DeInit();   


    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);


    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    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 = 3;


    ADC_Init(ADC1, &ADC_InitStructure);      


    // 配置 ADC 通道
    ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_3Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_3Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 3, ADC_SampleTime_3Cycles);
    // 使能 DMA 请求
    ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
    // 使能 ADC DMA
    ADC_DMACmd(ADC1, ENABLE);
    // 使能 ADC1
    ADC_Cmd(ADC1, ENABLE);


    // 开始 ADC 转换
    ADC_SoftwareStartConv(ADC1);
}


          


void DMA_Configuration(void)
{
    DMA_InitTypeDef DMA_InitStructure;


    DMA_DeInit(DMA2_Stream0);
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS;
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValues;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_BufferSize = 3;    
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    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);
    // 使能 DMA2 流0
    DMA_Cmd(DMA2_Stream0, ENABLE);
}

以上代码完成了以下几个任务:

1.使能 GPIOA、GPIOC、ADC1 和 DMA2 的时钟。

2.配置 GPIOA 的 A6 和 A7 引脚、GPIOC 的 C4 引脚为模拟输入模式。

3.配置 ADC1 为独立模式,设置采样时间,并使能 DMA。    

4.配置 DMA2 通道0 以循环模式传输 ADC 转换数据。

5.使能 ADC1 并开始转换。

这个例子使用了标准外设库的函数和定义,如果你在实际项目中使用 HAL 库,配置方法会有所不同。希望这段代码能帮助你理解如何配置 ADC 和 DMA 以采集多个通道的数据。

2、stm32f4 ADC DMA得到的数据如何转换

在 STM32F4 微控制器上,通过 ADC 和 DMA 可以实现高效的数据采集。使用 DMA 从 ADC 获取的数据通常存储在一个数组中,然后需要将这些原始数据进行处理或转换,以便在应用中使用。

以下是一个使用 ADC 和 DMA 获取数据并将其转换的示例。假设我们要读取多个通道的 ADC 值,并将这些值转换为电压或其他有意义的物理量。

示例代码

1.配置时钟。

2.配置 GPIO。

3.配置 ADC 和 DMA。

4.实现数据转换。

#include "stm32f4xx.h"
          
// 定义一些常量
#define ADC_BUFFER_SIZE 3  // 读取 3 个通道的 ADC 数据
#define ADC_MAX_VALUE 4095 // 12 位 ADC 最大值
#define VREF 3.3f          // 参考电压         


// DMA 缓冲区
uint16_t ADC_Buffer[ADC_BUFFER_SIZE];
// 函数声明
void RCC_Configuration(void);
void GPIO_Configuration(void);
void ADC_Configuration(void);
void DMA_Configuration(void);
void ADC_DMA_Init(void);
void Process_ADC_Data(void);


int main(void)
{
    // 配置系统时钟
    RCC_Configuration();
    // 初始化 GPIO
    GPIO_Configuration();
    // 初始化 ADC 和 DMA
    ADC_DMA_Init();    
    while (1) {
        // 处理 ADC 数据
        Process_ADC_Data();
        // 其他操作
    }
}


void RCC_Configuration(void)
{
    // 使能 GPIOA 和 ADC1 时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
}


void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    // 配置 PA0, PA1, PA2 为模拟输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}


void ADC_Configuration(void)
{
    ADC_InitTypeDef ADC_InitStructure;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    // 配置 ADC 公共设置
    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);
    // 配置 ADC1    
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    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 = ADC_BUFFER_SIZE;
    ADC_Init(ADC1, &ADC_InitStructure); 


    // 配置 ADC 通道
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_144Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_144Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_144Cycles);


    // 启动 ADC
    ADC_Cmd(ADC1, ENABLE);
}    


void DMA_Configuration(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    // 配置 DMA2 Stream0
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC_Buffer[0];
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_BufferSize = ADC_BUFFER_SIZE;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    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);
    // 启动 DMA2 Stream0
    DMA_Cmd(DMA2_Stream0, ENABLE);
}


          


void ADC_DMA_Init(void)
{
    // 配置 ADC
    ADC_Configuration();
    // 配置 DMA
    DMA_Configuration();
    // 使能 ADC DMA 请求
    ADC_DMACmd(ADC1, ENABLE);
    // 开始 ADC 转换
    ADC_SoftwareStartConv(ADC1);
}


void Process_ADC_Data(void)
{
    float voltages[ADC_BUFFER_SIZE];
    // 将 ADC 采样值转换为电压值


    for (int i = 0; i < ADC_BUFFER_SIZE; i++) {
        voltages[i] = ((float)ADC_Buffer[i] / ADC_MAX_VALUE) * VREF;
    }
    // 在这里可以进一步处理电压值,例如显示或计算
}

说明

1.系统时钟配置: RCC_Configuration 函数使能 GPIO、ADC 和 DMA 时钟。

2.GPIO 配置: GPIO_Configuration 函数将 PA0、PA1 和 PA2 配置为模拟输入。

3.ADC 配置: ADC_Configuration 函数配置 ADC 通道、分辨率和其他参数。

4.DMA 配置: DMA_Configuration 函数配置 DMA 用于从 ADC 获取数据。

5.ADC 和 DMA 初始化: ADC_DMA_Init 函数初始化 ADC 和 DMA 并开始 ADC 转换。

6.数据处理: Process_ADC_Data 函数将 DMA 获取的 ADC 数据转换为电压值。    

注意事项

·该示例代码假设 ADC 的参考电压为 3.3V,并使用 12 位分辨率。

·ADC_BUFFER_SIZE 定义了要读取的 ADC 通道数量。根据实际应用需要调整该值。

·DMA 采用循环模式,以便连续获取 ADC 数据。

·数据处理部分可以根据应用需求进行扩展,例如计算平均值、滤波等。

  改动很小,几乎可以直接用的。效果如下:

6aeabbc3442883998578718913fb8b6f.png    

欢迎关注:

8616b07e5d8dc84ad525ed860c42db3e.png

距离电机转动又进了一步~

之前其他的积累:

3_stm32_pwm呼吸灯

2_stm32定时中断点灯

1_stm32点亮led

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值