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勒索病毒的运作方…...
干货 | SpringBoot 全局异常拦截到底怎么用(附完整可复制代码)
一、前言 开发接口最烦啥?代码一报错,前端直接抛一堆 500 红码、后台堆栈日志满天飞、用户看页面一脸懵。要是每个接口都手动 try-catch,代码又臭又长、冗余到想吐。 Spring 全局异常拦截就是用来根治这个问题的:一次配置、全局…...
XSS之Flash弹窗钓鱼
0x1 前言 哈喽,师傅们好! 这次打算给师弟们分享的是XSS之Flash弹窗钓鱼和文件上传getshell各种姿势的内容,然后先是给小白师傅们简单介绍下XSS漏洞和文件上传漏洞。然后后面给师傅们简单演示了XSS之Flash弹窗钓鱼,然后后面很详细…...
yolov8 mobilev3轻量级 注意力机制感兴趣的话点“我想要”和我私聊吧~
yolov8 mobilev3轻量级 注意力机制 感兴趣的话点“我想要”和我私聊吧~...
知识竞赛在党建教育中的创新应用:激活学习动能,赋能组织活力
引言:党建教育需要新载体在新时代背景下,党建教育工作面临着党员群体年轻化、信息获取渠道多元化、学习需求个性化等新挑战。传统的单向宣讲、文件学习模式有时难以充分激发党员的学习热情和深度参与。因此,探索形式新颖、互动性强、富有时代…...
配置Claude Code遇到Unable to connect to Anthropic services Failed to connect to api.anthropic.cOm: ERR_B
在PowerShell里输入[Environment]::SetEnvironmentVariable("HTTP_PROXY", "http://127.0.0.1:xxxxx", "User")[Environment]::SetEnvironmentVariable("HTTPS_PROXY", "http://127.0.0.1:xxxxx", "User")[Enviro…...
革新性量化交易平台:基于Backtrader的高效策略回测工具实现方法
革新性量化交易平台:基于Backtrader的高效策略回测工具实现方法 【免费下载链接】backtrader-pyqt-ui 项目地址: https://gitcode.com/gh_mirrors/bac/backtrader-pyqt-ui Backtrader可视化平台是一款融合PyQt界面框架与finplot图表库的革新性量化交易回测工…...
FullControl GCode Designer:重新定义3D打印设计的参数化控制工具
FullControl GCode Designer:重新定义3D打印设计的参数化控制工具 【免费下载链接】FullControl-GCode-Designer Software for designing GCODE for 3D printing 项目地址: https://gitcode.com/gh_mirrors/fu/FullControl-GCode-Designer 突破传统3D打印限制…...
实战指南:使用快马平台开发基于codex的vscode智能sql查询助手
实战指南:使用快马平台开发基于Codex的VSCode智能SQL查询助手 最近在开发过程中,我发现编写和优化SQL查询是个挺费时间的事情。特别是当业务逻辑复杂时,经常要反复调试语法和性能问题。于是我想,能不能利用AI来辅助这个流程&…...
3分钟掌握抖音智能批量下载:全流程自动化解决方案
3分钟掌握抖音智能批量下载:全流程自动化解决方案 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. …...
实战应用:利用快马平台模拟鸿蒙pc版与手机的笔记跨设备同步功能
最近在研究鸿蒙系统的跨设备协同功能,特别是PC端和手机端之间的数据同步场景。作为一个开发者,我很好奇这种分布式能力在实际项目中如何落地。于是我用InsCode(快马)平台快速搭建了一个模拟原型,下面分享下实现思路和过程。 项目整体设计 这个…...
