[综合信息] HC32F460 温度传感器(OTS)原理与应用实战

[复制链接]
1984|0
Xiashiqi 发表于 2025-9-4 13:59 | 显示全部楼层 |阅读模式
在嵌入式系统设计中,温度监测是保障设备稳定运行、延长硬件寿命的关键功能。HC32F460 系列微控制器内置的温度传感器(OTS)模块,凭借无需外部硬件、集成度高、功耗低等优势,广泛应用于电机控制、工业监测、消费电子等场景。本文将从 OTS 模块的工作原理、硬件特性、驱动开发到实际应用,全面解析其技术细节与工程实践方法。

一、OTS 模块核心特性与工作原理
1.1 核心特性(基于 HC32F460 参考手册)
HC32F460 的 OTS 模块是一款基于半导体热敏效应的内置温度传感器,主要特性如下:

测量范围:典型覆盖 -40℃ ~ 125℃,满足工业级宽温需求;
时钟灵活性:支持 HRC(内部高速时钟)或 XTAL(外部晶振)作为工作时钟,适配不同系统时钟方案;
低功耗设计:支持采样完成后自动关闭(Auto-Off),降低待机功耗;
校准机制:通过斜率(K)和偏移(M)参数校准,可实现 ±1℃ 级测量精度;
硬件触发:支持通过 AOS(自动运行系统)模块实现外设联动触发采样,减少 CPU 干预。
1.2 工作原理
OTS 模块的核心是利用半导体器件的 温度 - 频率特性 实现温度测量,其原理框图如下(参考手册图 17-1):

时钟源选择:从 HRC 或 XTAL 中选择稳定时钟,为采样提供基准;
双路采样电路:通过 DR1(数据寄存器 1)和 DR2(数据寄存器 2)采集不同温度敏感元件的信号,抵消环境干扰;
误差补偿:ECR(误差补偿寄存器)存储出厂校准的误差系数,修正采样偏差;
温度计算:通过公式 T = K × [(1/DR1) - (1/DR2)] × ECR + M 计算实际温度,其中 K(斜率)和 M(偏移)需通过校准实验获取。
二、OTS 硬件配置与寄存器解析
2.1 外设时钟与地址映射
根据 HC32F460 参考手册 “存储器映射” 章节:

OTS 模块挂载于 APB4 总线,基地址为 0x4004_A400;
需通过 PWC_FCG3 寄存器(功能时钟控制 3)的 OTS 位使能时钟:PWC_FCG3 |= PWC_FCG3_OTSEN(位 12 置 1)。
2.2 关键寄存器说明
OTS 模块的配置与控制依赖 4 个核心寄存器,需结合参考手册 17.3 节理解其功能:

2147568b92aa44c522.png


关键位配置示例:

选择 HRC 时钟:OTS_CTL |= OTS_CTL_OTSCK;
使能自动关闭:OTS_CTL |= OTS_CTL_TSSTP(采样完成后自动停止 OTS);
启动采样:OTS_CTL |= OTS_CTL_OTSST。
三、OTS 驱动开发实战(基于 LL 库)
HC32F460 提供 LL(底层库)驱动,开发者可基于 hc32_ll_ots.h/hc32_ll_ots.c 封装实用接口。以下为完整驱动实现,包含初始化、校准、温度读取功能。

3.1 驱动头文件(iots.h)
#ifndef __IOTS_H__
#define __IOTS_H__

#include "hc32_ll.h"
#include "hc32f460.h"


#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief  OTS 初始化函数
* @param  None
* @retval int32_t: 初始化结果
*         - LL_OK: 初始化成功
*         - LL_ERR_INVD_PARAM: 参数错误(内部断言触发,正常不会返回)
*/
int32_t BSP_OTS_Init(void);

/**
* @brief  OTS 轮询读取温度(阻塞式)
* @param  [out] pf32Temp: 温度存储地址(单位:℃)
* @param  [in] u32Timeout: 超时时间(单位:循环次数,建议≥1000)
* @retval int32_t: 读取结果
*         - LL_OK: 读取成功
*         - LL_ERR_TIMEOUT: 超时失败
*         - LL_ERR_INVD_PARAM: 输入指针为空
*/
int32_t BSP_OTS_ReadTempPolling(float32_t *pf32Temp, uint32_t u32Timeout);

