当前位置: 首页 > news >正文

STM32-ADC实验

AD转换包括采样阶段和转换阶段。在采样阶段才对通道数据进行;在转换阶段只是将采集的数据进行转换为数字量输出,此刻通道数据变化不会改变转换结果。

实验1:单ADC单通道中断

硬件原理图

由于PC1接到电位器上,所以我们实验选择PC1引脚作为ADC接口,查询STM32数据手册得知PC1可作为ADC1的IN11(ADC1_IN11)。

USART配置

115200-8-N-1,重定向支持printf打印,勾选C库。

ADC1配置

ADC_HandleTypeDef hadc1;void MX_ADC1_Init(void)
{ADC_ChannelConfTypeDef sConfig = {0};/* Common config */hadc1.Instance 						= ADC1;hadc1.Init.ScanConvMode 			= ADC_SCAN_DISABLE;hadc1.Init.ContinuousConvMode		= ENABLE;hadc1.Init.DiscontinuousConvMode 	= DISABLE;hadc1.Init.ExternalTrigConv 		= ADC_SOFTWARE_START;hadc1.Init.DataAlign 				= ADC_DATAALIGN_RIGHT;hadc1.Init.NbrOfConversion 			= 1;if (HAL_ADC_Init(&hadc1) != HAL_OK){Error_Handler();}/* Configure Regular Channel */sConfig.Channel 					= ADC_CHANNEL_11;sConfig.Rank 						= ADC_REGULAR_RANK_1;sConfig.SamplingTime 				= ADC_SAMPLETIME_1CYCLE_5;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}HAL_ADC_Start_IT(&hadc1);
}void HAL_ADC_MspInit(ADC_HandleTypeDef *adcHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if (adcHandle->Instance == ADC1){__HAL_RCC_ADC1_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();/**ADC1 GPIO ConfigurationPC1     ------> ADC1_IN11*/GPIO_InitStruct.Pin = GPIO_PIN_1;GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);/* ADC1 interrupt Init */HAL_NVIC_SetPriority(ADC1_2_IRQn, 0, 0);HAL_NVIC_EnableIRQ(ADC1_2_IRQn);}
}void HAL_ADC_MspDeInit(ADC_HandleTypeDef *adcHandle)
{if (adcHandle->Instance == ADC1){__HAL_RCC_ADC1_CLK_DISABLE();/**ADC1 GPIO ConfigurationPC1     ------> ADC1_IN11*/HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1);/* ADC1 interrupt Deinit */HAL_NVIC_DisableIRQ(ADC1_2_IRQn);}
}
/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};...PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK){Error_Handler();}
}

初始化结构体的参数

ScanConvMode:扫描转换模式

指定转换是扫描模式(多通道模式)还是单个转换(单通道模式)。ADC_SCAN_DISABLE 或 ADC_SCAN_ENABLE。

在扫描模式下,扫描一组选定的通道,它们将会被依次转换,由序列寄存器ADC_SQRx或ADC_JSQRx选中的通道被转换。如果分别设置了EOCIE位或JEOCIE位,只在最后一个通道转换完后才会产生EOC或JEOC中断。

ContinuousConvMode:连续转换模式

ADC转换可以在一次转换后停止,然后再次触发后进行下一次转换(一般配置);

也可以是持续不断地进行转换。

通过ADC_CR2:CONT位决定。

ExternalTrigConv:外部触发方式

根据项目需求配置触发源。实际上一般使用软件自动触发。

测试环节

