STM32G431 ADC 多个channel 采集

REF:

https://blog.csdn.net/A_Peaceful_Place/article/details/148075041

STM32cubeMX

IO 配置

Clock

Projects

Code

main.c

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "fdcan.h"
#include "i2c.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "usb.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

// ADC数据缓冲区 - DMA将数据直接写入这里
volatile uint16_t adc_buffer[ADC_BUFFER_SIZE];
volatile uint8_t adc_conversion_complete = 0;

// 处理后的电压值
float adc_voltage[ADC_CHANNEL_COUNT];

// 当前转换计数
volatile uint32_t adc_conversion_count = 0;


/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc);

void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc);


/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

__IO uint32_t uhADCxConvertedValue = 0;
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* 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_FDCAN1_Init();
  MX_UART4_Init();
  MX_USB_PCD_Init();
  MX_I2C1_Init();
  MX_SPI1_Init();
  MX_TIM2_Init();
  MX_USART1_UART_Init();
  MX_USART3_UART_Init();
  MX_SPI2_Init();
  MX_ADC2_Init();
  /* USER CODE BEGIN 2 */
	
	

  //未执行校准可能导致偏移误差和增益误差。
	//解决方法: 在初始化时调用校准函数:
  HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);
  //HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED);
	
		    //HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);
	//HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED);
  //HAL_ADC_Start_DMA(&hadc1,(uint32_t *)My_adcData,adc_max);
	//HAL_ADC_Start_DMA(&hadc2,(uint32_t *)My_adcData2,adc_max2);
  
	/* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
				
		 ADC_Multich_Sample ();
		 //ADC_Multich_Sample2();
		
		    uint8_t text[30];
        int text_lenth;
       
        uint8_t text_ADC2[30];
        int text_lenth_ADC2;
				
				uint8_t   text_ADC3[100];  //使用数组则OK,使用指针则异常。
        int text_lenth_ADC3;
				{
////         if (HAL_ADC_Start(&hadc2) != HAL_OK)
//        if (HAL_ADC_Start(&hadc1) != HAL_OK)
//        {
//          /* Start Conversation Error */
//          Error_Handler();
//        }
////        if (HAL_ADC_PollForConversion(&hadc2, 10) != HAL_OK)
//        if (HAL_ADC_PollForConversion(&hadc1, 10) != HAL_OK)
//        {
//          /* End Of Conversion flag not set on time */
//          Error_Handler();
//        }
////        if ((HAL_ADC_GetState(&hadc2) & HAL_ADC_STATE_EOC_REG) == HAL_ADC_STATE_EOC_REG)
//        if ((HAL_ADC_GetState(&hadc1) & HAL_ADC_STATE_EOC_REG) == HAL_ADC_STATE_EOC_REG)
//        {
////          uhADCxConvertedValue = HAL_ADC_GetValue(&hadc2);
//          uhADCxConvertedValue = HAL_ADC_GetValue(&hadc1);
//        }
//        
////        text_lenth = sprintf((char *) &text,"adc value: %d %dmV\r\n",uhADCxConvertedValue,(uhADCxConvertedValue*3300*11)>>16); 
//        //text_lenth = sprintf((char *) &text,"G431 adc value: %d %dmV\r\n",((uhADCxConvertedValue*16)>>4),(uhADCxConvertedValue*3300*10)>>16);  //PA0
//				
//				printf("G431 adc value: %d, %dmV\r\n",((uhADCxConvertedValue*16)>>4),(uhADCxConvertedValue*3300*10)>>16);
//		
//		
}
		HAL_Delay(1000);
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_SET);
    
		HAL_Delay(1000);
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET);
		
		HAL_Delay(1000);
		
		printf("Hello, World!\n\r");
		printf("My_adcData = %d\n\r",My_adcData[4]);
//		printf("My_adcData = %d\n\r",My_adcData[8]);
//		printf("My_adcData = %d\n\r",My_adcData[12]);
//		printf("My_adcData = %d\n\r",My_adcData[16]);
		HAL_Delay(1000);
		
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
  RCC_OscInitStruct.PLL.PLLN = 85;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV8;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

// DMA传输完成回调
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    if (hadc->Instance == ADC1)
    {
        adc_conversion_complete = 1;
        adc_conversion_count++;
    }
}

// DMA传输半完成回调(如果使用循环缓冲)
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
{
    // 可选:处理半缓冲区数据
}



