本帖最后由 Zhao_kar 于 2025-3-19 19:56 编辑
【STM32 H533RE】测评六_官方自带温度传感器的尝试
备注:这一篇算是头一次尝试单片机自带的温度传感器,其实常用的h7也有,但是一直没用过,所以这一篇就简单按照当初计划说的试一试
一、内部温度传感器描述
首先在看h5的资料图的时候可以看到如下
明显可以看到,这个温度传感器是内置在adc里面的,应该是一个内部数字传感器,然后我们打开cubemx部分,在adc部分开一个通道,可以看到一个设置
再了解如何操作之前,先看一下官方文档内容,然后我们在这个文档去找资料
打开之后是一个h5的文档,在目录里面我们可以看到adc相关配置里面有内置温度传感器的资料
详细的步骤在文档里面都有,这里补一个通道数,明显是16通道
然后再看一下官方的算法
基本了解之后就可以开始配置了。
二、cubemx部分
这部分比较简单,首先是打开传感器部分,像前面一样,然后是周期按照需求改
然后串口老样子
时钟树核实一下
基本上cubemx就操作好了
三、写代码
我这边先给一个函数库,这部分有两种方法,第一种直接按照官方文档来写,第二种是去调用寄存器存的内容,我这边用的第一种,第二种用的人比较多,我这边只是简单测试,就不用了。
void Read_Internal_Temperature()
{
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) // 确保转换成功
{
uint32_t ADC_Value = HAL_ADC_GetValue(&hadc1);
printf("ADC1_IN16 ADC value: %d\r\n", ADC_Value);
float Vol_Value = ADC_Value * (VREF / ADC_RESOLUTION);
printf("ADC1_IN16 VOL value: %.2fV\r\n", Vol_Value);
float Temperature = (TS_CAL1_VOLTAGE - Vol_Value) / TS_SLOPE + TS_CAL1_TEMP;
printf("MCU Internal Temperature: %.2f°C\r\n", Temperature);
}
else
{
printf("ADC conversion timeout!\r\n");
}
HAL_Delay(1000);
}
把这部分函数写好,然后在主函数开头做一个宏定义
#define VREF 3.3
#define ADC_RESOLUTION 4096.0
#define TS_CAL1_TEMP 25.0
#define TS_CAL1_VOLTAGE 0.4
#define TS_SLOPE 0.01 // 传感器斜率
然后补充一点,配置这部分可以去adc里面看一下初始化的代码确认一下,也就是这部分
void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 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_ASYNC_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
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.SamplingMode = ADC_SAMPLING_MODE_NORMAL;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
做完这些之后就可以在while循环里面调用函数了,具体操作如下
/* USER CODE BEGIN 3 */
// HAL_ADC_Start(&hadc1);
// HAL_ADC_PollForConversion(&hadc1, 50);
//
// ADC_Value = HAL_ADC_GetValue(&hadc1); //读取ADC转换数据(16位数据)
// TS_CAL1 = *(__IO uint16_t *)(0x1FF1E820);
// TS_CAL2 = *(__IO uint16_t *)(0x1FF1E840);
// ADC_Value = ((110.0f - 30.0f) / (TS_CAL2 - TS_CAL1)) * (ADC_Value - TS_CAL1) + 30.0f;
// printf("%f\n",ADC_Value);
// HAL_Delay(1000);
Read_Internal_Temperature();
HAL_Delay(1000);
}
/* USER CODE END 3 */
然后我这部分是之前测试的按照地址读的方法,不同的芯片地址不一样,这边也不去试第二种方法了。
接下来就可以把代码烧录,然后看一下串口调试助手打印的数据(摄氏度那个句号稍微有点问题,不过无伤大雅)
然后我把板子稍微靠近灯带,温度也会上升
经过简单测试,内置温度器明显精读不够高,不够也就是测试玩玩,后面会上个专门的ds18b20和aht温湿度传感器测试