__IO uint32_t ADC_ConvertedValue;
float ADC_Vol; /*** @brief  转换完成中断回调函数(非阻塞模式)* @param  AdcHandle : ADC句柄* @retval 无*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *AdcHandle)
{ADC_ConvertedValue = HAL_ADC_GetValue(AdcHandle);
}void test(void)
{while (1){HAL_Delay(1000);ADC_Vol =(float) ADC_ConvertedValue*(3.3/4096); // 读取转换的AD值printf("\r\n The current AD value = %f V \r\n", ADC_Vol);  }
}

实验现象

旋钮电位器,电压输入有变化。将PC1接到VCC,输出3.3V。

实验2:单ADC单通道DMA

硬件原理图和USART配置

看实验1

ADC1配置

ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;__IO uint32_t ADC_ConvertedValue;void MX_ADC1_Init(void)
{ADC_ChannelConfTypeDef sConfig = {0};/** Common config*/hadc1.Instance 						= ADC1;hadc1.Init.ScanConvMode 			= ADC_SCAN_DISABLE;hadc1.Init.ContinuousConvMode 		= ENABLE;hadc1.Init.DiscontinuousConvMode 	= DISABLE;hadc1.Init.ExternalTrigConv 		= ADC_SOFTWARE_START;hadc1.Init.DataAlign 				= ADC_DATAALIGN_RIGHT;hadc1.Init.NbrOfConversion 			= 1;if (HAL_ADC_Init(&hadc1) != HAL_OK){Error_Handler();}/** Configure Regular Channel*/sConfig.Channel 		= ADC_CHANNEL_11;sConfig.Rank 			= ADC_REGULAR_RANK_1;sConfig.SamplingTime 	= ADC_SAMPLETIME_1CYCLE_5;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&ADC_ConvertedValue, 1);
}void HAL_ADC_MspInit(ADC_HandleTypeDef *adcHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if (adcHandle->Instance == ADC1){__HAL_RCC_ADC1_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();/**ADC1 GPIO ConfigurationPC1     ------> ADC1_IN11*/GPIO_InitStruct.Pin 	= GPIO_PIN_1;GPIO_InitStruct.Mode 	= GPIO_MODE_ANALOG;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);/* ADC1 DMA Init *//* ADC1 Init */hdma_adc1.Instance 					= DMA1_Channel1;hdma_adc1.Init.Direction 			= DMA_PERIPH_TO_MEMORY;hdma_adc1.Init.PeriphInc 			= DMA_PINC_DISABLE;hdma_adc1.Init.MemInc 				= DMA_MINC_DISABLE;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_MEDIUM;if (HAL_DMA_Init(&hdma_adc1) != HAL_OK){Error_Handler();}__HAL_LINKDMA(adcHandle, DMA_Handle, hdma_adc1);}
}void HAL_ADC_MspDeInit(ADC_HandleTypeDef *adcHandle)
{if (adcHandle->Instance == ADC1){__HAL_RCC_ADC1_CLK_DISABLE();/**ADC1 GPIO ConfigurationPC1     ------> ADC1_IN11*/HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1);/* ADC1 DMA DeInit */HAL_DMA_DeInit(adcHandle->DMA_Handle);}
}
/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};...PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK){Error_Handler();}
}

测试环节

