STM32H7A3 ADC+DMA使用问题

11 篇文章 0 订阅

问题1:DMA采用半字传输16位ADC值,用于存储ADC数据的数组一定是采集数的两倍,否则会产生ADC溢出的错误中断HAL_ADC_ErrorCallback,从而无法进入ADC采集完成中断HAL_ADC_ConvCpltCallback。具体为什么是两倍,网上有很多解释,有兴趣的可以去查一下。

问题2:在使用ADC+DMA采集的时候突然发现一个奇怪的现象,就是只要在程序的任何一个地方再申请一个全局变量,ADC就会出现错误中断HAL_ADC_ErrorCallback。最后发现程序没有什么问题,就怀疑和初始化顺序相关,然后就使用STM32CUBEMX配置了一下ADC+DMA,看一下配置出来的初始化顺序,然后改成和CUBEMX配置顺序一样的,这个问题就解决了。


void ADC_Init(void)
{  
    ADC_ChannelConfTypeDef sConfig = {0};
	
	AdcHandle.Instance = ADC1;
    AdcHandle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2; 
    AdcHandle.Init.Resolution = ADC_RESOLUTION_16B; 
    AdcHandle.Init.ScanConvMode = ADC_SCAN_ENABLE; 
    AdcHandle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; 
    AdcHandle.Init.LowPowerAutoWait = DISABLE; 
    AdcHandle.Init.ContinuousConvMode = ENABLE; 
    AdcHandle.Init.NbrOfConversion = 3; 
    AdcHandle.Init.DiscontinuousConvMode = DISABLE; 
    AdcHandle.Init.NbrOfDiscConversion = 1; 
    AdcHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START; 
    AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; 
    AdcHandle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; 
    AdcHandle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; 
    AdcHandle.Init.OversamplingMode = DISABLE; /* 禁止过采样 */
    /* 初始化 ADC */
    if (HAL_ADC_Init(&AdcHandle) != HAL_OK)
    {
    }
    /* 校准 ADC,采用偏移校准 */
    if (HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
    {
    }
	
	
	/*黄灯对应采集通道*/
    sConfig.Channel = ADC_CHANNEL_3; /* 配置使用的 ADC 通道 */
    sConfig.Rank = ADC_REGULAR_RANK_1; /* 采样序列里的第 1 个 */
    sConfig.SamplingTime = ADC_SAMPLETIME_387CYCLES_5; /* 采样周期 */
    sConfig.SingleDiff = ADC_SINGLE_ENDED; /* 单端输入 */
    sConfig.OffsetNumber = ADC_OFFSET_NONE; /* 无偏移 */
    sConfig.Offset = 0; /* 无偏移的情况下,此参数忽略 */
    sConfig.OffsetRightShift = DISABLE; /* 禁止右移 */
    sConfig.OffsetSignedSaturation = DISABLE; /* 禁止有符号饱和 */
	HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
	

	sConfig.Channel = ADC_CHANNEL_7; /* 配置使用的 ADC 通道 */
    sConfig.Rank = ADC_REGULAR_RANK_2; /* 采样序列里的第 1 个 */
    HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
	

	sConfig.Channel = ADC_CHANNEL_4; /* 配置使用的 ADC 通道 */
    sConfig.Rank = ADC_REGULAR_RANK_3; /* 采样序列里的第 1 个 */
    HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
	

	sConfig.Channel = ADC_CHANNEL_9; /* 配置使用的 ADC 通道 */
    sConfig.Rank = ADC_REGULAR_RANK_4; /* 采样序列里的第 1 个 */
    HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
	
	
    /* 启动 ADC 的 DMA 方式传输 */
    if (HAL_ADC_Start_DMA(&AdcHandle, (uint32_t*)adc_buf, 3) != HAL_OK)
    {
    }

}

void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(adcHandle->Instance==ADC1)
  {
    /* ADC1 clock enable */
    __HAL_RCC_ADC12_CLK_ENABLE();
    __HAL_RCC_DMA1_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_4|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
	
	
	ADC1DMA_Handler.Instance = DMA1_Stream1; 
    ADC1DMA_Handler.Init.Request = DMA_REQUEST_ADC1; 
    ADC1DMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY; 
    ADC1DMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;
    ADC1DMA_Handler.Init.MemInc = DMA_MINC_ENABLE; 
    ADC1DMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; 
    ADC1DMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; 
    ADC1DMA_Handler.Init.Mode = DMA_CIRCULAR; 
    ADC1DMA_Handler.Init.Priority = DMA_PRIORITY_LOW; 
    ADC1DMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 
    ADC1DMA_Handler.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 
    ADC1DMA_Handler.Init.MemBurst = DMA_MBURST_SINGLE; 
    ADC1DMA_Handler.Init.PeriphBurst = DMA_PBURST_SINGLE;
    if(HAL_DMA_Init(&ADC1DMA_Handler) != HAL_OK)
    {
    }

	__HAL_LINKDMA(&AdcHandle, DMA_Handle, ADC1DMA_Handler);
	/* DMA interrupt init */
    /* DMA1_Stream0_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 2, 0);
    HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
  }
}

void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{

  if(adcHandle->Instance==ADC1)
  {
    /* Peripheral clock disable */
    __HAL_RCC_ADC12_CLK_DISABLE();
    __HAL_RCC_DMA1_CLK_DISABLE();

    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0|GPIO_PIN_4|GPIO_PIN_5);
  }
}


void DMA1_Stream1_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&ADC1DMA_Handler);
}


void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
  
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您想了解有关MATLAB中ADC(模数转换器)的内容。MATLAB提供了多种方法来模拟和分析ADC的性能。下面是一些与ADC相关的MATLAB功能和工具: 1. Simulink中的ADC模块:Simulink是MATLAB的图形化建模和仿真环境,其中包含了ADC模块,可以用于模拟ADC的性能。您可以配置ADC的参数,如分辨率、采样率、非线性误差等,并将其与其他系统组件进行连接和仿真。 2. Signal Processing Toolbox:这个工具箱提供了一些函数和工具,可用于模拟和分析模拟信号到数字信号的转换过程。您可以使用该工具箱中的函数来生成模拟信号、添加噪声、模拟ADC的非线性特性,并进行信号重构和后处理。 3. 数据采集工具箱(Data Acquisition Toolbox):该工具箱提供了与外部硬件设备进行数据采集和控制的功能。如果您需要将MATLAB与实际硬件连接并进行ADC数据采集,则可以使用该工具箱来配置和控制ADC设备,并进行数据采集和分析。 4. 信号处理工具箱(Signal Processing Toolbox)和通信系统工具箱(Communications System Toolbox):这些工具箱提供了一些用于数字信号处理和通信系统设计的函数和工具。您可以使用这些工具箱来处理和分析从ADC获取的数字信号,进行滤波、频谱分析、信号再构建等操作。 这些是MATLAB中与ADC相关的一些功能和工具。您可以根据具体的需求选择适合您的方法和工具来模拟和分析ADC的性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值