STM32G474读取内部参考电压和内部温度传感器

STM32G474通过读取内部参考电压(Vrefint)和内部温度传感器(VTS),来测试“多个单通道ADC转换”。本实验采用软件触发,逐个读取ADC值

内部参考电压(Vrefint),连接到“ADC1_INP18通道”、“ADC3_INP18通道”、“ADC4_INP18通道”和“ADC5_INP18通道”,典型值为1.212V。
内部温度传感器(VTS),连接到“ADC1_INP16通道”和“ADC5_INP4通道”;

1、温度计算方法和宏定义


根据上面的表格,定义如下:

#define TS_CAL1     *((__IO uint16_t *)0x1FFF75A8)  //单位为mV
#define TS_CAL2     *((__IO uint16_t *)0x1FFF75CA)  //单位为mV
 
#define TS_TEMP_CAL1      30    //温度为30度时,其AD值为TS_CAL1
#define TS_TEMP_CAL2      130   //温度为130度,其AD值为TS_CAL2

1)、当Vref+=3.0V时,则采用下面的宏,计算其温度

由于(TS_TEMP_CAL2 - TS_TEMP_CAL1)/(TS_CAL2 - TS_CAL1))表示“度/mV”,所以我们定义温度为:

#define CalculateInternalTemperature(TS_DATA)      (TS_TEMP_CAL2 - TS_TEMP_CAL1)/(TS_CAL2 - TS_CAL1) * ( (TS_DATA*1) - TS_CAL1)  + TS_TEMP_CAL1
//TS_DATA为读到温度电压值,单位为mV,因为,上面的表格是Vref+=3.0V时校准的,Vref+ = 3.0V,因此使用“TS_DATA*1”参与计算。

2)、当Vref+=3.3V时,则采用下面的宏,计算其温度

#define CalculateInternalTemperature(TS_DATA)      (TS_TEMP_CAL2 - TS_TEMP_CAL1)/(TS_CAL2 - TS_CAL1) * ( (TS_DATA*1.1) - TS_CAL1)  + TS_TEMP_CAL1
//当Vref+ = 3.3V,3.3/3.0=1.1,这个1.1系数是这么来的
//if VREF+ = 3.3 V and TS_CAL data are acquired at VREF+= 3.0 V, TS_DATA must be replaced by TS_DATA x (3.3/3.0).

2、测试程序如下:

ADC_HandleTypeDef hadc1;
__IO uint16_t ADC1_RESULT[2];

void ADC1_Init(void);
void Read_ADC_Value_Use_SoftwareTriger(void);

void ADC1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
  ADC_MultiModeTypeDef multimode = {0};
//  ADC_AnalogWDGConfTypeDef AnalogWDGConfig = {0};
  ADC_ChannelConfTypeDef sConfig = {0};

  /* Peripheral clock enable */
  __HAL_RCC_ADC12_CLK_ENABLE(); //使能“ADC1和ADC2时钟”

