简单的来说就是关闭DMA之后再次初始化。
之前调试F051遇到过这个问题,当时需求精度不高,就屏蔽掉了。现在使用F030再次遇到,就跟踪仿真观察寄存器,找到折中的办法。
问题详细描述:
ADC初始化函数如下图:
/* ADC 初始化配置 */
static void MX_ADC_Init(void)
{
LL_ADC_InitTypeDef ADC_InitStruct = {0};
LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* ADC相关外设时钟使能 */
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_ADC1);
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
/* DMA 控制器时钟使能 */
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
/**ADC GPIO 配置:PA0 ------> ADC_IN0 */
GPIO_InitStruct.Pin = LL_GPIO_PIN_0 | LL_GPIO_PIN_1;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* 配置ADC的全局特性:时钟、分辨率、数据对齐和转换次数 */
ADC_InitStruct.Clock = LL_ADC_CLOCK_SYNC_PCLK_DIV4;
ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;
ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;
LL_ADC_Init(ADC1, &ADC_InitStruct);
ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;//LL_ADC_REG_CONV_CONTINUOUS;//
ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_UNLIMITED;
ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN;
LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
/* 配置ADC通道 */
// LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_TEMPSENSOR);
LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_VREFINT);
LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_0);
LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_1);
// LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_PATH_INTERNAL_TEMPSENSOR);
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_PATH_INTERNAL_VREFINT);
LL_ADC_REG_SetSequencerScanDirection(ADC1, LL_ADC_REG_SEQ_SCAN_DIR_FORWARD);
LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_239CYCLES_5);
LL_ADC_DisableIT_EOC(ADC1);
LL_ADC_DisableIT_EOS(ADC1);
LL_ADC_StartCalibration(ADC1);
while( LL_ADC_IsCalibrationOnGoing(ADC1));
LL_ADC_Enable(ADC1);
/* ADC DMA初始化 */
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_LOW);
LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MODE_CIRCULAR);
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PDATAALIGN_WORD);
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MDATAALIGN_WORD);
LL_DMA_SetDataLength(DMA1,LL_DMA_CHANNEL_1,ADBufferSize);
LL_DMA_SetPeriphAddress(DMA1,LL_DMA_CHANNEL_1,LL_ADC_DMA_GetRegAddr(ADC1,LL_ADC_DMA_REG_REGULAR_DATA));
LL_DMA_SetMemoryAddress(DMA1,LL_DMA_CHANNEL_1,(uint32_t)ADC_ConvertedValue);
LL_DMA_EnableChannel(DMA1,LL_DMA_CHANNEL_1);
LL_DMA_DisableChannel(DMA1,LL_DMA_CHANNEL_1);
/* ADC DMA再次初始化 */
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_LOW);
LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MODE_CIRCULAR);
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PDATAALIGN_WORD);
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MDATAALIGN_WORD);
LL_DMA_SetDataLength(DMA1,LL_DMA_CHANNEL_1,ADBufferSize);
LL_DMA_SetPeriphAddress(DMA1,LL_DMA_CHANNEL_1,LL_ADC_DMA_GetRegAddr(ADC1,LL_ADC_DMA_REG_REGULAR_DATA));
LL_DMA_SetMemoryAddress(DMA1,LL_DMA_CHANNEL_1,(uint32_t)ADC_ConvertedValue);
LL_DMA_EnableChannel(DMA1,LL_DMA_CHANNEL_1);
LL_ADC_REG_StartConversion(ADC1);
}
在使用校准之后,ADC准确度能提升很大,建议还是加上
LL_ADC_StartCalibration(ADC1);
while( LL_ADC_IsCalibrationOnGoing(ADC1));
但是问题就在校准之后,ADC的DR寄存器会产生校准码,打开DMA后会进行一次传输。
试了很多办法,清除不掉这次传输。没办法只能关闭DMA之后,再次配置。ADC数据才能按照顺序存储在数组中。

1732

被折叠的 条评论
为什么被折叠?



