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勒索病毒的运作方…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...