[笔记]STM32基于HAL库的ADC+DMA多通道扫描

前提:有一段时间没有使用STM32了,最近在使用ADC功能,要提高其效率的问题就会用到DMA,但是ST公司的STM32CubeMX软件生成出来的代码,它的排序是有问题的,所以本文章进行记录

 

MCU:STM32G031P6F6

生成软件工具:STM32CubeMX

前面的部分我就省略了,我就挑重点

1、选择ADC的输入通道

2、设置DMA为循环模式、半字传输、外设到内存

3、添加Rank列表参数,这一步是你有几个ADC通道就写几个Rank值

 之后扫描存储的顺序就会按照你这里设定的通道,从1到3顺序读取和保存到数组中

4、使能扫描模式、连续模式、DMA

5、修改ADC的频率

因为ADC的频率不能超过12M,所以你要在时钟树中修改一下。

请注意,毕竟每个系列或型号多多少少的时钟树上是不同的显示,所以就只管找到ADC所属于的时钟或是APB/AHB之类的

我这里选择21.333333明显是超过了12M,但是ADC的配置中会有分频器的问题,所以最后的频率是21.3333 / 2

6、最后配置一下后面的路径和版本

如果不会配置的,请参考其他博主的方法,这里我就不提供了

 7、生成代码

Keil打开代码后,有一行DMA初始化代码要放在ADC初始化的前面才能正常使用DMA+ADC的功能,否则出来的结果都是0!!!

最后贴出部分代码

int main(void)
{
    
  /* USER CODE BEGIN 1 */
    float Vin = 0;
    float Vout = 0;
    float Iin = 0;
	uint16_t AD_DMA[3] = {0};
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
	MX_DMA_Init();
  MX_ADC1_Init();
  MX_TIM1_Init();
//  MX_DMA_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	
	
	printf("hello\r\n");
	
	HAL_ADCEx_Calibration_Start(&hadc1);
	HAL_ADC_Start_DMA(&hadc1, (uint32_t*)AD_DMA, 3);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		HAL_Delay(1000);
		Vin = ((AD_DMA[2]*(3.3/4096));
		Vout = ((AD_DMA[1]*(3.3/4096));
		Iin = ((AD_DMA[0]*(3.3/4096));
		
		printf("Vin = %f\r\n",Vin);
		printf("Vout = %f\r\n",Vout);
		printf("Iin = %f\r\n",Iin);
		
		
  }
  /* USER CODE END 3 */
}

最后

导致这个问题的原因可能是时钟没有开启,却配置DMA参数。而导致参数并未成功赋值。

我们可以看到MX_DMA_Init函数里面只有三行代码,开启时钟、配置DMA的NVIC、开启DMA的NVIC

按照排除法,应该就是时钟问题

有问题的话请在评论区或是私信,有点要说,CSDN的私信和评论的提醒做的有点拉跨,我在使用的时候没有一眼发现有人私信或是评论。不知道是不是我的设置问题。

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32上进行多路ADC采样时,可以使用循环扫描模式。循环扫描模式允许我们一次性采样多个通道,每个通道的采样结果都会被存储在相应的寄存器中。 以下是一个简单的示例代码,实现了ADC1、ADC2、ADC3三个通道的循环扫描采样: ```c // 定义通道数组 uint32_t channels[] = {ADC_CHANNEL_0, ADC_CHANNEL_1, ADC_CHANNEL_2}; // 初始化ADC HAL_ADC_Init(&hadc1); // 配置ADC采样模式 ADC_ChannelConfTypeDef sConfig = {0}; sConfig.Rank = ADC_RANK_CHANNEL_NUMBER; sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.Offset = 0; HAL_ADC_ConfigChannel(&hadc1, &sConfig); // 配置循环扫描模式 hadc1.Init.ScanConvMode = ENABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.NbrOfConversion = 3; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; HAL_ADC_Init(&hadc1); // 启动ADC HAL_ADC_Start(&hadc1); // 循环采样 for (;;) { // 等待采样完成 HAL_ADC_PollForConversion(&hadc1, 100); // 读取采样结果 uint16_t result1 = HAL_ADC_GetValue(&hadc1); uint16_t result2 = HAL_ADC_GetValue(&hadc1); uint16_t result3 = HAL_ADC_GetValue(&hadc1); // 处理采样结果 // ... // 启动下一轮采样 HAL_ADC_Start(&hadc1); } ``` 在上面的代码中,我们首先定义了一个通道数组 `channels`,其中包含了需要采样的三个通道。然后我们通过 `HAL_ADC_Init` 函数初始化了ADC,并设置了采样模式。接着,我们将 `hadc1.Init.ScanConvMode` 设置为 `ENABLE`,表示启用循环扫描模式,并将 `hadc1.Init.NbrOfConversion` 设置为 3,表示采样三个通道。最后,我们通过调用 `HAL_ADC_Start` 函数启动ADC。 在循环中,我们首先调用 `HAL_ADC_PollForConversion` 函数等待采样完成,然后通过 `HAL_ADC_GetValue` 函数读取每个通道的采样结果,最后对采样结果进行处理。最后,我们再次调用 `HAL_ADC_Start` 函数启动下一轮采样。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值