/***********************************************/
    hadc1.Instance = ADC1;   //选择ADC1
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
    //分频系数:4分频,ADCCLK=PCLK2/4=170/4=42.5MHZ
    //设置ADCx_CCR寄存器bit17:16(CKMODE[1:0]]),CKMODE[1:0]=11,adc_hclk/4

  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
    //分辨率:12位模式
    //设置ADC_CFGR寄存器bit4:3(RES[1:0]),令RES[1:0]=00b,AD转换结果为12位

  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    //对齐方式:右对齐
    //设置ADC_CFGR寄存器bit15(ALIGN位),令ALIGN=0,AD转换结果为“右对齐”

  hadc1.Init.GainCompensation = 0;
    //ADC增益设置为0
    //设置ADC_CFGR2寄存器bit16(GCOMP),令GCOMP=0,常规ADC工作模式

  hadc1.Init.NbrOfConversion = 1;
    //“正则通道序列长度”为1,只有有1个AD转换;本程序用来测试“多个单通道ADC转换”
    //设置ADC_SQR1寄存器的bit3:0(L[3:0]),令L[3:0]=1-1,表示“正则通道序列长度”为1,有1个AD转换

    hadc1.Init.NbrOfDiscConversion=0;//不连续采样通道数为0
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
    //因为hadc1.Init.NbrOfConversion = 1,所以要使用“单通道转换”
    //如果是单通道转换使用ADC_SCAN_DISABLE
    //如果是多通道转换使用ADC_SCAN_ENABLE,这种情况需要DMA配合传输,否则读数据速度太慢,导致被取错。

  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    //ADC触发源选择“软件触发AD转换”
    //设置HRTIM->ADC1R寄存器bit5(ADC1EEV1位),ADC1EEV1=0,使用“内部软件”触发一次ADC转换

  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
    //上升沿触发
    //设置ADC->CFGR寄存器bit11:10(EXTEN[1:0]),EXTEN[1:0]=01b,硬件触发检测为上升沿

  hadc1.Init.ContinuousConvMode = DISABLE;
    //因为要采用“软件触发AD转换”,所以要用“单次转换”
    //使用ENABLE配置为使能自动连续转换;
    //使用DISABLE配置为单次转换,转换一次后停止,需要手动控制才重新启动转换
    //设置ADC_CFGR寄存器bit13(CONT位),令CONT=1,ADC采用“连续转换模式”

    hadc1.Init.SamplingMode=ADC_SAMPLING_MODE_NORMAL;
    //设置ADC_CFGR2寄存器bit27(SMPTRIG),令SMPTRIG=0,禁用“ADC轮询采样模式”
    //ADC转换采样相位持续时间

  hadc1.Init.DiscontinuousConvMode = DISABLE;
    //设置ADC_CFGR寄存器bit16(DISCEN位),令DISCEN=0,对于常规通道,禁止“不连续采样模式”

  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
    //ADC_EOC_SINGLE_CONV和 ADC_EOC_SEQ_CONV,指定转换结束时是否产生EOS中断或事件标志
    //配置ADC_IER寄存器bit2(EOCIE位),EOCIE=1,使能ADC转换完成产生中断

  hadc1.Init.LowPowerAutoWait = DISABLE;
    //配置是否使用低功耗自动延迟等待模式:关闭低功耗模式
    //配置ADC_CR寄存器bit29(DEEPPWD位),令DEEPPWD=0,ADC not in Deep-power down
    //可选参数为 ENABLE 和DISABLE,当使能时,仅当一组内所有之前的数据已处理完毕时
    //才开始新的转换,适用于低频应用。该模式仅用于 ADC 的轮询模式,不可用于 DMA 以及中断

  hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
    //数据溢出覆盖;当过载发生时,使用ADC_DR的新值覆盖
    //设置ADC_CFGR寄存器bit12(OVRMOD),令OVRMOD=1,当检测到溢出时,将用最后一个转换结果覆盖ADC_DR寄存器

  hadc1.Init.OversamplingMode = DISABLE;
    //设置ADC_CFGR2寄存器bit27(SMPTRIG),令SMPTRIG=1,启用过采样功能
    //这里需要设置为DISABLE,否则数据会发生错误

  hadc1.Init.DMAContinuousRequests = DISABLE;
    //不开启DMA请求连续模式或者单独模式
    //设置ADC_CFGR寄存器bit0(DMAEN),令DMAEN=0,不使能DMA

    HAL_ADC_Init(&hadc1);

  sConfig.Channel = ADC_CHANNEL_VREFINT;