/**
* @brief  OTS 校准实验(获取K/M参数,需在已知温度环境下执行)
* @param  [in] u8TempCond: 校准温度条件(参考 OTS_Param_Temp_Cond)
*         - OTS_PARAM_TEMP_COND_TN40: -40℃
*         - OTS_PARAM_TEMP_COND_T25: 25℃(常温推荐)
*         - OTS_PARAM_TEMP_COND_T125: 125℃
* @param  [out] pf32SlopeK: 校准后的斜率K(输出参数,用于初始化)
* @param  [out] pf32OffsetM: 校准后的偏移M(输出参数,用于初始化)
* @param  [in] u32Timeout: 超时时间(单位:循环次数,建议≥1000)
* @retval int32_t: 校准结果
*         - LL_OK: 校准成功
*         - LL_ERR_TIMEOUT: 超时失败
*         - LL_ERR_INVD_PARAM: 输入指针为空或温度条件非法
*/
int32_t BSP_OTS_Calibrate(uint8_t u8TempCond, float32_t *pf32SlopeK, float32_t *pf32OffsetM, uint32_t u32Timeout);

#ifdef __cplusplus
}
#endif

#endif /* __IOTS_H__ */



3.2 驱动源文件(iots.c)
#include "iots.h"

/**
* @brief  OTS 硬件依赖初始化(时钟使能)
* @NOTE   HC32F460 的 OTS 挂载在 CM_OTS 外设,需先使能其时钟
* @param  None
* @retval None
*/
static void BSP_OTS_HwInit(void)
{
    /* 1. 使能 OTS 外设时钟(CM_OTS 时钟由 PCLK0 提供,需先确保 PCLK0 使能) */
    FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_OTS, ENABLE);

    /* 2. (可选)若使用 XTAL 作为 OTS 时钟,需先初始化 XTAL 并确保其稳定 */
    // 示例:若选择 OTS_CLK_XTAL,需先初始化 XTAL(根据实际硬件配置,如 8MHz)
    // stc_clk_xtal_init_t stcXtalInit = {0};
    // stcXtalInit.u8XtalState = CLK_XTAL_ON;
    // stcXtalInit.u8XtalMode = CLK_XTAL_MODE_OSC;
    // stcXtalInit.u8XtalDrv = CLK_XTAL_DRV_LOW;
    // CLK_XtalInit(&stcXtalInit);
    // while (CLK_GetXtalSta() != CLK_XTAL_STA_STB) { /* 等待 XTAL 稳定 */ }
}

/**
* @brief  OTS 初始化(调用 LL 库接口,配置时钟、自动关闭、校准参数)
* @param  None
* @retval int32_t: 初始化结果
*/
int32_t BSP_OTS_Init(void)
{
    int32_t i32Ret = LL_ERR_INVD_PARAM;
    stc_ots_init_t stcOTSInit = {0};

    /* 1. 硬件初始化(时钟使能) */
    BSP_OTS_HwInit();

    /* 2. 初始化 OTS 配置结构体(默认参数,可根据需求修改) */
    i32Ret = OTS_StructInit(&stcOTSInit);
    if (i32Ret != LL_OK)
    {
        return i32Ret;
    }

    /* 3. 自定义 OTS 配置(根据实际需求调整) */
    stcOTSInit.u16ClockSrc = OTS_CLK_HRC; // 选择 HRC 作为 OTS 时钟(推荐,无需额外初始化)
    // stcOTSInit.u16ClockSrc  = OTS_CLK_XTAL;    // 若选择 XTAL,需先完成 XTAL 初始化(见 BSP_OTS_HwInit 注释)
    stcOTSInit.u16AutoOffEn = OTS_AUTO_OFF_ENABLE; // 采样完成后自动关闭 OTS(降低功耗)

    /* 4. 校准参数配置 */

    // 使用校准后的 K/M 参数(精度高,需先执行 BSP_OTS_Calibrate 获得)
    stcOTSInit.f32SlopeK = 3005.26F;   // 斜率(根据芯片特性微调)
    stcOTSInit.f32OffsetM = 27.93F; // 偏移(修正量)

    /* 5. 调用 LL 库初始化 OTS */
    i32Ret = OTS_Init(&stcOTSInit);
    return i32Ret;
}