int fputc(int ch, FILE *f)//fputc函数的定义。它接受两个参数:一个整数ch(代表要输出的字符),和一个FILE指针f(代表输出流)
{
	HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xFFFF);//通过串口1将字符ch的地址转换为一个指向uint8_t的指针作为要发送数据的地址,发送一个字节,发送的有效时间为0xFFFF
	return ch;//返回发送的字符。在标准的fputc实现中,通常返回写入的字符,或者在发生错误时返回EOF。在这里,它总是返回发送的字符ch,没有错误处理
}
//------------------------------------------------
//版权声明:本文为CSDN博主「小酒丸子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
//原文链接:https://blog.csdn.net/m0_69119438/article/details/136789290
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart4, &ch, 1, 0xffff);
  return ch;
}


/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

main.h

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.h
  * @brief          : Header for main.c file.
  *                   This file contains the common defines of the application.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "stm32g4xx_hal.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include <stdio.h>
/* USER CODE END Includes */

/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */

/* USER CODE END ET */

/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */

/* USER CODE END EC */

/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */

/* USER CODE END EM */

/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);

/* USER CODE BEGIN EFP */

int fputc(int ch, FILE *f);
/* USER CODE END EFP */

/* Private defines -----------------------------------------------------------*/

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

#ifdef __cplusplus
}
#endif

#endif /* __MAIN_H */

adc.c

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    adc.c
  * @brief   This file provides code for the configuration
  *          of the ADC instances.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "adc.h"

/* USER CODE BEGIN 0 */

uint16_t My_adcData[adc_max]={0};
uint16_t My_adcData2[adc_max2]={0}; //这里一定要定义的uint16_t 的数据,因为我们在Cube选择的就是Half Word 类型的数据
 
struct adcValue_type adcValue ;

//------------------------------------------------
//版权声明:本文为CSDN博主「A_Peaceful_Place」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
//原文链接:https://blog.csdn.net/A_Peaceful_Place/article/details/148075041

/* USER CODE END 0 */

ADC_HandleTypeDef hadc1;
ADC_HandleTypeDef hadc2;
DMA_HandleTypeDef hdma_adc1;

/* ADC1 init function */
void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */

  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.GainCompensation = 0;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.NbrOfConversion = 3;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.OversamplingMode = ENABLE;
  hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_128;
  hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_3;
  hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
  hadc1.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure the ADC multi-mode
  */
  multimode.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_3;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}
/* ADC2 init function */
void MX_ADC2_Init(void)
{

  /* USER CODE BEGIN ADC2_Init 0 */

  /* USER CODE END ADC2_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC2_Init 1 */

  /* USER CODE END ADC2_Init 1 */

  /** Common config
  */
  hadc2.Instance = ADC2;
  hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;
  hadc2.Init.Resolution = ADC_RESOLUTION_12B;
  hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc2.Init.GainCompensation = 0;
  hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc2.Init.LowPowerAutoWait = DISABLE;
  hadc2.Init.ContinuousConvMode = DISABLE;
  hadc2.Init.NbrOfConversion = 1;
  hadc2.Init.DiscontinuousConvMode = DISABLE;
  hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc2.Init.DMAContinuousRequests = DISABLE;
  hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc2.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc2) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_4;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC2_Init 2 */

  /* USER CODE END ADC2_Init 2 */

}

static uint32_t HAL_RCC_ADC12_CLK_ENABLED=0;

void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  if(adcHandle->Instance==ADC1)
  {
  /* USER CODE BEGIN ADC1_MspInit 0 */

  /* USER CODE END ADC1_MspInit 0 */

  /** Initializes the peripherals clocks
  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12;
    PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

    /* ADC1 clock enable */
    HAL_RCC_ADC12_CLK_ENABLED++;
    if(HAL_RCC_ADC12_CLK_ENABLED==1){
      __HAL_RCC_ADC12_CLK_ENABLE();
    }

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**ADC1 GPIO Configuration
    PA0     ------> ADC1_IN1
    PA1     ------> ADC1_IN2
    PA2     ------> ADC1_IN3
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* ADC1 DMA Init */
    /* ADC1 Init */
    hdma_adc1.Instance = DMA1_Channel1;
    hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
    hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_adc1.Init.Mode = DMA_CIRCULAR;
    hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);

  /* USER CODE BEGIN ADC1_MspInit 1 */

  /* USER CODE END ADC1_MspInit 1 */
  }
  else if(adcHandle->Instance==ADC2)
  {
  /* USER CODE BEGIN ADC2_MspInit 0 */

  /* USER CODE END ADC2_MspInit 0 */

  /** Initializes the peripherals clocks
  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12;
    PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

    /* ADC2 clock enable */
    HAL_RCC_ADC12_CLK_ENABLED++;
    if(HAL_RCC_ADC12_CLK_ENABLED==1){
      __HAL_RCC_ADC12_CLK_ENABLE();
    }

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**ADC2 GPIO Configuration
    PA7     ------> ADC2_IN4
    */
    GPIO_InitStruct.Pin = GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN ADC2_MspInit 1 */

  /* USER CODE END ADC2_MspInit 1 */
  }
}

