硬汉嵌入式论坛

 找回密码
 立即注册
查看: 295|回复: 2
收起左侧

[ADC] STM32H7获取内置温度传感器值一直为65535

[复制链接]

1

主题

5

回帖

8

积分

新手上路

积分
8
发表于 2025-9-4 09:53:55 | 显示全部楼层 |阅读模式
void MX_ADC3_Init(void)
{

  /* USER CODE BEGIN ADC3_Init 0 */

  /* USER CODE END ADC3_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC3_Init 1 */

  /* USER CODE END ADC3_Init 1 */

  /** Common config
  */
  hadc3.Instance = ADC3;
  hadc3.Init.Resolution = ADC_RESOLUTION_16B;
  hadc3.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc3.Init.LowPowerAutoWait = DISABLE;
  hadc3.Init.ContinuousConvMode = DISABLE;
  hadc3.Init.NbrOfConversion = 1;
  hadc3.Init.DiscontinuousConvMode = DISABLE;
  hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
  hadc3.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc3.Init.OversamplingMode = DISABLE;
  hadc3.Init.Oversampling.Ratio = 16;
  if (HAL_ADC_Init(&hadc3) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  sConfig.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC3_Init 2 */
  HAL_Delay(20);
  if (HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK) {
        Error_Handler();
    }
  /* USER CODE END ADC3_Init 2 */

}

void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{

  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(adcHandle->Instance==ADC3)
  {
  /* USER CODE BEGIN ADC3_MspInit 0 */

  /* USER CODE END ADC3_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
    PeriphClkInitStruct.PLL2.PLL2M = 6;
    PeriphClkInitStruct.PLL2.PLL2N = 114;
    PeriphClkInitStruct.PLL2.PLL2P = 4;
    PeriphClkInitStruct.PLL2.PLL2Q = 4;
    PeriphClkInitStruct.PLL2.PLL2R = 4;
    PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_0;
    PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOMEDIUM;
    PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
    PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }

    /* ADC3 clock enable */
    __HAL_RCC_ADC3_CLK_ENABLE();
  /* USER CODE BEGIN ADC3_MspInit 1 */

  /* USER CODE END ADC3_MspInit 1 */
  }
}

void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{

  if(adcHandle->Instance==ADC3)
  {
  /* USER CODE BEGIN ADC3_MspDeInit 0 */

  /* USER CODE END ADC3_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_ADC3_CLK_DISABLE();
  /* USER CODE BEGIN ADC3_MspDeInit 1 */

  /* USER CODE END ADC3_MspDeInit 1 */
  }
}通过该代码初始化后HAL_ADC_GetValue(&hadc3);获取的值一直为65535

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
118335
QQ
发表于 2025-9-4 11:09:50 | 显示全部楼层
看着没什么问题,这个是我的。
[C] 纯文本查看 复制代码
/*
*********************************************************************************************************
*
*	模块名称 : ADC驱动
*	文件名称 : bsp_adc.c
*	版    本 : V1.0
*	说    明 : ADC多通道采样
*              1. 例子默认用的PLL时钟供ADC使用,大家可以通过bsp_adc.c文件开头宏定义切换到AHB时钟。
*              2、采用DMA方式进行多通道采样,采集了PC0, Vbat/4, VrefInt和温度。
*              3、ADC配置做了一个16倍过采样,使得采样数据比较稳定,最高支持1024倍过采样。
*
*	修改记录 :
*		版本号  日期        作者     说明
*		V1.0    2018-12-12 armfly  正式发布
*
*	Copyright (C), 2018-2030, 安富莱电子 [url]www.armfly.com[/url]
*
*********************************************************************************************************
*/
#include "bsp.h"



/* 选择ADC的时钟源 */
//#define ADC_CLOCK_SOURCE_AHB     /* 选择AHB时钟源 */
#define ADC_CLOCK_SOURCE_PLL     /* 选择PLL时钟源 */

/* 方便Cache类的API操作,做32字节对齐 */
#if defined ( __ICCARM__ )
#pragma location = 0x38000000
uint16_t ADCxValues[4];
#elif defined ( __CC_ARM )
ALIGN_32BYTES(__attribute__((section (".RAM_D3"))) uint16_t ADCxValues[4]);
#endif

DMA_HandleTypeDef   DMA_Handle = {0};

/*
*********************************************************************************************************
*	函 数 名: bsp_InitADC
*	功能说明: 初始化ADC,采用DMA方式进行多通道采样,采集了PC0, Vbat/4, VrefInt和温度
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitADC(void)
{
	ADC_HandleTypeDef   AdcHandle = {0};
	ADC_ChannelConfTypeDef   sConfig = {0};
	GPIO_InitTypeDef          GPIO_InitStruct;

  /* ## - 1 - 配置ADC采样的时钟 ####################################### */
#if defined (ADC_CLOCK_SOURCE_PLL)
	/* 配置PLL2时钟为的72MHz,方便分频产生ADC最高时钟36MHz */
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
	PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
	PeriphClkInitStruct.PLL2.PLL2M = 25;
	PeriphClkInitStruct.PLL2.PLL2N = 504;
	PeriphClkInitStruct.PLL2.PLL2P = 7;
	PeriphClkInitStruct.PLL2.PLL2Q = 7;
	PeriphClkInitStruct.PLL2.PLL2R = 7;
	PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_0;
	PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
	PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
	PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
	if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);  
	}