extern __IO uint32_t ADC_ConvertedValue;
float ADC_Vol; void test(void)
{while (1){HAL_Delay(1000);ADC_Vol =(float) ADC_ConvertedValue*(3.3/4096); // 读取转换的AD值printf("\r\n The current AD value = %f V \r\n", ADC_Vol);  }
}

实验现象

旋钮电位器,电压输入有变化。将PC1接到VCC,输出3.3V。

实验3:单ADC多通道DMA

硬件原理图和USART配置

对硬件原理图的PC0、PC1、PC2、PC3、PC4、PC5进行ADC配置,具体看实验1。

ADC1配置

____IO uint16_t ADC_ConvertedValue[6] = {0};ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;void MX_ADC1_Init(void)
{ADC_ChannelConfTypeDef sConfig = {0};/** Common config*/hadc1.Instance 						= ADC1;hadc1.Init.ScanConvMode 			= ADC_SCAN_ENABLE;hadc1.Init.ContinuousConvMode 		= ENABLE;hadc1.Init.DiscontinuousConvMode 	= DISABLE;hadc1.Init.ExternalTrigConv 		= ADC_SOFTWARE_START;hadc1.Init.DataAlign 				= ADC_DATAALIGN_RIGHT;hadc1.Init.NbrOfConversion 			= 6;if (HAL_ADC_Init(&hadc1) != HAL_OK){Error_Handler();}/** Configure Regular Channel*/sConfig.Channel 		= ADC_CHANNEL_10;sConfig.Rank 			= ADC_REGULAR_RANK_1;sConfig.SamplingTime 	= ADC_SAMPLETIME_1CYCLE_5;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}sConfig.Channel = ADC_CHANNEL_11;sConfig.Rank 	= ADC_REGULAR_RANK_2;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}sConfig.Channel = ADC_CHANNEL_12;sConfig.Rank = ADC_REGULAR_RANK_3;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}sConfig.Channel = ADC_CHANNEL_13;sConfig.Rank 	= ADC_REGULAR_RANK_4;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}sConfig.Channel = ADC_CHANNEL_14;sConfig.Rank = ADC_REGULAR_RANK_5;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}sConfig.Channel = ADC_CHANNEL_15;sConfig.Rank = ADC_REGULAR_RANK_6;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&ADC_ConvertedValue, 6);
}void HAL_ADC_MspInit(ADC_HandleTypeDef *adcHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if (adcHandle->Instance == ADC1){__HAL_RCC_ADC1_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();/**ADC1 GPIO ConfigurationPC0     ------> ADC1_IN10PC1     ------> ADC1_IN11PC2     ------> ADC1_IN12PC3     ------> ADC1_IN13PC4     ------> ADC1_IN14PC5     ------> ADC1_IN15*/GPIO_InitStruct.Pin 	= GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;GPIO_InitStruct.Mode 	= GPIO_MODE_ANALOG;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);/* ADC1 DMA Init *//* ADC1 Init */hdma_adc1.Instance 					= DMA1_Channel1;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_MEDIUM;if (HAL_DMA_Init(&hdma_adc1) != HAL_OK){Error_Handler();}__HAL_LINKDMA(adcHandle, DMA_Handle, hdma_adc1);}
}void HAL_ADC_MspDeInit(ADC_HandleTypeDef *adcHandle)
{if (adcHandle->Instance == ADC1){__HAL_RCC_ADC1_CLK_DISABLE();/**ADC1 GPIO ConfigurationPC0     ------> ADC1_IN10PC1     ------> ADC1_IN11PC2     ------> ADC1_IN12PC3     ------> ADC1_IN13PC4     ------> ADC1_IN14PC5     ------> ADC1_IN15*/HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);/* ADC1 DMA DeInit */HAL_DMA_DeInit(adcHandle->DMA_Handle);}
}
/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};...PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK){Error_Handler();}
}

测试环节

