使用STM32L031F6芯片 在hal库下进行ADC+DMA多通道采集时候,采集的电压值始终为0是什么原因?

使用STM32L031F6芯片 在hal库下进行ADC+DMA多通道采集时候,采集的电压值始终为0是什么原因?

代码在下面

void adc_nch_dma_init(uint32_t mar)
{
    ADC_ChannelConfTypeDef sConfig = {0};

        
    g_dma_nch_adc_handle.Instance = DMA1_Channel1;
    g_dma_nch_adc_handle.Init.Request = DMA_REQUEST_0;
    g_dma_nch_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;
    g_dma_nch_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE;
    g_dma_nch_adc_handle.Init.MemInc = DMA_MINC_ENABLE;
    g_dma_nch_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    g_dma_nch_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    g_dma_nch_adc_handle.Init.Mode = DMA_CIRCULAR;
    g_dma_nch_adc_handle.Init.Priority = DMA_PRIORITY_LOW;
    HAL_DMA_Init(&g_dma_nch_adc_handle);
    __HAL_LINKDMA(&g_adc_nch_dma_handle,DMA_Handle,g_dma_nch_adc_handle);
    

    g_adc_nch_dma_handle.Instance = ADC1;
    g_adc_nch_dma_handle.Init.OversamplingMode = DISABLE; 
    g_adc_nch_dma_handle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;  
    g_adc_nch_dma_handle.Init.Resolution = ADC_RESOLUTION_12B; 
    g_adc_nch_dma_handle.Init.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
    g_adc_nch_dma_handle.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
    g_adc_nch_dma_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;  
    g_adc_nch_dma_handle.Init.ContinuousConvMode = ENABLE; 
    g_adc_nch_dma_handle.Init.DiscontinuousConvMode = DISABLE; 
    g_adc_nch_dma_handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    g_adc_nch_dma_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; 
    g_adc_nch_dma_handle.Init.DMAContinuousRequests = ENABLE;
    g_adc_nch_dma_handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; 
    g_adc_nch_dma_handle.Init.Overrun = ADC_OVR_DATA_PRESERVED;
    g_adc_nch_dma_handle.Init.LowPowerAutoWait = DISABLE;  
    g_adc_nch_dma_handle.Init.LowPowerFrequencyMode = DISABLE;
    g_adc_nch_dma_handle.Init.LowPowerAutoPowerOff = DISABLE;
    HAL_ADC_Init(&g_adc_nch_dma_handle);
    

    HAL_ADCEx_Calibration_Start(&g_adc_nch_dma_handle, ADC_SINGLE_ENDED);     

    sConfig.Channel = ADC_CHANNEL_0;
    sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &sConfig);
    
    sConfig.Channel = ADC_CHANNEL_1;
    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &sConfig);
    
    sConfig.Channel = ADC_CHANNEL_2;
    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &sConfig);
    
    sConfig.Channel = ADC_CHANNEL_3;
    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &sConfig);
    
    sConfig.Channel = ADC_CHANNEL_4;
    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &sConfig);
    
    sConfig.Channel = ADC_CHANNEL_7;
    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &sConfig);
    
    HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
    
    //HAL_DMA_Start_IT(&g_dma_nch_adc_handle, (uint32_t)&ADC1->DR, mar, 0);    
    HAL_ADC_Start_DMA(&g_adc_nch_dma_handle, &mar, 300);                        
}

上面是配置代码,GPIO口在MSP里面配置了

这一段是使能DMA和ADC的代码,之前想打印看看有没有程序有没有进去这个函数

void adc_dma_enable(uint32_t mar,uint16_t cndtr)
{


    __HAL_DMA_DISABLE(&g_dma_nch_adc_handle);
    __HAL_ADC_DISABLE(&g_adc_nch_dma_handle);
    while(__HAL_DMA_GET_FLAG(&g_dma_nch_adc_handle, __HAL_DMA_GET_TC_FLAG_INDEX(&g_dma_nch_adc_handle)));

    DMA1_Channel1->CNDTR = cndtr;
    __HAL_DMA_ENABLE(&g_dma_nch_adc_handle);
    __HAL_ADC_ENABLE(&g_adc_nch_dma_handle);
    
    
    HAL_ADC_Start_DMA(&g_adc_nch_dma_handle, &mar, 300);;


        
}