#elif defined (ADC_CLOCK_SOURCE_AHB)
  
  /* 使用AHB时钟的话,无需配置,默认选择*/
  
#endif

	/* ## - 2 - 配置ADC采样使用的时钟 ####################################### */
	__HAL_RCC_GPIOC_CLK_ENABLE();

	GPIO_InitStruct.Pin = GPIO_PIN_0;
	GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  
	/* ## - 3 - 配置ADC采样使用的时钟 ####################################### */
	__HAL_RCC_DMA1_CLK_ENABLE();
	DMA_Handle.Instance                 = DMA1_Stream1;            /* 使用的DMA1 Stream1 */
	DMA_Handle.Init.Request             = DMA_REQUEST_ADC3;  	   /* 请求类型采用DMA_REQUEST_ADC3 */  
	DMA_Handle.Init.Direction           = DMA_PERIPH_TO_MEMORY;    /* 传输方向是从存储器到外设 */  
	DMA_Handle.Init.PeriphInc           = DMA_PINC_DISABLE;        /* 外设地址自增禁止 */ 
	DMA_Handle.Init.MemInc              = DMA_MINC_ENABLE;         /* 存储器地址自增使能 */  
	DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;   /* 外设数据传输位宽选择半字,即16bit */     
	DMA_Handle.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;   /* 存储器数据传输位宽选择半字,即16bit */    
	DMA_Handle.Init.Mode                = DMA_CIRCULAR;            /* 循环模式 */   
	DMA_Handle.Init.Priority            = DMA_PRIORITY_LOW;        /* 优先级低 */  
	DMA_Handle.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;    /* 禁止FIFO*/
	DMA_Handle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL; /* 禁止FIFO此位不起作用,用于设置阀值 */
	DMA_Handle.Init.MemBurst            = DMA_MBURST_SINGLE;       /* 禁止FIFO此位不起作用,用于存储器突发 */
	DMA_Handle.Init.PeriphBurst         = DMA_PBURST_SINGLE;       /* 禁止FIFO此位不起作用,用于外设突发 */

	/* 初始化DMA */
	if(HAL_DMA_Init(&DMA_Handle) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);     
	}
    
	/* 关联ADC句柄和DMA句柄 */
	__HAL_LINKDMA(&AdcHandle, DMA_Handle, DMA_Handle);
	
    
	/* ## - 4 - 配置ADC ########################################################### */
	__HAL_RCC_ADC3_CLK_ENABLE();
	AdcHandle.Instance = ADC3;

#if defined (ADC_CLOCK_SOURCE_PLL)
	AdcHandle.Init.ClockPrescaler        = ADC_CLOCK_ASYNC_DIV8;          /* 采用PLL异步时钟,8分频,即72MHz/8 = 36MHz */
#elif defined (ADC_CLOCK_SOURCE_AHB)
	AdcHandle.Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV4;      /* 采用AHB同步时钟,4分频,即200MHz/4 = 50MHz */
