问答

汇集网友智慧,解决技术难题

21ic问答首页 - G032实现双通道ADC+DMA出现采集错误

G032实现双通道ADC+DMA出现采集错误

本帖最后由 阿斯顿发大水 于 2025-11-20 15:27 编辑

N32G032实现双通道ADC+DMA实现数据采集


void RCC_Configuration(void)
{
    ErrorStatus HSIStartUpStatus;  // HSI启动状态
    // 1. 使能ADC、DMA、GPIOA时钟(确保时钟已使能)
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA , ENABLE);
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE);
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC, ENABLE);
    /* 使能HSI时钟 */
    RCC_EnableHsi(ENABLE);
    /* 等待HSI稳定(最多等待10ms,超时则启动失败) */
    HSIStartUpStatus = RCC_WaitHsiStable();
    if (HSIStartUpStatus != SUCCESS)
    {
        /* HSI启动失败,进入死循环(需硬件复位) */
        while (1);
    }
   
    /* 配置ADC时钟(ADC工作频率需≤18MHz)   ADC_1MCLK用于内部计时功能,在RCC中配置,频率大小必须配置成1M  */
    RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSI, RCC_ADC1MCLK_DIV8);  // ADC1M时钟=HSI/8=1MHz
//    RCC_ConfigAdcHclk(RCC_ADCHCLK_DIV16);                         // ADC核时钟=AHB/16=3MHz
        ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16);
}



void ADC_DMA_Configuration(void)
{
    ADC_InitType ADC_InitStructure;
    DMA_InitType DMA_InitStructure;
    GPIO_InitType GPIO_InitStructure;
        ADC_InitTypeEx ADC_InitStructureEx;
   
    RCC_Configuration();

    // 1. 配置PA0、PA1为模拟输入
    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin = PA0_MAINS_ZERO_PIN | PA1_INV_VOLT_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_ANALOG;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
       
    // 2. 配置DMA通道(单通道传输多个ADC数据)
    DMA_DeInit(DMA_CH1);  // 使用通道1
    DMA_StructInit(&DMA_InitStructure);
    DMA_InitStructure.PeriphAddr = (uint32_t)&ADC->DAT;    // ADC数据寄存器
    DMA_InitStructure.MemAddr = (uint32_t)&adc_values[0]; // 起始地址
    DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;      // 外设→内存
    DMA_InitStructure.BufSize = 2;                         // 传输2个通道数据
    DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;  // 外设地址固定
    DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE;  // 内存地址递增
    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD; // 16位
    DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.CircularMode = DMA_MODE_CIRCULAR;    // 循环模式
    DMA_InitStructure.Priority = DMA_PRIORITY_HIGH;
    DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
    DMA_Init(DMA_CH1, &DMA_InitStructure);
    DMA_RequestRemap(DMA_REMAP_ADC, DMA, DMA_CH1, ENABLE);
    DMA_EnableChannel(DMA_CH1, ENABLE);
       

    // 3. 配置ADC多通道扫描
    ADC_InitStruct(&ADC_InitStructure);
    ADC_InitStructure.MultiChEn = ENABLE;               // 多通道使能
    ADC_InitStructure.ContinueConvEn = ENABLE;          // 连续转换
    ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE; // 软件触发
    ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;       // 右对齐
    ADC_InitStructure.ChsNumber = 2;                    // 2个转换通道
    ADC_Init(ADC, &ADC_InitStructure);
       

    // 4. 配置通道转换顺序
    // PA0(ADC_CH0):第1个转换
    ADC_ConfigRegularChannel(ADC, ADC_CH_0_PA0, 1, ADC_SAMP_TIME_56CYCLES5);
    // PA1(ADC_CH1):第2个转换  
    ADC_ConfigRegularChannel(ADC, ADC_CH_1_PA1, 2, ADC_SAMP_TIME_56CYCLES5);

    // 5. 使能ADC并等待就绪
    ADC_Enable(ADC, ENABLE);
    while (!ADC_GetFlagStatusNew(ADC, ADC_FLAG_RDY));
    while (ADC_GetFlagStatusNew(ADC, ADC_FLAG_PD_RDY));
   
    // 6. 使能ADC-DMA,启动转换
    ADC_EnableDMA(ADC, ENABLE);
    ADC_EnableSoftwareStartConv(ADC, ENABLE);
}

不管有没有输入,采集的数据都是接近12位的最大值
回答 +关注 0
56人浏览 0人回答问题 分享 举报
0 个回答

您需要登录后才可以回复 登录 | 注册