使用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);
}
}
可能导致您在STM32L031F6芯片上使用ADC+DMA功能时得到恒定值为0的几个潜在原因。以下是您可以检查的一些事项:
ADC引脚配置:确保在GPIO初始化代码中正确配置ADC引脚。确保将其设置为模拟输入,并选择相应的引脚用于您正在使用的ADC通道。
ADC时钟配置:验证在SystemClock_Config()函数中正确配置ADC时钟。确保ADC时钟源和分频器设置正确。
DMA传输大小:检查DMA传输大小。确保它与ADC缓冲区的大小和您使用的通道数量相匹配。在您的代码中,您将ADC_DMA_BUF_SIZE定义为50 * 6,这似乎表示您正在使用6个ADC通道和每个通道的50个样本的缓冲区大小。确保这与您的预期设置相匹配。
DMA中断配置:如果您想使用DMA中断,请确保DMA中断已正确配置并在NVIC设置中启用。取消注释DMA1_Channel1_IRQHandler()函数,并确保它被注册为DMA1_Channel1_IRQn的中断处理程序。
ADC和DMA的启用顺序:检查您启用ADC和DMA的顺序。确保在启用DMA之前启用ADC。
【以下回答由 GPT 生成】
根据提供的代码,有几个可能的原因导致采集的电压值始终为0:
ADC配置错误:可能是ADC配置中的某些参数设置不正确导致采集的电压值为0。推荐重新检查和确认ADC初始化代码中的各个参数设置,特别是时钟分频、采样时间、数据对齐等。
通道未正确配置:ADC多通道采集时,需要明确指定要采集的通道。在给定的示例代码中,缺少了配置每个通道的代码。请确保使用HAL_ADC_ConfigChannel()
函数将每个要采集的通道配置到ADC上。
DMA配置错误:DMA配置可能有误,导致数据无法正确传输。建议检查并确认DMA初始化代码中的各个参数设置,特别是方向、地址增量和数据对齐等。
中断未启用:ADC采集完成后,需要通过中断来触发数据传输或提醒主程序进行处理。请确保已启用ADC的中断并正确处理。
综上所述,请检查以上可能的问题并进行适当的调整。如果问题仍然存在,请提供更多的代码和相关信息,以便进一步分析和诊断问题。