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:读取芯片温度
相关文章:
STM32-ADC实验
AD转换包括采样阶段和转换阶段。在采样阶段才对通道数据进行;在转换阶段只是将采集的数据进行转换为数字量输出,此刻通道数据变化不会改变转换结果。 实验1:单ADC单通道中断 硬件原理图 由于PC1接到电位器上,所以我们实验选择PC1…...
05、Python -- 爬取ts文件格式视频思路
目录 第一步:爬取一段5秒视频找url代码结果 第二步:下载整个视频的所有片段代码:结果: 第三步:合成视频安装模块代码:结果 简洁代码代码:结果: 最终代码简洁前代码简洁后代码 思路&a…...
【QT】其他常用控件2
新建项目 lineEdit 什么都不显示(linux password) password textEdit和plainTextEdit spinBox和doubleSpinBox timeEdit、dateEdit、dateTimeEdit label 显示图案,导入资源:【QT】资源文件导入_复制其他项目中的文件到qt项目中_St…...
django报错--Not Found The requested URL was not found on the server.
这个问题通常是由于服务器配置或代码错误导致的。以下是解决这个问题的一些建议和步骤: 首先,请确保你的URL拼写正确。确认URL中的路径和文件名都是正确的,并且没有任何拼写错误。如果你是从浏览器中复制粘贴URL,请确保没有任何额…...
VLOOKUP函数的使用方法
VLOOKUP是一个查找函数,给定一个查找的目标,它就能从指定的查找区域中查找返回想要查找到的值。它的基本语法为: VLOOKUP(查找目标,查找范围,返回值的列数,精确OR模糊查找)下面以一个实例来介绍…...
关于前端如何下载后端接口返回content-type为application/octet-stream的文件
关于前端如何下载后端接口返回response-type为application/octet-stream的文件 问题描述 后端接口定义为直接返回一个文件,如果带认证信息可以直接通过浏览器url下载,但是接口需要传headers认证信息,url上又不支持传相关信息 解决 前端…...
报错:SSL routines:ssl3_get_record:wrong version number
一、问题描述 前后端联调的时候,连接后端本地服务器,接口一直pending调不通,控制台还报以下错误: 立马随手搜索了一下解决方案,但是emmm,不符合前端的实际情况: 二、解决方法: 实际…...
Flask后端开发(一)-基础知识和前期准备
目录 1.背景介绍1.1. 项目背景1.2. 项目难点1.3. 项目环境 2. flask后端开发实现的功能3. flask部署和前后端对接3.1. flask运行配置和服务器部署3.2. flask前后端传参 4. 后端测试工具4.1. 工具介绍4.2. 工具使用 后记 1.背景介绍 1.1. 项目背景 就是前几个月临时接手了一个…...
基于SSM的幼儿园管理系统
基于SSM的幼儿园管理系统的设计与实现~ 开发语言:Java数据库:MySQL技术:SpringSpringMVCMyBatis工具:IDEA/Ecilpse、Navicat、Maven 系统展示 登录界面 管理员界面 摘要 基于SSM(Spring、Spring MVC、MyBatis&#…...
互联网Java工程师面试题·Spring篇·第三弹
目录 编辑 4、注解 4.1、什么是基于注解的容器配置 4.2、如何在 spring 中启动注解装配? 4.3、Component, Controller, Repository,Service 有何区别? 4.4、Required 注解有什么用? 4.5、Autowired 注解有什么用? 4.6、…...
前端(二十三)——轮询和长轮询
😫博主:小猫娃来啦 😫文章核心:实现客户端与服务器实时通信的技术手段 文章目录 前言轮询技术轮询的概念轮询的实现原理轮询的优缺点轮询的使用场景 长轮询技术长轮询的概念长轮询的实现原理长轮询的优缺点长轮询的使用场景 轮询与…...
uniapp把文件中的内复制到另一个文件中
使用的是Html 5的plus.io.resolveLocalFileSystemURL方法,文档:HTML5 API Reference var soursePath file:///storage/emulated/0/a/;//用于读取var removePath file:///storage/emulated/0/w/;//用于移除w这个文件夹var targetPath file:///storage/…...
什么是蓝桥杯?什么是蓝桥STEMA考试?
第十五届蓝桥大赛赛事安排? STEMA考试11月(考试时间11月26日) STEMA考试1月(2024年1月) STEMA考试3月(2024年3月) 第十五届蓝桥杯省赛(2024年4月待定) 第十五届蓝桥杯国赛(2024年5月待定) 注:以上时间具体以组委会官方发布为准。 01.蓝桥杯 蓝桥杯全国软件和…...
快递排序Java
快速排序是在工具类常用的排序算法,快速排序的思想主要是选定一个基准元素,然后找到基准元素的位置,然后再分别排序他左边的和他右边的,快速排序是不稳定的,时间复杂度位Nlog(N),最极端的情况就是一个反向排好顺序的数组ÿ…...
Spark简单回顾
星光下的赶路人star的个人主页 大鹏一日同风起,扶摇直上九万里 文章目录 1、Spark1.1 Spark入门1.1.1 Spark部署模式1.1.2 常用端口 1.2 SparkCore1.2.1 RDD不可变和五大属性1.2.2 RDD的弹性1.2.3 cache和Checkpoint的区别1.2.4 算子 1.3 SparkSQL1.4 内核1.4.1提交…...
DDD与微服务的千丝万缕
一、软件设计发展过程二、什么是DDD?2.1 战略设计2.2 战术设计2.3 名词扫盲1. 领域和子域2. 核心域、通用域和支撑域3. 通用语言4. 限界上下文5. 实体和值对象6. 聚合和聚合根 2.4 事件风暴2.5 领域事件 三、DDD与微服务3.1 DDD与微服务的关系3.2 基于DDD进行微服务…...
S32K324 UDS Bootloader开发-需求篇
文章目录 前言内存分配UDS诊断协议需求CAN ID及时间参数UDS诊断服务Bootloader诊断服务APP诊断服务 DID22服务的DID:2E服务的DID:Routine Control DID: 刷写流程预编程主编程后编程 总结 前言 之前做过一个STM32的UDS Bootloader,协议栈主要是NXP官网下…...
【前端设计模式】之调停者模式(中介者模式)
调停者模式是一种行为设计模式,它通过引入一个调停者对象来集中处理一组对象之间的交互。调停者模式的目标是减少对象之间的直接通信,从而降低耦合度,并且使代码更易于维护和扩展。 调停者模式特性 将对象之间的通信集中在一个调停者对象中…...
【MySQL架构篇】SQL执行流程与缓冲池
文章目录 1. SQL执行流程2. 数据库缓冲池(Buffer Pool)2.1 缓冲池概述2.2 缓冲池如何读取数据2.3 查看和设置缓冲池的大小2.4 多个Buffer Pool实例2.5 引申问题 1. SQL执行流程 查询缓存:因为查询效率往往不高,所以在MySQL8.0之后就抛弃了这个功能解析器…...
[support2022@cock.li].faust、[tsai.shen@mailfence.com].faust勒索病毒数据怎么处理|数据解密恢复
引言: 威胁网络安全的恶意软件不断涌现,而[support2022cock.li].faust勒索病毒则是其中的一员。这个网络黑暗角落的新星,以其数据绑架的方式,一度成为数据安全的威胁焦点。本文将探究[support2022cock.li].faust勒索病毒的运作方…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
