本帖最后由 dffzh 于 2025-6-4 17:24 编辑
#申请原创#
@21小跑堂
我们有时候会利用MCU芯片内部的温度传感器来读取MCU温度,并用此温度数据来做一些应用功能,比如参数随温度动态调整,监控MCU芯片温度或者线性调整温度偏移等功能。这篇文章作者就带大家看一下如何读取STM32的STM32G431KBU3芯片的内部温度数据。通过整个读取过程的操作,以后大家遇到其他芯片,也可以按这个步骤进行尝试。 1、先看手册 我们先来看下芯片数据手册,找到与内部温度传感器相关的章节介绍,主要如下: 温度数据一般来源于模拟信号,那肯定是用ADC模块,所以我们先确认绑定了ADC外设的哪个通道,这个时候就需要打开数据手册或者用户手册来查看:
从用户手册可以看出,内部温度传感器是绑定了ADC1的16通道和ADC5的4通道。 再来看看对温度传感器的说明,读取流程和计算方法:
如果公式里面有一些常量参数值,也要看下如何读取出来: 2、再写代码 知道怎么读取芯片的温度传感器数据和计算方法后,接下来就可以编写代码调试了。 代码主要涉及ADC初始化配置和温度读取两个方面。 其中读取芯片内部温度传感器的ADC通道对应的宏是: ADC初始化配置接口为MX_ADC_Init,代码如下: void MX_ADC_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.GainCompensation = 0;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR_ADC1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_92CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
读取出厂校准点参数的代码如下:
uint8_t TS_CAL1_TEMP = 30;
uint8_t TS_CAL2_TEMP = 130;
uint16_t TS_CAL1 = 0;
uint16_t TS_CAL2 = 0;
//存储校准参数的地址
#define TS_CAL1_ADDR 0x1FFF75A8
#define TS_CAL2_ADDR 0x1FFF75CA
//从地址里读取所存的数据
uint8_t read_from_flash(uint32_t addr)
{
return *(uint8_t*)addr;
}
void read_g4_temp_cal(void)
{
uint8_t ts_cal_value_1 = 0;
uint8_t ts_cal_value_2 = 0;
HAL_FLASH_Unlock();
ts_cal_value_1 = read_from_flash(TS_CAL1_ADDR);
ts_cal_value_2 = read_from_flash(TS_CAL1_ADDR+1);
TS_CAL1 = ts_cal_value_1 | (ts_cal_value_2 << 8);
ts_cal_value_1 = read_from_flash(TS_CAL2_ADDR);
ts_cal_value_2 = read_from_flash(TS_CAL2_ADDR+1);
TS_CAL2 = ts_cal_value_1 | (ts_cal_value_2 << 8);
HAL_FLASH_Lock();
}
读取并转换温度的代码如下: void read_g4_temperature(void)
{
uint16_t adc_value = 0;
//1.read adc value
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
while(!HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC));
adc_value = HAL_ADC_GetValue(&hadc1);
AD_Value = adc_value *3.3/3;
//2.calculate actual temperature
g4_temp = ((TS_CAL2_TEMP - TS_CAL1_TEMP)*(AD_Value - TS_CAL1)/(TS_CAL2 - TS_CAL1)) + 30;
//3. test
//*ADC_PartStruct[0].Objects.objChannelValue = g4_temp;
sCh1Value = g4_temp;
//HAL_Delay(500);
}
3、最后测试验证 代码写好并且编译通过后,就是上板验证看看能不能成功读取温度。在Keil里使用jlink仿真器进行调试,全速运行后,看指示温度(单位为摄氏度)的全局变量的值从开始的21慢慢上升到27:
又升到了29:
从以上的仿真验证结果可以看出,读取MCU芯片内部温度传感器的代码和数据基本上是准确的。 不过这里没有考虑到精度问题,如果是对温度精度要求不高的场景,可以使用MCU内部温度作为数据源,如果是对温度精度要求比较高的场景,比如要保留几位小数点等,最好是先确认下你所用的MCU的内部温度传感器的精度,但是一般情况下建议直接使用外置的温度传感器,比如PT100或者热电偶之类的。
以上通过读取STM32G431KBU3芯片的内部温度数据,给大家提供了一种读取MCU芯片内部温度的基本方法,可以作为温度测试的一种参考。
|
@21小跑堂 :本地文档查看是有超过800字的(算上代码),我又增加了文字描述,请原创审核哦!
感谢大佬分享本文未满800字不予审核