开发环境:
IDE:MKD 5.38a
STM32CubeMX: V6.12.0
开发板:STM32H7S78-DK开发板
MCU:STM32H7S7L8H6H
1 内部温度传感器工作原理
STM32H7S有一个内部温度传感器,可以用来测量 CPU 及周围的温度。该温度传感器在内部VSENSE输入通道相连接,此通道把传感器输出的电压转换成数字值。STM32H7S的内部温度传感器支持的温度范围为:-40~125度。
Figure 1-1 Temperature sensor架构
温度传感器的输出电压随温度线性变化。由于工艺不同,该线性函数的偏移量取决于各个芯片(芯片之间的温度变化可达 45°C)。
内部温度传感器更适用于对温度变量而非绝对温度进行测量的应用情况。如果需要读取精确温度,则应使用外部温度传感器。
STM32 内部温度传感器的使用很简单,只要设置一下内部 ADC,并激活其内部通道就差不多了。接下来我们介绍一下和温度传感器设置相关的 2 个地方。
第一个地方,我们要使用 STM32 的内部温度传感器,必须先激活 ADC 的内部通道,这里通过 ADC_CCR 的 TSEN位(bit23)设置。设置该位为 1 则启用内部温度传感器。
第二个地方, STM32 的内部温度传感器固定的连接在 ADC 的通道VSENSE上,所以,我们在设置好 ADC 之后只要读取VSENSE的值,就是温度传感器返回来的电压值了。根据这个值,我们就可以计算出当前温度。STM32内置一个温度传感器,通过VSENSE通道可以读出温度传感器的电压。其中给出了一个计算公式:
- TS_CAL1 是温度传感器在 30℃时的校准值,固定保存在芯片内部的: 0x08FF F814 - 0x08FF F815这两个地址( 16 位)。
- TS_CAL2 是温度传感器在 130℃时的校准值,固定保存在芯片内部的:0x08FF F818 - 0x08FF F819这两个地址( 16 位)。
- TS_DATA: ADC1通道VSENSE读取到的当前温度传感器转换值。
Table 1-1 Temperature sensor校准值
现在,我们就可以总结一下 STM32 内部温度传感器使用的步骤了,如下:
1)设置 ADC,开启内部温度传感器。
关于如何设置 ADC,上一节已经介绍了,我们采用与上一节相似的设置。 不同的是上一节温度传感器是读取外部通道的值,而内部温度传感器相当与把通道端口连接在内部温度传感器上。函数如下。
HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef *hadc, const ADC_ChannelConfTypeDef *pConfig)
2)读取通道VSENSE的 AD 值,计算结果。
在设置完之后,我们就可以读取温度传感器的电压值了, 得到该值就可以用上面的公式计算温度值。
2 内部温度传感器读取实现
2.1 STM32Cube生成工程
STM32H7S通道VSENSE连接内部温度传感器,因此,只需配置相应的参数即可。我们在串口的例子的基础上进行配置。
打开工程,打开Analog选项,配置ADC参数。
使能连续转换模式(Continuous Conversion Mode)。设置转换周期。其他为默认设置。
然后生成工程即可。
2.2 内部温度传感器具体代码
内部温度数据采集和普通ADC采集数据一样,其编程流程:
1.硬件等初始化;
2.串口、ADC等参数配置;
3.校准ADC,处理ADC数据;
主函数很简单:
/**
* [url=home.php?mod=space&uid=159083]@brief[/url] The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
float ADC_ConvertedValueLocal;
uint32_t ADC_ConvertedValue;
uint16_t ts_cal1 = 0;
uint16_t ts_cal2 = 0;
float temp = 0;
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_UART4_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart4, (uint8_t *)&RxBuffer, 1);
HAL_ADC_Start(&hadc1); //开启
ts_cal1 = *(volatile uint16_t*)(0x08FFF814);
ts_cal2 = *(volatile uint16_t*)(0x08FFF818);
temp = (float)((130.0f - 30.0f) / (ts_cal2-ts_cal1));
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_ADC_PollForConversion(&hadc1,10); //等待转换完成
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
{
ADC_ConvertedValue = HAL_ADC_GetValue(&hadc1);
ADC_ConvertedValueLocal =(float) ADC_ConvertedValue/(float)4096*3.3; // 读取转换的AD值
printf("The current AD value = 0x%04X \r\n", ADC_ConvertedValue);
printf("The current AD value = %f V \r\n",ADC_ConvertedValueLocal); //实际电压值
printf("temperture =%f\r\n\r\n",((ADC_ConvertedValue - ts_cal1) * temp + 30));
}
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
上述是通过查询的方式读取温度,也可通过中断和DMA的方式获取。
3 实验现象
将程序编译好后下载到板子中,通过串口助手可以看到在接收区有温度值输出。