extern __IO uint16_t ADC_ConvertedValue[6];
float ADC_Vol[6];void test(void)
{while(1){HAL_Delay(1000);ADC_Vol[0] =(float) ADC_ConvertedValue[0]/4096*(float)3.3; // 读取转换的AD值ADC_Vol[1] =(float) ADC_ConvertedValue[1]/4096*(float)3.3; // 读取转换的AD值ADC_Vol[2] =(float) ADC_ConvertedValue[2]/4096*(float)3.3; // 读取转换的AD值ADC_Vol[3] =(float) ADC_ConvertedValue[3]/4096*(float)3.3; // 读取转换的AD值ADC_Vol[4] =(float) ADC_ConvertedValue[4]/4096*(float)3.3; // 读取转换的AD值ADC_Vol[5] =(float) ADC_ConvertedValue[5]/4096*(float)3.3; // 读取转换的AD值printf("ADC_CHANNEL10 value = %f V \r\n", ADC_Vol[0]);printf("ADC_CHANNEL11 value = %f V \r\n", ADC_Vol[1]);printf("ADC_CHANNEL12 value = %f V \r\n", ADC_Vol[2]);printf("ADC_CHANNEL13 value = %f V \r\n", ADC_Vol[3]);printf("ADC_CHANNEL14 value = %f V \r\n", ADC_Vol[4]);printf("ADC_CHANNEL15 value = %f V \r\n", ADC_Vol[5]);}
}

实验现象

输出引脚悬空状态,依次将各引脚接到VCC,依次输出3.3V。

实验4:双ADC单通道慢速交叉采集

硬件原理图和USART配置

看实验1

快速交叉模式

该模式下只能在规则通道组(通常一个通道)上启动。外部触发源来自于ADC1的规则通道复用器。外部触发后:

ADC2立即启动。

ADC1延时7个ADC_CLK时钟周期后启动。

在ADC1(如果通过EOCIE位使能)产生EOC中断后,生成一个32位DMA传输请求(如果设置了DMA位),该请求将 ADC1_DR 寄存器传输到SRAM(ADC2转换的数据在高16位,ADC1转换的数据在低16位)。

允许的最大采样周期 < 7个ADC_CLK时钟周期,以避免在ADC1和ADC2转换相同通道的情况下采样相位转换重叠。

如果在ADC1和ADC2上都设置了CONT位,则两个ADC所选的规则通道将连续转换。

慢速交叉模式

该模式下只能在规则通道组(只有一个通道)上启动。外部触发源来自于ADC1的规则通道复用器。外部触发后:

ADC2立即启动。

ADC1延时14个ADC_CLK时钟周期后启动。

ADC2在第二次延时14个ADC_CLK时钟周期后启动。依次类推,交叉采集

在ADC1(如果通过EOCIE位使能)产生EOC中断后,生成一个32位DMA传输请求(如果设置了DMA位),该请求将 ADC1_DR 寄存器传输到SRAM(ADC2转换的数据在高16位,ADC1转换的数据在低16位)。

允许的最大采样周期 < 14个ADC_CLK时钟周期,以避免与下一次转换重叠。

CONT位不能在模式中设置,因为它不断地转换所选的规则通道。

应用程序必须确保在启用交叉模式时不会发生注入通道的外部触发器。

ADC配置

ADC_HandleTypeDef hadc1;
ADC_HandleTypeDef hadc2;
DMA_HandleTypeDef hdma_adc1;void MX_ADC1_Init(void)
{ADC_MultiModeTypeDef multimode = {0};ADC_ChannelConfTypeDef sConfig = {0};/** Common config*/hadc1.Instance 						= ADC1;hadc1.Init.ScanConvMode 			= ADC_SCAN_DISABLE;hadc1.Init.ContinuousConvMode 		= ENABLE;hadc1.Init.DiscontinuousConvMode 	= DISABLE;hadc1.Init.ExternalTrigConv 		= ADC_SOFTWARE_START;hadc1.Init.DataAlign 				= ADC_DATAALIGN_RIGHT;hadc1.Init.NbrOfConversion 			= 1;if (HAL_ADC_Init(&hadc1) != HAL_OK){Error_Handler();}/** Configure the ADC multi-mode*/multimode.Mode = ADC_DUALMODE_INTERLSLOW;if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK){Error_Handler();}/** Configure Regular Channel*/sConfig.Channel 		= ADC_CHANNEL_11;sConfig.Rank 			= ADC_REGULAR_RANK_1;sConfig.SamplingTime 	= ADC_SAMPLETIME_1CYCLE_5;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}
}void MX_ADC2_Init(void)
{ADC_ChannelConfTypeDef sConfig = {0};/** Common config*/hadc2.Instance 						= ADC2;hadc2.Init.ScanConvMode 			= ADC_SCAN_DISABLE;hadc2.Init.ContinuousConvMode 		= ENABLE;hadc2.Init.DiscontinuousConvMode 	= DISABLE;hadc2.Init.ExternalTrigConv 		= ADC_SOFTWARE_START;hadc2.Init.DataAlign 				= ADC_DATAALIGN_RIGHT;hadc2.Init.NbrOfConversion 			= 1;if (HAL_ADC_Init(&hadc2) != HAL_OK){Error_Handler();}/** Configure Regular Channel*/sConfig.Channel 		= ADC_CHANNEL_11;sConfig.Rank 			= ADC_REGULAR_RANK_1;sConfig.SamplingTime 	= ADC_SAMPLETIME_1CYCLE_5;if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK){Error_Handler();}
}void HAL_ADC_MspInit(ADC_HandleTypeDef *adcHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if (adcHandle->Instance == ADC1){__HAL_RCC_ADC1_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();/**ADC1 GPIO ConfigurationPC1     ------> ADC1_IN11*/GPIO_InitStruct.Pin 	= GPIO_PIN_1;GPIO_InitStruct.Mode 	= GPIO_MODE_ANALOG;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);/* ADC1 DMA Init *//* ADC1 Init */hdma_adc1.Instance 					= DMA1_Channel1;hdma_adc1.Init.Direction 			= DMA_PERIPH_TO_MEMORY;hdma_adc1.Init.PeriphInc 			= DMA_PINC_DISABLE;hdma_adc1.Init.MemInc 				= DMA_MINC_DISABLE;hdma_adc1.Init.PeriphDataAlignment 	= DMA_PDATAALIGN_WORD;hdma_adc1.Init.MemDataAlignment 	= DMA_MDATAALIGN_WORD;hdma_adc1.Init.Mode 				= DMA_CIRCULAR;hdma_adc1.Init.Priority 			= DMA_PRIORITY_HIGH;if (HAL_DMA_Init(&hdma_adc1) != HAL_OK){Error_Handler();}__HAL_LINKDMA(adcHandle, DMA_Handle, hdma_adc1);}else if (adcHandle->Instance == ADC2){__HAL_RCC_ADC2_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();/**ADC2 GPIO ConfigurationPC1     ------> ADC2_IN11*/GPIO_InitStruct.Pin 	= GPIO_PIN_1;GPIO_InitStruct.Mode 	= GPIO_MODE_ANALOG;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);}
}void HAL_ADC_MspDeInit(ADC_HandleTypeDef *adcHandle)
{if (adcHandle->Instance == ADC1){__HAL_RCC_ADC1_CLK_DISABLE();/**ADC1 GPIO ConfigurationPC1     ------> ADC1_IN11*/HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1);/* ADC1 DMA DeInit */HAL_DMA_DeInit(adcHandle->DMA_Handle);}else if (adcHandle->Instance == ADC2){/* Peripheral clock disable */__HAL_RCC_ADC2_CLK_DISABLE();/**ADC2 GPIO ConfigurationPC1     ------> ADC2_IN11*/HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1);}
}
/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};...PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK){Error_Handler();}
}

