• 国民技术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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

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

    RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSE,RCC_ADC1MCLK_DIV8);
    
    • 1

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

    ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB,RCC_ADCHCLK_DIV4);
    
    • 1

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    读取数据使用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位也能在主数据寄存器上读取从转换数据,至于什么原因暂时还没有深究,有时间再看吧。
    在这里插入图片描述

  • 相关阅读:
    计讯物联外贸公司--佰沃恩应邀出席第三届“嘉庚论坛”—科技创新推动经济高质量发展分论坛
    12030.LMK03000时钟合成器
    两个不相交的闭集并不能保证两个集合可分
    【1-ElasticSearch的基本介绍与用途、ElasticSearch中一些基本的概念、倒排索引的基本概念】
    初识JavaScript
    2022国赛D题气象报文信息卫星通信传输参考代码及思路
    els 兼容性DC、传递图片到窗口
    【0236】聊一聊PG内核中的命令标签(Command Tags、CommandTag、tag_behavior)
    基于java的创意项目众筹平台的设计与开发计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署
    安卓手机如何使用第三方主题,制作专属自己喜好的主题
  • 原文地址:https://blog.csdn.net/sinat_42731525/article/details/126390079