国民技术N32G45x双ADC规则同步模式配置

国民技术N32G45XVL-STB评估板ADC问题

N32G45x的ADC有三个时钟,分别是工作时钟源、采样时钟源和计时时钟源。计时时钟源必须为1M,可以不配置,不配置的话默认是使用的HSI,8分频。

因为项目需要进行电池电源的监测,对应的ADC引脚在ADC2上,此外还需要采集Vrefint通道,对应的ADC通道位于ADC1,因此可以用这款MCU的双ADC模式。双ADC为主从模式,ADC1(主)和 ADC2(从),ADC3(主)和 ADC4(从)可以组成双 ADC 模式,一共有6种模式,还可以组合使用6种模式,具体可以查阅手册。

初始化并启动转换过程:

void Dev_ADCInit(void)
{
	ADC_InitType ADC_InitStructure;
	GPIO_InitType GPIO_InitStructure;
	
	RCC_EnableAPB2PeriphClk(PWR_ADC_RCC, ENABLE);
	RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC1,ENABLE);
	RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC2,ENABLE);
	RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSE,RCC_ADC1MCLK_DIV8);
	/* RCC_ADCHCLK_DIV8*/
  	ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB,RCC_ADCHCLK_DIV4);
	
    
	/* Configure PWR_ADC_Pin as analog input -------------------------*/
	GPIO_InitStructure.Pin       = PWR_ADC_Pin;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Speed	= GPIO_INPUT;
	GPIO_InitPeripheral(PWR_ADC_Port, &GPIO_InitStructure);
	
	/* ADC1 configuration ------------------------------------------------------*/
	ADC_InitStructure.WorkMode       = ADC_WORKMODE_REG_SIMULT;	//规则同步模式
	ADC_InitStructure.MultiChEn      = DISABLE;					//关闭扫描模式
	ADC_InitStructure.ContinueConvEn = DISABLE;					//单次转换
	ADC_InitStructure.ExtTrigSelect  = ADC_EXT_TRIGCONV_NONE;	//SWSTRRCH
	ADC_InitStructure.DatAlign       = ADC_DAT_ALIGN_R;			//右对齐
	ADC_InitStructure.ChsNumber      = 1;						//规则通道序列长度
	ADC_Init(ADC1, &ADC_InitStructure);
	
	/* ADC1 regular configuration */
	ADC_ConfigRegularChannel(ADC1, ADC_CH_INT_VREF, 1, ADC_SAMP_TIME_71CYCLES5);//ADC_CH_18:测内部1.2V基准
	
	/* ADC1 temp sensor enable */
	ADC_EnableTempSensorVrefint(ENABLE); 						//使能温度传感器和VREFINT通道
	
	/* ADC2 configuration ------------------------------------------------------*/
	ADC_InitStructure.WorkMode       = ADC_WORKMODE_REG_SIMULT;	//规则同步模式
	ADC_InitStructure.MultiChEn      = DISABLE;					//关闭扫描模式
	ADC_InitStructure.ContinueConvEn = DISABLE;					//单次转换
	ADC_InitStructure.ExtTrigSelect  = ADC_EXT_TRIGCONV_NONE;	//SWSTRRCH
	ADC_InitStructure.DatAlign       = ADC_DAT_ALIGN_R;			//右对齐
	ADC_InitStructure.ChsNumber      = 1;						//规则通道序列长度
	ADC_Init(ADC2, &ADC_InitStructure);
	
	/* ADC2 regular configuration */
	ADC_ConfigRegularChannel(ADC2, PWR_ADC_CHANNEL, 1, ADC_SAMP_TIME_71CYCLES5);//vbat监测
	
	/* Enable ADC2 external trigger conversion */
	ADC_EnableExternalTrigConv(ADC2, ENABLE);
	
	/* Enable ADC1 */
	ADC_Enable(ADC1, ENABLE);
	/*Check ADC Ready*/
	while(ADC_GetFlagStatusNew(ADC1,ADC_FLAG_RDY) == RESET);
	/* Start ADC1 calibration */
	ADC_StartCalibration(ADC1);
	/* Check the end of ADC1 calibration */
	while (ADC_GetCalibrationStatus(ADC1));
	
	/* Enable ADC2 */
	ADC_Enable(ADC2, ENABLE);
	/*Check ADC Ready*/
	while(ADC_GetFlagStatusNew(ADC2,ADC_FLAG_RDY) == RESET);
	/* Start ADC2 calibration */
	ADC_StartCalibration(ADC2);
	/* Check the end of ADC2 calibration */
	while (ADC_GetCalibrationStatus(ADC2));
	
	/* Start ADC1 Software Conversion */
	ADC_EnableSoftwareStartConv(ADC1, ENABLE);
}

项目中MCU的主频使用的是48M。
计时时钟源采用的是HSE(8M)的8分频,为1M;

RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSE,RCC_ADC1MCLK_DIV8);

采样时钟使用的是AHB时钟的4分频,也就是12M。

ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB,RCC_ADCHCLK_DIV4);

ADC1和ADC2各采集一个通道,获取数据过程:

uint16_t ADC_Read(void)
{
	uint32_t adc_data = 0;
 	uint16_t i = 0,BattAdVal = 0,VrefAdVal = 0,Battery = 0;
 	
	Dev_ADCInit();

	while((ADC_GetFlagStatus(ADC2, ADC_FLAG_ENDC)==RESET)&&((i++) <= 200));
	ADC_ClearFlag(ADC1, ADC_FLAG_ENDC);
	ADC_ClearFlag(ADC1, ADC_FLAG_STR);
	ADC_ClearFlag(ADC2, ADC_FLAG_ENDC);
	ADC_ClearFlag(ADC2, ADC_FLAG_STR);
	
	adc_data = ADC_GetDualModeConversionDat(ADC1);
	BattAdVal = (uint16_t)(adc_data>>16);
	VrefAdVal = (uint16_t)adc_data;	
	
	Dev_ADCDeInit();
	
	Battery = Get_Battery(BattAdVal,VrefAdVal);
	
	return Battery;
}

读取数据使用ADC_GetDualModeConversionDat()函数,此函数会读取主ADC(ADC1/ADC3)的规则数据寄存器,该寄存器的高16位在双模式下,包含了从ADC转换的规则通道数据,低16位为主ADC转换的规则通道数据。至此就可以实现双ADC采集,通过Vbat和Vrefint通道的转换结果就可以求出当前电池电压。
笔记:STM32的ADC参考电压与参照电压(电源监测)
在这里插入图片描述
在这里插入图片描述

疑问:
在ADC的DMA请求章节中有双 ADC 模式时, 由 ADC2 转化的数据在 ADC1 的数据寄存器中,由 ADC4 转化的数据在 ADC3 的数据寄存器中的描述。在ADC的双ADC模式章节中有在双ADC 模式里,为了在主数据寄存器上读取从转换数据,必须使能DMA 位,即使不使用DMA 传输规则通道数据,从ADC 不能使能DMA的描述。

但是实际使用时发现没有使能DMA位也能在主数据寄存器上读取从转换数据,至于什么原因暂时还没有深究,有时间再看吧。
在这里插入图片描述


版权声明:本文为sinat_42731525原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。