问题现象:
用最新版的6.3.0版CUBEMX+最新的L0系列1.12.1的库,生成ADC+DMA代码,添上几句简单的代码和回调函数本应该就可以正常AD了,结果DMA始终无法传输数据,而单步运行所有初始化和运行过程始终返回HAL_OK,但是始终不进DMA传输过程。
一度以为买到假的STM32,又一度以为板子设计有问题而开始怀疑人生。
解决办法:
将CUBEMX生成的原始代码中main初始化代码
MX_GPIO_Init();
MX_ADC_Init();
MX_DMA_Init();
调整ADC和DMA初始化顺序成为
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC_Init();
原因:
CUBEMX在ADC的初始化过程中加入了DMA和ADC之间产生关联的代码
/**
* @brief ADC MSP Initialization
* This function configures the hardware resources used in this example
* @param hadc: ADC handle pointer
* @retval None
*/
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hadc->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspInit 0 */
HAL_DMA_DeInit(&hdma_adc);
/* USER CODE END ADC1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**ADC GPIO Configuration
PA0 ------> ADC_IN0
PA1 ------> ADC_IN1
PA7 ------> ADC_IN7
*/
GPIO_InitStruct.Pin = Battry_vol_Pin|Temp85_1st_Input_Pin|Temp85_2st_Input_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* ADC1 DMA Init */
/* ADC Init */
hdma_adc.Instance = DMA1_Channel1;
hdma_adc.Init.Request = DMA_REQUEST_0;
hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc.Init.Mode = DMA_CIRCULAR;
hdma_adc.Init.Priority = DMA_PRIORITY_HIGH;
if (HAL_DMA_Init(&hdma_adc) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc);
/* ADC1 interrupt Init */
HAL_NVIC_SetPriority(ADC1_COMP_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ADC1_COMP_IRQn);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
}
}
而DMA的时钟却在执行完ADC初始化后才开启,换句话就是如果先运行ADC初始化而没有开启DMA时钟会导致DMA配置失败,而不会返回任何错误代码。
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
由此产生了DMA不传输AD数据。