测试环节

float ADC_ConvertedValueLocal[2];
uint32_t ADC_ConvertedValue;int test(void)
{初始化HAL_ADCEx_Calibration_Start(&hadc1);HAL_ADCEx_Calibration_Start(&hadc2);/* 启动AD转换并使能DMA传输和中断 */HAL_ADC_Start(&hadc2);HAL_ADCEx_MultiModeStart_DMA(&hadc1, &ADC_ConvertedValue, sizeof(ADC_ConvertedValue));while (1){HAL_Delay(1000);// ADC1的值ADC_ConvertedValueLocal[0] = (float)(ADC_ConvertedValue & 0xFFF) * 3.3 / 4096; // ADC2的值ADC_ConvertedValueLocal[1] = (float)((ADC_ConvertedValue>>16) & 0xFFF) * 3.3 / 4096; 	printf("ADC1 电压值 = %f V \r\n", ADC_ConvertedValueLocal[0]);    printf("ADC2 电压值 = %f V \r\n", ADC_ConvertedValueLocal[1]); }
}

实验现象

同实验1

实验5:双ADC多通道同步规则采集

硬件原理图和USART配置

对硬件原理图的PC0、PC1进行ADC配置,具体看实验1。

同步规则模式

该模式在规则通道组上启动。外部触发源来自于ADC1的规则组复用器(由ADC1_CR2:EXTSEL[2:0]位决定)。为ADC2提供一个同步触发器。

不要在两个ADC上转换同一通道(转换同一通道时,两个ADC没有重叠采样时间)。

在ADC1或ADC2上的转换事件结束时:

生成一个32位的DMA传输请求(如果设置了DMA位),该请求将 ADC1_DR 寄存器传输到SRAM(ADC2转换的数据在高16位,ADC1转换的数据在低16位)。

当ADC1/ADC2规则通道全部转换结束时,生成EOC中断(如果在两个ADC接口之一上启用)。

在同步规则模式下,应该为两个通道配置完全相同的采样时间,这两个通道将被ADC1和ADC2同时采样。

ADC配置

ADC_HandleTypeDef hadc1;
ADC_HandleTypeDef hadc2;
DMA_HandleTypeDef hdma_adc1;void MX_ADC1_Init(void)
{ADC_MultiModeTypeDef multimode = {0};ADC_ChannelConfTypeDef sConfig = {0};/** Common config*/hadc1.Instance 						= ADC1;hadc1.Init.ScanConvMode 			= ADC_SCAN_DISABLE;hadc1.Init.ContinuousConvMode 		= ENABLE;hadc1.Init.DiscontinuousConvMode 	= DISABLE;hadc1.Init.ExternalTrigConv 		= ADC_SOFTWARE_START;hadc1.Init.DataAlign 				= ADC_DATAALIGN_RIGHT;hadc1.Init.NbrOfConversion 			= 1;if (HAL_ADC_Init(&hadc1) != HAL_OK){Error_Handler();}/** Configure the ADC multi-mode*/multimode.Mode = ADC_DUALMODE_REGSIMULT;if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK){Error_Handler();}/** Configure Regular Channel*/sConfig.Channel 		= ADC_CHANNEL_11;sConfig.Rank 			= ADC_REGULAR_RANK_1;sConfig.SamplingTime 	= ADC_SAMPLETIME_1CYCLE_5;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}
}void MX_ADC2_Init(void)
{ADC_ChannelConfTypeDef sConfig = {0};/** Common config*/hadc2.Instance 						= ADC2;hadc2.Init.ScanConvMode 			= ADC_SCAN_DISABLE;hadc2.Init.ContinuousConvMode 		= ENABLE;hadc2.Init.DiscontinuousConvMode 	= DISABLE;hadc2.Init.ExternalTrigConv 		= ADC_SOFTWARE_START;hadc2.Init.DataAlign 				= ADC_DATAALIGN_RIGHT;hadc2.Init.NbrOfConversion 			= 1;if (HAL_ADC_Init(&hadc2) != HAL_OK){Error_Handler();}/** Configure Regular Channel*/sConfig.Channel 		= ADC_CHANNEL_10;sConfig.Rank 			= ADC_REGULAR_RANK_1;sConfig.SamplingTime 	= ADC_SAMPLETIME_1CYCLE_5;if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK){Error_Handler();}
}void HAL_ADC_MspInit(ADC_HandleTypeDef *adcHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if (adcHandle->Instance == ADC1){        __HAL_RCC_ADC1_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();/**ADC1 GPIO ConfigurationPC1     ------> ADC1_IN11*/GPIO_InitStruct.Pin 	= GPIO_PIN_1;GPIO_InitStruct.Mode 	= GPIO_MODE_ANALOG;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);/* ADC1 DMA Init *//* ADC1 Init */hdma_adc1.Instance 					= DMA1_Channel1;hdma_adc1.Init.Direction 			= DMA_PERIPH_TO_MEMORY;hdma_adc1.Init.PeriphInc 			= DMA_PINC_DISABLE;hdma_adc1.Init.MemInc 				= DMA_MINC_DISABLE;hdma_adc1.Init.PeriphDataAlignment 	= DMA_PDATAALIGN_WORD;hdma_adc1.Init.MemDataAlignment 	= DMA_MDATAALIGN_WORD;hdma_adc1.Init.Mode 				= DMA_CIRCULAR;hdma_adc1.Init.Priority 			= DMA_PRIORITY_HIGH;if (HAL_DMA_Init(&hdma_adc1) != HAL_OK){Error_Handler();}__HAL_LINKDMA(adcHandle, DMA_Handle, hdma_adc1);}else if (adcHandle->Instance == ADC2){__HAL_RCC_ADC2_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();/**ADC2 GPIO ConfigurationPC0     ------> ADC2_IN10*/GPIO_InitStruct.Pin 	= GPIO_PIN_0;GPIO_InitStruct.Mode 	= GPIO_MODE_ANALOG;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);}
}void HAL_ADC_MspDeInit(ADC_HandleTypeDef *adcHandle)
{if (adcHandle->Instance == ADC1){__HAL_RCC_ADC1_CLK_DISABLE();/**ADC1 GPIO ConfigurationPC1     ------> ADC1_IN11*/HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1);/* ADC1 DMA DeInit */HAL_DMA_DeInit(adcHandle->DMA_Handle);}else if (adcHandle->Instance == ADC2){__HAL_RCC_ADC2_CLK_DISABLE();/**ADC2 GPIO ConfigurationPC0     ------> ADC2_IN10*/HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0);}
}
/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};...PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK){Error_Handler();}
}