//内参考电压(Vrefint),连接到“ADC1_INP18通道”
  sConfig.Rank = ADC_REGULAR_RANK_1;
    //设置ADC_SQR1寄存器bit10:6(SQ1[4:0]),SQ1[4:0]=18,即AD通道18的序号为1
    //AD转换顺序排列:配置通道18位于“第1个序列”

  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
    //采样时间
    //设置ADC_SMPR1寄存器bit8:6(SMP2[2:0]),SMP2[2:0]=000b,2.5 ADC clock cycles

  sConfig.SingleDiff = ADC_SINGLE_ENDED;
    //配置ADC通道输入为“单端模式”,非“差动输入模式”
  sConfig.OffsetNumber = ADC_OFFSET_NONE;//无偏移数量
  sConfig.Offset = 0;//偏移量=0
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);//配置AD通道6的序号为1

    HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
}

void Read_ADC_Value_Use_SoftwareTriger(void)
{
    float f;
    ADC_ChannelConfTypeDef sConfig = {0};

    LED1_Toggle();

  sConfig.Channel = ADC_CHANNEL_VREFINT;

//内参考电压(Vrefint),连接到“ADC1_INP18通道”
  sConfig.Rank = ADC_REGULAR_RANK_1;
    //设置ADC_SQR1寄存器bit10:6(SQ1[4:0]),SQ1[4:0]=18,即AD通道18的序号为1
    //AD转换顺序排列:配置通道18位于“第1个序列”

  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
    //采样时间
    //设置ADC_SMPR1寄存器bit8:6(SMP2[2:0]),SMP2[2:0]=000b,2.5 ADC clock cycles

  sConfig.SingleDiff = ADC_SINGLE_ENDED;
    //配置ADC通道输入为“单端模式”,非“差动输入模式”
  sConfig.OffsetNumber = ADC_OFFSET_NONE;//无偏移数量
  sConfig.Offset = 0;//偏移量=0
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);//配置AD通道6的序号为1
    HAL_ADC_Start(&hadc1);//启动一次AD转换
    HAL_ADC_PollForConversion(&hadc1,100);
    //等待“常规组”转换完成
    //Wait for regular group conversion to be completed

  ADC1_RESULT[0]=HAL_ADC_GetValue(&hadc1);
    //获取ADC“常规组”转换结果
    //Get ADC regular group conversion result.
//    HAL_ADC_Stop(&hadc1);
    //停止常规组的ADC转换,禁用ADC外设。
    //Stop ADC conversion of regular group,disable ADC peripheral.


  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR_ADC1;//内部温度传感器(VTS),连接到“ADC1_INP16通道”
  sConfig.Rank = ADC_REGULAR_RANK_1;
    //设置ADC_SQR1寄存器bit10:6(SQ1[4:0]),SQ1[4:0]=16,即AD通道16的序号为1
    //AD转换顺序排列:配置通道16位于“第1个序列”

  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
    //采样时间
    //设置ADC_SMPR1寄存器bit8:6(SMP2[2:0]),SMP2[2:0]=000b,2.5 ADC clock cycles

  sConfig.SingleDiff = ADC_SINGLE_ENDED;
    //配置ADC通道输入为“单端模式”,非“差动输入模式”
  sConfig.OffsetNumber = ADC_OFFSET_NONE;//无偏移数量
  sConfig.Offset = 0;//偏移量=0
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);//配置AD通道2的序号为2
    HAL_ADC_Start(&hadc1);//启动一次AD转换
    HAL_ADC_PollForConversion(&hadc1,100);
    //等待“常规组”转换完成
    //Wait for regular group conversion to be completed
  ADC1_RESULT[1]=HAL_ADC_GetValue(&hadc1);
    //获取ADC“常规组”转换结果
    //Get ADC regular group conversion result.

  printf("ADC1_RESULT[0]=0x%X\r\n",ADC1_RESULT[0]);
    printf("ADC1_RESULT[1]=0x%X\r\n",ADC1_RESULT[1]);
  f=ADC1_RESULT[0];f=f/4096;f=f*3300;
    printf("Vrefint=%0.1fmV\r\n",f);


    f=ADC1_RESULT[1];f=f*3300;f=f/4096;
    f=CalculateInternalTemperature(f);
    printf("Temperature=%0.1f\r\n",f);
}

3、测试结果

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值