一、背景介绍
stm32G474VET6含有5个12bit分辨率的ADC,可以采集单端或差分模拟信号。联合DMA使用,可以有效降低系统资源占用。
二、STM32CubeMX配置
第一步:选择时钟来源
第二步:选择ADC3的通道1至通道4,10通道,14通道为单端输入信号
第三步:设置ADC参数,ADC设置为12位分辨率,数据右对齐,连续转换模式使能、扫描模式使能、数据循环覆盖
第四步:配置每排对应的通道、采样时间
第五步:配置DMA参数,循环采集,数据宽度为Half Word,DMA的传输方向为从Peripheral to Memory
第六步:开启DMA全局中断,并配置优先级。优先级需要再System Core中的NVIC中修改
第七步:根据自身的需求修改时钟树,配置ADC的时钟。注意:ADC的最大工作频率是有限制的
第八步:生成代码,开启ADC的采集。STM32cubmx只是对外设进行了初始化。
/** Common config
*/
hadc3.Instance = ADC3;
hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;
hadc3.Init.Resolution = ADC_RESOLUTION_12B;
hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc3.Init.GainCompensation = 0;
hadc3.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc3.Init.LowPowerAutoWait = DISABLE;
hadc3.Init.ContinuousConvMode = ENABLE;
hadc3.Init.NbrOfConversion = 6;
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_OVERWRITTEN;
hadc3.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc3) != HAL_OK)
{
Error_Handler();
}
/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc3, &multimode) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
{
Error_Handler();
}
DMA的参数设置
/* ADC3 DMA Init */
/* ADC3 Init */
hdma_adc3.Instance = DMA1_Channel1;
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_MEDIUM;
if (HAL_DMA_Init(&hdma_adc3) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc3);//
第八步:ADC进行刻度,然后开启ADC和DMA进行采集, 6个通道,每个通道采集10个数方便滤波。
/* Private user code ---------------------------------------------------------*/
uint16_t adc_value[60];
uint32_t adc_sum[6];
float adc_flit[6];
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC3_Init();
/* USER CODE BEGIN 2 */
HAL_ADCEx_Calibration_Start(&hadc3, ADC_SINGLE_ENDED); /* 以单端模式运行ADC校准 */
HAL_ADC_Start_DMA(&hadc3, (uint32_t *)adc_value, 60); //开启采集
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
for(int j=0;j<6;j++){
for(int i=0;i<10;i++){
adc_sum[j]+=adc_value[6*i+j];
}
}
for(int j=0;j<6;j++){
adc_flit[j]=(3300*adc_sum[j])/4096/10;//求平均值然后换算采集的电压值
adc_sum[j]=0;
}
/* USER CODE END WHILE */
HAL_Delay(5);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
第九步:把编译完的程序下入单片机,就可以看到采集到的数据了。本程序使用了DMA软件触发ADC,循环采集。若需要定时采集的话,可以将ADC的触发方式改成定时器触发。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_60800812/article/details/144919487
|