#endif
	
	AdcHandle.Init.Resolution            = ADC_RESOLUTION_16B;        /* 16位分辨率 */
	AdcHandle.Init.ScanConvMode          = ADC_SCAN_ENABLE;           /* 禁止扫描,因为仅开了一个通道 */
	AdcHandle.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;       /* EOC转换结束标志 */
	AdcHandle.Init.LowPowerAutoWait      = DISABLE;                   /* 禁止低功耗自动延迟特性 */
	AdcHandle.Init.ContinuousConvMode    = ENABLE;                    /* 禁止自动转换,采用的软件触发 */
	AdcHandle.Init.NbrOfConversion       = 4;                         /* 使用了4个转换通道 */
	AdcHandle.Init.DiscontinuousConvMode = DISABLE;                   /* 禁止不连续模式 */
	AdcHandle.Init.NbrOfDiscConversion   = 1;                         /* 禁止不连续模式后,此参数忽略,此位是用来配置不连续子组中通道数 */
	AdcHandle.Init.ExternalTrigConv      = ADC_SOFTWARE_START;        /* 采用软件触发 */
	AdcHandle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_RISING;    /* 采用软件触发的话,此位忽略 */
	AdcHandle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; /* DMA循环模式接收ADC转换的数据 */
	AdcHandle.Init.BoostMode             = DISABLE;                            /* ADC时钟低于20MHz的话,可以禁止boost */
	AdcHandle.Init.Overrun               = ADC_OVR_DATA_OVERWRITTEN;     	   /* ADC转换溢出的话,覆盖ADC的数据寄存器 */
	AdcHandle.Init.OversamplingMode         		  = ENABLE;                        /* 使能过采样 */
	AdcHandle.Init.Oversampling.Ratio                 = 15;                            /* 15+1倍过采样 */
	AdcHandle.Init.Oversampling.RightBitShift         = ADC_RIGHTBITSHIFT_4;           /* 数据右移4bit,即除以16 */
	AdcHandle.Init.Oversampling.TriggeredMode         = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;   /* 触发后连续完成每个通道的所有过采样转换 */
	AdcHandle.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE; /* 如果触发注入转换,过采样会暂时停止,并会在注
                                                                                               入序列完成后继续,注入序列过程中会保留过采样缓冲区*/    

    /* 初始化ADC */
	if (HAL_ADC_Init(&AdcHandle) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
  
  
	/* 校准ADC,采用偏移校准 */
	if (HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
  
	/* 配置ADC通道,序列1,采样PC0引脚 */
	/*
		采用PLL2时钟的话,ADCCLK = 72MHz / 8 = 9MHz
	    ADC采样速度,即转换时间 = 采样时间 + 逐次逼近时间
	                            = 810.5 + 8.5(16bit)
	                            = 820个ADC时钟周期
	    那么转换速度就是9MHz / 820 = 10975Hz
	*/
	sConfig.Channel      = ADC_CHANNEL_10;              /* 配置使用的ADC通道 */
	sConfig.Rank         = ADC_REGULAR_RANK_1;          /* 采样序列里的第1个 */
	sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;  /* 采样周期 */
	sConfig.SingleDiff   = ADC_SINGLE_ENDED;            /* 单端输入 */
	sConfig.OffsetNumber = ADC_OFFSET_NONE;             /* 无偏移 */ 
	sConfig.Offset = 0;                                 /* 无偏移的情况下,此参数忽略 */
	sConfig.OffsetRightShift       = DISABLE;           /* 禁止右移 */
	sConfig.OffsetSignedSaturation = DISABLE;           /* 禁止有符号饱和 */
	
	if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
	
	/* 配置ADC通道,序列2,采样Vbat/4 */
	sConfig.Channel      = ADC_CHANNEL_VBAT_DIV4;       /* 配置使用的ADC通道 */
	sConfig.Rank         = ADC_REGULAR_RANK_2;          /* 采样序列里的第2个 */
	sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;  /* 采样周期 */
	sConfig.SingleDiff   = ADC_SINGLE_ENDED;            /* 单端输入 */
	sConfig.OffsetNumber = ADC_OFFSET_NONE;             /* 无偏移 */ 
	sConfig.Offset = 0;                                 /* 无偏移的情况下,此参数忽略 */
	sConfig.OffsetRightShift       = DISABLE;           /* 禁止右移 */
	sConfig.OffsetSignedSaturation = DISABLE;           /* 禁止有符号饱和 */
	
	if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
  
	/* 配置ADC通道,序列3,采样VrefInt */
	sConfig.Channel      = ADC_CHANNEL_VREFINT;         /* 配置使用的ADC通道 */
	sConfig.Rank         = ADC_REGULAR_RANK_3;          /* 采样序列里的第3个 */
	sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;  /* 采样周期 */
	sConfig.SingleDiff   = ADC_SINGLE_ENDED;            /* 单端输入 */
	sConfig.OffsetNumber = ADC_OFFSET_NONE;             /* 无偏移 */ 
	sConfig.Offset = 0;                                 /* 无偏移的情况下,此参数忽略 */
	sConfig.OffsetRightShift       = DISABLE;           /* 禁止右移 */
	sConfig.OffsetSignedSaturation = DISABLE;           /* 禁止有符号饱和 */
	
	if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}

	/* 配置ADC通道,序列4,采样VrefInt */
	sConfig.Channel      = ADC_CHANNEL_TEMPSENSOR;      /* 配置使用的ADC通道 */
	sConfig.Rank         = ADC_REGULAR_RANK_4;          /* 采样序列里的第4个 */
	sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;  /* 采样周期 */
	sConfig.SingleDiff   = ADC_SINGLE_ENDED;            /* 单端输入 */
	sConfig.OffsetNumber = ADC_OFFSET_NONE;             /* 无偏移 */ 
	sConfig.Offset = 0;                                 /* 无偏移的情况下,此参数忽略 */
	sConfig.OffsetRightShift       = DISABLE;           /* 禁止右移 */
	sConfig.OffsetSignedSaturation = DISABLE;           /* 禁止有符号饱和 */
	
	if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}	
  

	/* ## - 6 - 启动ADC的DMA方式传输 ####################################### */
	if (HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *)ADCxValues, 4) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
}