这一段是DMA1中断服务程序,之前配置DMA1的时候开启了中断和不循环模式,在里面打印数据,发现程序没有进去过中断服务函数,在it.c文件里将被注释掉的_IRQHandler(void)函数重新开启,发现还是进不去中断服务函数

//uint8_t g_adc_dma_sta = 0;
//void DMA1_Channel1_IRQHandler(void)
//{

//    if(DMA1->ISR & (1<<1))
//    {
//        g_adc_dma_sta=1;
//        DMA1->IFCR = 1<<1;
//    }
//}

于是我就关闭并使用DMA循环模式,然后注释掉这段代码,在main函数里面开启,发现数组里面的数据还是为0,测不到电压值,想问问到底是什么原因


#define ADC_DMA_BUF_SIZE        50 * 6     
uint16_t g_adc_dma_buf[ADC_DMA_BUF_SIZE];  

//extern uint8_t g_adc_dma_sta;               

int main(void)
{
    uint16_t i,j;
    uint16_t adcx;
    uint32_t sum;
    float temp;

    HAL_Init();                               
    SystemClock_Config();                              
    USART2_UART_Init();                    
   

    adc_nch_dma_init((uint32_t)&g_adc_dma_buf);

    adc_dma_enable((uint32_t)&g_adc_dma_buf,ADC_DMA_BUF_SIZE);  

    while (1)
    {

        
        

            for(j = 0; j < 6; j++)
            {
                sum = 0;
                for (i = 0; i < ADC_DMA_BUF_SIZE / 6; i++)  
                {
                    sum += g_adc_dma_buf[(6 * i) + j];   
                }
                adcx = sum / (ADC_DMA_BUF_SIZE / 6);        
                



                temp = (float)adcx * (3.3 / 4096);  
                adcx = temp;                    


                temp -= adcx;                      
                temp *= 1000;                     

            }
 
//            g_adc_dma_sta = 0;                   
            adc_dma_enable((uint32_t)&g_adc_dma_buf,ADC_DMA_BUF_SIZE);      
        

        led_Toggle();
        HAL_Delay(3000);
    }
}

img

可能导致您在STM32L031F6芯片上使用ADC+DMA功能时得到恒定值为0的几个潜在原因。以下是您可以检查的一些事项:

  1. ADC引脚配置:确保在GPIO初始化代码中正确配置ADC引脚。确保将其设置为模拟输入,并选择相应的引脚用于您正在使用的ADC通道。

  2. ADC时钟配置:验证在SystemClock_Config()函数中正确配置ADC时钟。确保ADC时钟源和分频器设置正确。

  3. DMA传输大小:检查DMA传输大小。确保它与ADC缓冲区的大小和您使用的通道数量相匹配。在您的代码中,您将ADC_DMA_BUF_SIZE定义为50 * 6,这似乎表示您正在使用6个ADC通道和每个通道的50个样本的缓冲区大小。确保这与您的预期设置相匹配。

  4. DMA中断配置:如果您想使用DMA中断,请确保DMA中断已正确配置并在NVIC设置中启用。取消注释DMA1_Channel1_IRQHandler()函数,并确保它被注册为DMA1_Channel1_IRQn的中断处理程序。

  5. ADC和DMA的启用顺序:检查您启用ADC和DMA的顺序。确保在启用DMA之前启用ADC。

【以下回答由 GPT 生成】

根据提供的代码,有几个可能的原因导致采集的电压值始终为0:

  1. ADC配置错误:可能是ADC配置中的某些参数设置不正确导致采集的电压值为0。推荐重新检查和确认ADC初始化代码中的各个参数设置,特别是时钟分频、采样时间、数据对齐等。

  2. 通道未正确配置:ADC多通道采集时,需要明确指定要采集的通道。在给定的示例代码中,缺少了配置每个通道的代码。请确保使用HAL_ADC_ConfigChannel()函数将每个要采集的通道配置到ADC上。

  3. DMA配置错误:DMA配置可能有误,导致数据无法正确传输。建议检查并确认DMA初始化代码中的各个参数设置,特别是方向、地址增量和数据对齐等。

  4. 中断未启用:ADC采集完成后,需要通过中断来触发数据传输或提醒主程序进行处理。请确保已启用ADC的中断并正确处理。

综上所述,请检查以上可能的问题并进行适当的调整。如果问题仍然存在,请提供更多的代码和相关信息,以便进一步分析和诊断问题。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^