void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{

  if(adcHandle->Instance==ADC1)
  {
  /* USER CODE BEGIN ADC1_MspDeInit 0 */

  /* USER CODE END ADC1_MspDeInit 0 */
    /* Peripheral clock disable */
    HAL_RCC_ADC12_CLK_ENABLED--;
    if(HAL_RCC_ADC12_CLK_ENABLED==0){
      __HAL_RCC_ADC12_CLK_DISABLE();
    }

    /**ADC1 GPIO Configuration
    PA0     ------> ADC1_IN1
    PA1     ------> ADC1_IN2
    PA2     ------> ADC1_IN3
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2);

    /* ADC1 DMA DeInit */
    HAL_DMA_DeInit(adcHandle->DMA_Handle);
  /* USER CODE BEGIN ADC1_MspDeInit 1 */

  /* USER CODE END ADC1_MspDeInit 1 */
  }
  else if(adcHandle->Instance==ADC2)
  {
  /* USER CODE BEGIN ADC2_MspDeInit 0 */

  /* USER CODE END ADC2_MspDeInit 0 */
    /* Peripheral clock disable */
    HAL_RCC_ADC12_CLK_ENABLED--;
    if(HAL_RCC_ADC12_CLK_ENABLED==0){
      __HAL_RCC_ADC12_CLK_DISABLE();
    }

    /**ADC2 GPIO Configuration
    PA7     ------> ADC2_IN4
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_7);

  /* USER CODE BEGIN ADC2_MspDeInit 1 */

  /* USER CODE END ADC2_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */
	/*
	*adc数据处理
	*
	*/
void ADC_Multich_Sample (void)
{
	
 printf(" %s==== ,%d \n\r",__func__,__LINE__);
//   函数减速,用来防止程序阻塞
	static uint32_t ADC_Tick1;
	if(uwTick - ADC_Tick1 < 5)
		return;
	ADC_Tick1 = uwTick;
//   函数减速结束
	adcValue .value1=0;
	adcValue .value2=0;
	adcValue .value3=0;
	adcValue .value4 =0;
	
	HAL_ADC_Start_DMA(&hadc1, (uint32_t *)My_adcData,adc_max);//因为你选择的软件触发,所以每次采集都需要开启一次
	
 printf(" %s==== ,%d \n\r",__func__,__LINE__);
	static   uint8_t i;
	
		adcValue .value1 = (My_adcData[0]>>4)*3300/4096;				// data alignment = right alignment; ADC 12 bit; 16 bit data length. so need be removed 4 bit to right for 12 bit ADC;
		adcValue .value2 = (My_adcData[4]>>4)*3300/4096;
		adcValue .value3 = (My_adcData[8]>>4)*3300/4096;
	
	
		printf("adcValue .value1 = %d\n\r",adcValue .value1);
		printf("adcValue .value2 = %d\n\r",adcValue .value2);
		printf("adcValue .value3 = %d\n\r",adcValue .value3);
 
//函数消除干扰,舍去微小电压
	if(adcValue .value1<5)adcValue .value1=0;
	if(adcValue .value2<5)adcValue .value2=0;
	if(adcValue .value3<5)adcValue .value3=0;
	//if(adcValue .value4<5)adcValue .value4=0;
	
	
// printf(" %s==== ,%d \n\r",__func__,__LINE__);
}

void ADC_Multich_Sample2(void)
{
 printf("ADC_Multich_Sample2 %s==== ,%d \n\r",__func__,__LINE__);
	static uint32_t ADC_Tick2;
	if(uwTick - ADC_Tick2 < 10)
		return;
	ADC_Tick2 = uwTick;
 
	adcValue .value5=adcValue .value6=adcValue .value7=adcValue .value8 =0;
	HAL_ADC_Start_DMA(&hadc2, (uint32_t *)My_adcData2,adc_max2);
	static   uint8_t m;
	for(m=1;m<=8;m++){                       				 //遍历8次,进行滤波
		adcValue .value5 += My_adcData2[0+4*m]*330/4096;					
		adcValue .value6 += My_adcData2[1+4*m]*330/4096;
		adcValue .value7 += My_adcData2[2+4*m]*330/4096;
		//adcValue .value8 += My_adcData2[3+4*m]*330/4096;
	}
	adcValue .value5 = adcValue .value5/8 ;
	adcValue .value6 = adcValue .value6/8 ;
	adcValue .value7 = adcValue .value7/8 ;
	//adcValue .value8 = adcValue .value8/8 ;
	
	if(adcValue .value5<5)adcValue .value5=0;
	if(adcValue .value6<5)adcValue .value6=0;
	if(adcValue .value7<5)adcValue .value7=0;
	//if(adcValue .value8<5)adcValue .value8=0;
}

//------------------------------------------------
//版权声明:本文为CSDN博主「A_Peaceful_Place」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
//原文链接:https://blog.csdn.net/A_Peaceful_Place/article/details/148075041

/* USER CODE END 1 */

adc.h

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    adc.h
  * @brief   This file contains all the function prototypes for
  *          the adc.c file
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __ADC_H__
#define __ADC_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* USER CODE BEGIN Includes */
/* USER CODE END Includes */

extern ADC_HandleTypeDef hadc1;

extern ADC_HandleTypeDef hadc2;

/* USER CODE BEGIN Private defines */




// ADC相关定义
#define ADC_CHANNEL_COUNT    4
#define ADC_BUFFER_SIZE      ADC_CHANNEL_COUNT * 10

// 外部变量声明
extern ADC_HandleTypeDef hadc1;
extern DMA_HandleTypeDef hdma_adc1;

// ADC数据缓冲区
extern volatile uint16_t adc_buffer[ADC_BUFFER_SIZE];
extern volatile uint8_t adc_conversion_complete;

// 处理后的数据
extern float adc_voltage[ADC_CHANNEL_COUNT];


/* USER CODE END Private defines */

void MX_ADC1_Init(void);
void MX_ADC2_Init(void);

/* USER CODE BEGIN Prototypes */

#define adc_max 40
#define adc_max2 40
 
extern uint16_t My_adcData[adc_max];
extern uint16_t My_adcData2[adc_max2];
 
struct adcValue_type
{
	uint16_t value1;
	uint16_t value2;
	uint16_t value3;
	uint16_t value4;
	
	uint16_t value5;
	uint16_t value6;
	uint16_t value7;
	uint16_t value8;
};
 
extern struct adcValue_type adcValue;
 
void ADC_Multich_Sample (void);
void ADC_Multich_Sample2(void);

/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif

#endif /* __ADC_H__ */

log printf

ADC PA0\PA1\PA2.

PA0 连接3.3V,其他两个悬空。

cpp 复制代码
ADC_Multich_Sample==== ,336 
 ADC_Multich_Sample==== ,350 
adcValue .value1 = 3295
adcValue .value2 = 14
adcValue .value3 = 0
相关推荐
qq_4017004117 分钟前
FreeRTOS用事件组替代全局变量实现同步
单片机
zhongvv21 分钟前
8位应广单片机与32位M0单片机开发差异总结
经验分享·单片机·嵌入式硬件
咸蛋-超人1 小时前
聊一聊 - STM32的堆和栈空间怎么分配
stm32·单片机·嵌入式硬件
raindrops.3 小时前
STM32之LL库使用(二)
stm32·单片机·嵌入式硬件
日更嵌入式的打工仔5 小时前
单片机基础知识:内狗外狗/软狗硬狗
笔记·单片机
v先v关v住v获v取6 小时前
12米折叠式高空作业车工作臂设计9张cad+三维图+设计说明书
科技·单片机·51单片机
单片机系统设计6 小时前
基于STM32的水质检测系统
网络·stm32·单片机·嵌入式硬件·毕业设计·水质检测
唔好理总之好犀利7 小时前
FreeRTOS中断内使用taskENTER_CRITICAL()进入临界区
单片机·嵌入式硬件
csg11077 小时前
PIC单片机入门实战(一):PIC16F1824/PIC12F1822,从振荡器与Timer1开始
单片机·嵌入式硬件·物联网
清风6666667 小时前
基于单片机的车辆超载报警系统设计及人数检测设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业