/*
*********************************************************************************************************
*	函 数 名: bsp_GetAdcValues
*	功能说明: 获取ADC的数据并打印
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_GetAdcValues(void)
{
    float AdcValues[5];
    uint16_t TS_CAL1;
    uint16_t TS_CAL2;
    
    /*
       使用此函数要特别注意,第1个参数地址要32字节对齐,第2个参数要是32字节的整数倍
    */
    SCB_InvalidateDCache_by_Addr((uint32_t *)ADCxValues,  sizeof(ADCxValues));
    AdcValues[0] = ADCxValues[0] * 3.3 / 65536;
    AdcValues[1] = ADCxValues[1] * 3.3 / 65536; 
    AdcValues[2] = ADCxValues[2] * 3.3 / 65536;     
    
    TS_CAL1 = *(__IO uint16_t *)(0x1FF1E820);
    TS_CAL2 = *(__IO uint16_t *)(0x1FF1E840);
    
    AdcValues[3] = (110.0 - 30.0) * (ADCxValues[3] - TS_CAL1)/ (TS_CAL2 - TS_CAL1) + 30;  
    
    printf("PC0 = %5.3fV, Vbat/4 = %5.3fV, VrefInt = %5.3fV, TempSensor = %5.3f℃\r\n", 
            AdcValues[0],  AdcValues[1], AdcValues[2], AdcValues[3]);

}

/***************************** 安富莱电子 [url]www.armfly.com[/url] (END OF FILE) *********************************/
回复

使用道具 举报

1

主题

5

回帖

8

积分

新手上路

积分
8
 楼主| 发表于 2025-9-4 15:13:16 | 显示全部楼层
eric2013 发表于 2025-9-4 11:09
看着没什么问题,这个是我的。
[mw_shl_code=c,true]/*
********************************************** ...

应该使VREF+没有电压,应该需要配置内部的VREFBUF,现在还没弄好
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-9-26 18:23 , Processed in 0.042840 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表