/**
* @brief  轮询读取温度(阻塞式,基于 LL_OTS_Polling 封装)
* @param  [out] pf32Temp: 温度存储地址
* @param  [in] u32Timeout: 超时时间 建议不小于10000
* @retval int32_t: 读取结果
*/
int32_t BSP_OTS_ReadTempPolling(float32_t *pf32Temp, uint32_t u32Timeout)
{
    int32_t i32Ret = LL_ERR_INVD_PARAM;

    /* 1. 参数合法性检查 */
    if (pf32Temp == NULL)
    {
        return LL_ERR_INVD_PARAM;
    }

    /* 2. 调用 LL 库轮询读取温度 */
    i32Ret = OTS_Polling(pf32Temp, u32Timeout);
    if (i32Ret == LL_OK)
    {
        /* 可选:温度范围过滤(HC32F460 OTS 典型量程:-40℃ ~ 125℃) */
        if (*pf32Temp < -50.0F || *pf32Temp > 135.0F)
        {
            i32Ret = LL_ERR_INVD_MD; // 超出合理范围,返回数据非法
        }
    }

    return i32Ret;
}

/**
* @brief  OTS 校准实验(获取 K/M 参数,需在已知温度环境下执行)
* @note   原理:在 2 个已知温度点(如 25℃ 和 125℃)执行校准,计算斜率 K 和偏移 M
* @param  [in] u8TempCond: 校准温度条件
* @param  [out] pf32SlopeK: 斜率 K
* @param  [out] pf32OffsetM: 偏移 M
* @param  [in] u32Timeout: 超时时间
* @retval int32_t: 校准结果
*/
int32_t BSP_OTS_Calibrate(uint8_t u8TempCond, float32_t *pf32SlopeK, float32_t *pf32OffsetM, uint32_t u32Timeout)
{
    int32_t i32Ret = LL_ERR_INVD_PARAM;
    static float32_t s_f32A1 = 0.0F, s_f32A2 = 0.0F; // 存储两个温度点的 A 参数
    static uint8_t s_u8CalibCnt = 0;                 // 校准计数(0:未校准,1:第一个点,2:完成)
    uint16_t u16Dr1 = 0, u16Dr2 = 0, u16Ecr = 0;

    /* 1. 参数合法性检查 */
    if ((pf32SlopeK == NULL) || (pf32OffsetM == NULL))
    {
        return LL_ERR_INVD_PARAM;
    }
    if ((u8TempCond != OTS_PARAM_TEMP_COND_TN40) &&
        (u8TempCond != OTS_PARAM_TEMP_COND_T25) &&
        (u8TempCond != OTS_PARAM_TEMP_COND_T125))
    {
        return LL_ERR_INVD_PARAM;
    }

    /* 2. 执行校准实验(获取当前温度点的 A 参数) */
    i32Ret = OTS_ScalingExperiment(&u16Dr1, &u16Dr2, &u16Ecr, (s_u8CalibCnt == 0) ? &s_f32A1 : &s_f32A2, u32Timeout);
    if (i32Ret != LL_OK)
    {
        return i32Ret;
    }

    /* 3. 累计校准计数,若完成 2 个点则计算 K/M */
    s_u8CalibCnt++;
    if (s_u8CalibCnt >= 2)
    {
        // 示例:假设两个校准点为 25℃(A1)和 125℃(A2),计算 K = (T2-T1)/(A2-A1),M = T1 - K*A1
        float32_t f32T1 = 25.0F, f32T2 = 125.0F; // 需与实际校准温度对应
        if (s_f32A2 != s_f32A1)
        { // 避免除以零
            *pf32SlopeK = (f32T2 - f32T1) / (s_f32A2 - s_f32A1);
            *pf32OffsetM = f32T1 - (*pf32SlopeK) * s_f32A1;
        }
        else
        {
            i32Ret = LL_ERR_INVD_MD; // 校准数据异常
        }
        s_u8CalibCnt = 0; // 重置校准计数,支持下次校准
    }
    else
    {
        i32Ret = LL_OK; // 第一个点校准完成,等待第二个点
    }

    return i32Ret;
}



四、总结
HC32F460 的 OTS 模块为嵌入式系统提供了低成本、高集成度的温度监测方案。通过理解其半导体热敏原理、寄存器配置逻辑,结合 LL 库封装驱动,可快速实现温度采集功能。在实际应用中,需根据精度需求执行校准、优化采样策略,并关注低功耗设计,以充分发挥 OTS 模块的性能优势。如需进一步深入,可参考 HC32F460 参考手册第 17 章 “温度传感器(OTS)”,获取更详细的硬件时序与寄存器细节。
————————————————
版权声明:本文为CSDN博主「时光呀时光慢慢走」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/XdaDC/article/details/150773165

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

本版积分规则

85

主题

250

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部