STM32学习笔记,双ADC_DMA同步采集(CUBEMX+HAL+过采样)

双ADC同步采集可以节省一半时间
CUBEMX配置ADCADC1配置
ADC2配置
DMA
GPIO


void Read_adc( void )
{

//dma方式*****************************************
    uint16_t ad1[20],ad2[20];
    AdcDMA_flag = 0;
    HAL_ADCEx_MultiModeStart_DMA(&hadc1, ADC_Value, 18);//启动多通道,双ADC同步采集DMA模式,ADC1在低16位,ADC2在高16位

    while(AdcDMA_flag == 0)  //因为要配合DAC进行采集,这里用用单次阻塞式采集,
    {
        delay_us(1);
    }
    /*******************************************
    双ADC同步DMA采样,各采样18次,去除最高和最低
    保留16次采样,右移2位得到14Bit采样值
    ********************************************/

    for (i=0 ; i< 18; i++) {  //分离提取ADC中各通道值 ,取18个
        ad1[i] = ADC_Value[i];
        ad2[i] = ADC_Value[i]>>16;
//        printf("No.%d= %d, %d\r\n",i,ad1[i],ad2[i]);
    }
    uint32_t   total_ad1 = 0, ad1_max = 0, ad1_min = 4095;
    uint32_t   total_ad2 = 0, ad2_max = 0, ad2_min = 4095;

    for ( i = 0;  i < 18; i++)  //累加18次,去除最大和最小值,相当于累加16次
    {
        
        if (ad1_max < ad1[i]) 		 ad1_max = ad1[i];
        if (ad2_max < ad2[i])		 	 ad2_max = ad2[i];

        if (ad1[i] < ad1_min)      ad1_min = ad1[i];
        if (ad2[i] < ad2_min)      ad2_min = ad2[i];
        total_ad1 += ad1[i];
        total_ad2 += ad2[i];
//       printf("total_1=%d,total_2=%d\r\n",total_1,total_2);
    }

    total_ad1 = (total_ad1 - ad1_min - ad1_max) ;
    total_ad2 = (total_ad2 - ad2_min - ad2_max) ;
    //    printf("max= %d min= %d\r\n",ad1_max,ad1_min);
//       printf("total_16= %d, total_2=%d\r\n",total_1,total_2);

//计算过采样14b的值
//    AdcDMA_flag = 0;
    V_ADC14b= (total_ad1)>>2;
    I_ADC14b= (total_ad2)>>2;
}

ADC初始化后要先校准

    HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED); //校准ADC1
    HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED); //校准ADC2

在While(1)中读取ADC

    uint32_t  time = HAL_GetTick(); //同步时间
    while (1)
    {
        if(HAL_GetTick()-time >=1000)
        {
            time = HAL_GetTick(); //同步时间
            Read_adc();
            printf("V_ADC=%d,I_ADC=%d\r\n",V_ADC14b,I_ADC14b);
        }
        /* USER CODE END WHILE */
        /* USER CODE BEGIN 3 */
    }

电压/电流差分采样电路
差分采样
开始是使用STM32F303内部运放进行差分采样,结果发现读数跳动较大,无输入时也有底数,且OPAMP之间有串扰,改用外置运放后读数相对稳定,无输入时读数为0,实测ADC读数跳动在3~4个字,注意这里使用了14位过采样,不使用过采样的话读数会更稳定。
完整程序下载:
https://download.csdn.net/download/u013348132/12034532

STM32 HAL_ADC_Start_DMA 函数是用于在STM32微控制器上使用DMA(Direct Memory Access)进行高速数据转换的高级API。它通常应用于需要大量数据快速采集并传输到内存的情况,比如连续测量或者实时处理。 当使用这个函数时,你需要做以下几个步骤: 1. 首先,初始化ADC模块,包括配置通道、启动模式等。例如: ```c ADC_HandleTypeDef hadc1; hadc1.Instance = ADC1; // 指定ADC1外设 hadc1.Init.Channel = ADC_CHANNEL_0; // 设置要采集的通道 // 其他初始化设置... HAL_ADC_Init(&hadc1); ``` 2. 然后,配置DMA,使其能从ADC的特定寄存器读取数据: ```c DMA_HandleTypeDef hdma_adc1; hdma_adc1.Init.Channel = DMA_CHANNEL_1; // 根据实际使用的DMA通道 hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; hdma_adc1.Init.Mode = DMA_NORMAL; hdma_adc1.Init.Priority = DMA_PRIORITY_LOW; hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE; hdma_adc1.Init.Request = DMA请求标志; // 初始化其他参数... HAL_DMA_Init(&hdma_adc1); ``` 3. 安排DMA将数据传输到指定的内存地址,并开始ADC的数据采集: ```c __HAL_ADC_ENABLE(&hadc1); // 开启ADC DMA_HandleTypeDef *hdmaHandle = &hdma_adc1; HAL_DMA_ConfigChannel(&hdmaHandle, &hadc1, ADC_DMA_REQUEST, (uint32_t)&hadc1->DR, (uint32_t)adcBuffer, ADC_BUFFER_SIZE); HAL_DMA_Start_IT(hdmaHandle); // 启动DMA传输 HAL_ADC_Start_DMA(&hadc1, NULL, (uint32_t)adcBuffer); // 开始ADC采样并将结果通过DMA发送到缓冲区 ``` 4. 最后,在DMA完成之前,ADC会继续运行直到停止采集。你可以通过中断或定期检查DMA完成标志来结束这一过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值