测试环节

float ADC_ConvertedValueLocal[2];
uint32_t ADC_ConvertedValue;int test(void)
{初始化HAL_ADCEx_Calibration_Start(&hadc1);HAL_ADCEx_Calibration_Start(&hadc2);/* 启动AD转换并使能DMA传输和中断 */HAL_ADC_Start(&hadc2);HAL_ADCEx_MultiModeStart_DMA(&hadc1, &ADC_ConvertedValue, sizeof(ADC_ConvertedValue));while (1){HAL_Delay(1000);// ADC1的值ADC_ConvertedValueLocal[0] = (float)(ADC_ConvertedValue & 0xFFF) * 3.3 / 4096; // ADC2的值ADC_ConvertedValueLocal[1] = (float)((ADC_ConvertedValue>>16) & 0xFFF) * 3.3 / 4096; 	printf("ADC1 电压值 = %f V \r\n", ADC_ConvertedValueLocal[0]);    printf("ADC2 电压值 = %f V \r\n", ADC_ConvertedValueLocal[1]); }
}

实验现象

依次将PC0、PC1接到VCC,ADC依次输出3.3V。

实验6:读取芯片温度

http://www.lryc.cn/news/205069.html

相关文章:

  • 05、Python -- 爬取ts文件格式视频思路
  • 【QT】其他常用控件2
  • django报错--Not Found The requested URL was not found on the server.
  • VLOOKUP函数的使用方法
  • 关于前端如何下载后端接口返回content-type为application/octet-stream的文件
  • 报错:SSL routines:ssl3_get_record:wrong version number
  • Flask后端开发(一)-基础知识和前期准备
  • 基于SSM的幼儿园管理系统
  • 互联网Java工程师面试题·Spring篇·第三弹
  • 前端(二十三)——轮询和长轮询
  • uniapp把文件中的内复制到另一个文件中
  • 什么是蓝桥杯?什么是蓝桥STEMA考试?
  • 快递排序Java
  • Spark简单回顾
  • DDD与微服务的千丝万缕
  • S32K324 UDS Bootloader开发-需求篇
  • 【前端设计模式】之调停者模式(中介者模式)
  • 【MySQL架构篇】SQL执行流程与缓冲池
  • [support2022@cock.li].faust、[tsai.shen@mailfence.com].faust勒索病毒数据怎么处理|数据解密恢复
  • 力扣学习笔记——49. 字母异位词分组
  • 五、Qt中的常用类
  • CentOS 7.9.2009 数据盘挂载
  • cv::solvePnP使用方法及注意点详解(OpenCV/C++)
  • DevOps持续集成-Jenkins(4)
  • 【数据仓库-零】数据仓库知识体系 ing
  • css3 3D 转换 技巧详细解析与代码实例
  • [Unity]给场景中的3D字体TextMesh增加描边方案一
  • TDengine(taos)数据库导出历史数据
  • 算法进修Day-37
  • 服务器之日常整活