【STM32G491试用】(4) ADC内核
看到网上有网友发帖说是STM32G4系列有多个独立ADC内核,可以同步采样转换多路ADC输入信号。有点疑惑,
翻阅STM32G4用户手册,它的ADC模块框图如下,应该是只有1个ADC转换内核,多路转换器分时转换。
决定使用STM32G491开发板来验证一下,使用直流源来测试没有意义,需要使用正弦波来测试。首先使用片内
DAC1通道1产生一个50HZ正弦波信号,然后分别施加到ADC1_2、ADC2_1、ADC3_5输入端,3路ADC同步使用
TIM6_TROG触发, DMA数据传输 。电路原理框图见下:
DAC1产生的50HZ正弦波
相关代码
DAC.C
- #include "dac.h"
- DAC_HandleTypeDef hdac1;
- DMA_HandleTypeDef hdma_dac1_ch1;
- void MX_DAC1_Init(void)
- {
- DAC_ChannelConfTypeDef sConfig = {0};
- hdac1.Instance = DAC1;
- if (HAL_DAC_Init(&hdac1) != HAL_OK)
- {
- Error_Handler();
- }
- sConfig.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_AUTOMATIC;
- sConfig.DAC_DMADoubleDataMode = DISABLE;
- sConfig.DAC_SignedFormat = DISABLE;
- sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
- sConfig.DAC_Trigger = DAC_TRIGGER_T2_TRGO;
- sConfig.DAC_Trigger2 = DAC_TRIGGER_NONE;
- sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
- sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_ENABLE;
- sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
- if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK)
- {
- Error_Handler();
- }
- }
- void HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- if(dacHandle->Instance==DAC1)
- {
- __HAL_RCC_DAC1_CLK_ENABLE();
- __HAL_RCC_GPIOA_CLK_ENABLE();
- GPIO_InitStruct.Pin = GPIO_PIN_4;
- GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- hdma_dac1_ch1.Instance = DMA1_Channel4;
- hdma_dac1_ch1.Init.Request = DMA_REQUEST_DAC1_CHANNEL1;
- hdma_dac1_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH;
- hdma_dac1_ch1.Init.PeriphInc = DMA_PINC_DISABLE;
- hdma_dac1_ch1.Init.MemInc = DMA_MINC_ENABLE;
- hdma_dac1_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
- hdma_dac1_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
- hdma_dac1_ch1.Init.Mode = DMA_CIRCULAR;
- hdma_dac1_ch1.Init.Priority = DMA_PRIORITY_MEDIUM;
- if (HAL_DMA_Init(&hdma_dac1_ch1) != HAL_OK)
- {
- Error_Handler();
- }
- __HAL_LINKDMA(dacHandle,DMA_Handle1,hdma_dac1_ch1);
- }
- }
- void HAL_DAC_MspDeInit(DAC_HandleTypeDef* dacHandle)
- {
- if(dacHandle->Instance==DAC1)
- {
- __HAL_RCC_DAC1_CLK_DISABLE();
- HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4);
- HAL_DMA_DeInit(dacHandle->DMA_Handle1);
- }
- }
复制代码
ADC.C
- #include "adc.h"
- ADC_HandleTypeDef hadc1;
- ADC_HandleTypeDef hadc2;
- ADC_HandleTypeDef hadc3;
- DMA_HandleTypeDef hdma_adc1;
- DMA_HandleTypeDef hdma_adc2;
- DMA_HandleTypeDef hdma_adc3;
- void MX_ADC1_Init(void)
- {
- ADC_MultiModeTypeDef multimode = {0};
- ADC_ChannelConfTypeDef sConfig = {0};
- hadc1.Instance = ADC1;
- hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
- hadc1.Init.Resolution = ADC_RESOLUTION_12B;
- hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
- hadc1.Init.GainCompensation = 0;
- hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
- hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
- hadc1.Init.LowPowerAutoWait = DISABLE;
- hadc1.Init.ContinuousConvMode = DISABLE;
- hadc1.Init.NbrOfConversion = 1;
- hadc1.Init.DiscontinuousConvMode = DISABLE;
- hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T6_TRGO;
- hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
- hadc1.Init.DMAContinuousRequests = ENABLE;
- hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
- hadc1.Init.OversamplingMode = DISABLE;
- if (HAL_ADC_Init(&hadc1) != HAL_OK)
- {
- Error_Handler();
- }
- multimode.Mode = ADC_MODE_INDEPENDENT;
- if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
- {
- Error_Handler();
- }
- sConfig.Channel = ADC_CHANNEL_2;
- sConfig.Rank = ADC_REGULAR_RANK_1;
- sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5;
- sConfig.SingleDiff = ADC_SINGLE_ENDED;
- sConfig.OffsetNumber = ADC_OFFSET_NONE;
- sConfig.Offset = 0;
- if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
- {
- Error_Handler();
- }
- }
- void MX_ADC2_Init(void)
- {
- ADC_ChannelConfTypeDef sConfig = {0};
- hadc2.Instance = ADC2;
- hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_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_EXTERNALTRIG_T6_TRGO;
- hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
- hadc2.Init.DMAContinuousRequests = ENABLE;
- hadc2.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
- hadc2.Init.OversamplingMode = DISABLE;
- if (HAL_ADC_Init(&hadc2) != HAL_OK)
- {
- Error_Handler();
- }
- sConfig.Channel = ADC_CHANNEL_1;
- sConfig.Rank = ADC_REGULAR_RANK_1;
- sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5;
- sConfig.SingleDiff = ADC_SINGLE_ENDED;
- sConfig.OffsetNumber = ADC_OFFSET_NONE;
- sConfig.Offset = 0;
- if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
- {
- Error_Handler();
- }
- }
- void MX_ADC3_Init(void)
- {
- ADC_ChannelConfTypeDef sConfig = {0};
- hadc3.Instance = ADC3;
- hadc3.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
- hadc3.Init.Resolution = ADC_RESOLUTION_12B;
- hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
- hadc3.Init.GainCompensation = 0;
- hadc3.Init.ScanConvMode = ADC_SCAN_DISABLE;
- hadc3.Init.EOCSelection = ADC_EOC_SEQ_CONV;
- hadc3.Init.LowPowerAutoWait = DISABLE;
- hadc3.Init.ContinuousConvMode = ENABLE;
- hadc3.Init.NbrOfConversion = 1;
- hadc3.Init.DiscontinuousConvMode = DISABLE;
- hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
- hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
- hadc3.Init.DMAContinuousRequests = ENABLE;
- hadc3.Init.Overrun = ADC_OVR_DATA_PRESERVED;
- hadc3.Init.OversamplingMode = DISABLE;
- if (HAL_ADC_Init(&hadc3) != HAL_OK)
- {
- Error_Handler();
- }
- sConfig.Channel = ADC_CHANNEL_5;
- sConfig.Rank = ADC_REGULAR_RANK_1;
- sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5;
- sConfig.SingleDiff = ADC_SINGLE_ENDED;
- sConfig.OffsetNumber = ADC_OFFSET_NONE;
- sConfig.Offset = 0;
- if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
- {
- Error_Handler();
- }
- }
- static uint32_t HAL_RCC_ADC12_CLK_ENABLED=0;
- void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- if(adcHandle->Instance==ADC1)
- {
- HAL_RCC_ADC12_CLK_ENABLED++;
- if(HAL_RCC_ADC12_CLK_ENABLED==1){
- __HAL_RCC_ADC12_CLK_ENABLE();
- }
- __HAL_RCC_GPIOA_CLK_ENABLE();
- GPIO_InitStruct.Pin = GPIO_PIN_1;
- GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- 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);
- }
- else if(adcHandle->Instance==ADC2)
- {
- HAL_RCC_ADC12_CLK_ENABLED++;
- if(HAL_RCC_ADC12_CLK_ENABLED==1){
- __HAL_RCC_ADC12_CLK_ENABLE();
- }
- __HAL_RCC_GPIOA_CLK_ENABLE();
- GPIO_InitStruct.Pin = GPIO_PIN_0;
- GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- hdma_adc2.Instance = DMA1_Channel2;
- hdma_adc2.Init.Request = DMA_REQUEST_ADC2;
- hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY;
- hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE;
- hdma_adc2.Init.MemInc = DMA_MINC_ENABLE;
- hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
- hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
- hdma_adc2.Init.Mode = DMA_CIRCULAR;
- hdma_adc2.Init.Priority = DMA_PRIORITY_LOW;
- if (HAL_DMA_Init(&hdma_adc2) != HAL_OK)
- {
- Error_Handler();
- }
- __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc2);
- }
- else if(adcHandle->Instance==ADC3)
- {
- __HAL_RCC_ADC345_CLK_ENABLE();
- __HAL_RCC_GPIOB_CLK_ENABLE();
- GPIO_InitStruct.Pin = GPIO_PIN_13;
- GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
- hdma_adc3.Instance = DMA1_Channel3;
- hdma_adc3.Init.Request = DMA_REQUEST_ADC3;
- hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY;
- hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE;
- hdma_adc3.Init.MemInc = DMA_MINC_ENABLE;
- hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
- hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
- hdma_adc3.Init.Mode = DMA_CIRCULAR;
- hdma_adc3.Init.Priority = DMA_PRIORITY_LOW;
- if (HAL_DMA_Init(&hdma_adc3) != HAL_OK)
- {
- Error_Handler();
- }
- __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc3);
- }
- }
- void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
- {
- if(adcHandle->Instance==ADC1)
- {
- HAL_RCC_ADC12_CLK_ENABLED--;
- if(HAL_RCC_ADC12_CLK_ENABLED==0){
- __HAL_RCC_ADC12_CLK_DISABLE();
- }
- HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1);
- HAL_DMA_DeInit(adcHandle->DMA_Handle);
- }
- else if(adcHandle->Instance==ADC2)
- {
- HAL_RCC_ADC12_CLK_ENABLED--;
- if(HAL_RCC_ADC12_CLK_ENABLED==0){
- __HAL_RCC_ADC12_CLK_DISABLE();
- }
- HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0);
- HAL_DMA_DeInit(adcHandle->DMA_Handle);
- }
- else if(adcHandle->Instance==ADC3)
- {
- __HAL_RCC_ADC345_CLK_DISABLE();
- HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13);
- HAL_DMA_DeInit(adcHandle->DMA_Handle);
- }
- }
复制代码
MAIN.C
- #include "main.h"
- #include "adc.h"
- #include "dac.h"
- #include "dma.h"
- #include "tim.h"
- #include "gpio.h"
- __IO uint32_t UserButtonStatus = 0;
- const uint16_t Sine12bit[60] = {0x07ff,0x08cb,0x0994,0x0a5a,0x0b18,0x0bce,0x0c79,0x0d18,0x0da8,0x0e29,0x0e98,0x0ef4,0x0f3e,0x0f72,0x0f92,0x0f9d,
- 0x0f92,0x0f72,0x0f3e,0x0ef4,0x0e98,0x0e29,0x0da8,0x0d18,0x0c79,0x0bce,0x0b18,0x0a5a,0x0994,0x08cb,0x07ff,0x0733,
- 0x066a,0x05a4,0x04e6,0x0430,0x0385,0x02e6,0x0256,0x01d5,0x0166,0x010a,0x00c0,0x008c,0x006c,0x0061,0x006c,0x008c,0x00c0,0x010a,0x0166,0x01d5,0x0256,0x02e6,0x0385,0x0430,0x04e6,0x05a4,0x066a,0x0733};
- uint16_t Result1[64];
- uint16_t Result2[64];
- uint16_t Result3[64];
- void SystemClock_Config(void);
- int main(void)
- {
- HAL_Init();
- SystemClock_Config();
- MX_GPIO_Init();
- MX_DMA_Init();
- MX_ADC1_Init();
- MX_TIM6_Init();
- MX_ADC2_Init();
- MX_ADC3_Init();
- MX_DAC1_Init();
- MX_TIM2_Init();
- HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
- HAL_ADCEx_Calibration_Start(&hadc2, ADC_SINGLE_ENDED);
- HAL_ADCEx_Calibration_Start(&hadc3, ADC_SINGLE_ENDED);
- HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&Result1,64);
- HAL_ADC_Start_DMA(&hadc2, (uint32_t *)&Result2,64);
- HAL_ADC_Start_DMA(&hadc3, (uint32_t *)&Result3,64);
- HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1,
- (uint32_t*)Sine12bit, 60, DAC_ALIGN_12B_R);
- HAL_TIM_Base_Start(&htim6);
- HAL_TIM_Base_Start(&htim2);
- while (1)
- {
- }
- }
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
- RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
- HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
- RCC_OscInitStruct.HSIState = RCC_HSI_ON;
- RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
- RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4;
- RCC_OscInitStruct.PLL.PLLN = 85;
- RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
- RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
- RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
- 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();
- }
- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12|RCC_PERIPHCLK_ADC345;
- PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
- PeriphClkInit.Adc345ClockSelection = RCC_ADC345CLKSOURCE_SYSCLK;
- if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
- {
- Error_Handler();
- }
- }
复制代码
变量数组Result1[64]、Result2[64]、Result3[64]保存3个ADC通道的转换结果. 如果有多个 ADC内核同时工作,
各路ADC输入端同时采样一个正弦波信号时的数据应该基本相同的。
从运行结果截图可以看出,各个数组的数据呈现明显的相位差,因此可以认为STM32G491的ADC应该是
使用同一个ADC内核,分时转换得到的。
ADC491.rar
(751.97 KB, 下载次数: 6)
|
你测试同一信号做验证是对的,但你不该将三个ADC输入并在一起。