This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TPS8802EVM:如何让 MCU 从睡眠状态唤醒到 TPS8802?

Guru**** 2410850 points
Other Parts Discussed in Thread: TPS8802

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/sensors-group/sensors/f/sensors-forum/1525987/tps8802evm-how-to-mcu-can-wakeup-from-sleep-to-tps8802-viceversa

器件型号:TPS8802EVM
主题中讨论的其他器件:TPS8802

工具/软件:

TI 团队大家好、

我指的是中所述的睡眠模式功能 TPS8802 AFE 数据表的第 8.4.1 节“睡眠模式“[第 40 页]。

我已将 TPS8802 配置为从睡眠模式转换 () SLEEP_EN = 1以唤醒模式 () SLEEP_DONE / SLEEP_EN = 0方法来实现的。

在此设置中、我将睡眠计时器设置为 10 秒。 这意味着 TPS8802 进入睡眠模式 (由显示的注册表表示) STATUS1VCCLOW等待 10 秒、然后自动唤醒 (显示)STATUS1SLP_DONE

MCU 持续监控 STATUS1用于检测从睡眠到唤醒的转换的寄存器。

启动时、MCU 会调用函数 afe_i2c_sleep_timer(10000)要配置睡眠计时器 10 秒 (10000ms)、请使用 TPS8802 数据表中指定的相应 I2C 寄存器设置。

计时器启动后、MCU 会重复调用 CheckSleepTimeExpiry()以读取 STATUS1寄存并监控睡眠至唤醒状态。

请参阅以下代码片段:

void CheckSleepTimeExpiry()
{
    static uint32_t elapsed_time = 0;
    int ret = 0;
    elapsed_time += 1000; // Assuming this function is called every 1 second (1000 ms)
    
    ret = afe_i2c_status_read_reg(TPS880X_REG_STATUS1);
    if(ret == SLP_DONE)
    {
        i2c_write_data(i2c_dev, TPS880X_REG_ENABLE2, 0x84); //SLP_EN = 0 
        StopI2CSleepTimer();
    }
    else if (elapsed_time >= SetSleeptime+5)
    {
        i2c_write_data(i2c_dev, TPS880X_REG_ENABLE2, 0x84); //SLP_EN = 0 
        StopI2CSleepTimer();
        elapsed_time = 0; // Reset the elapsed time
        printk("Abort Timer.\n");
    }
    printk("Elapsed time: %u ms\n", elapsed_time);
}

void afe_i2c_sleep_timer(uint16_t sleep_time)
{
    SetSleeptime = sleep_time;

    // Mask all interrupts, enable INT_MCU
    i2c_write_data(i2c_dev, TPS880X_REG_MASK, 0xFF);

    i2c_write_data(i2c_dev, TPS880X_REG_CONFIG1, 0x37); //SLP_MCU = SLP_ANALOG = SLP_BST = 1

    i2c_write_data(i2c_dev, TPS880X_REG_ENABLE1, 0x3D); // INT_EN = 1

    i2c_write_data(i2c_dev, TPS880X_REG_ENABLE2, 0x85); // SLP_EN = LEDPIN_EN = INT_DIR = LEDSEL = 1 

    if (sleep_time == 0) {
        // Disable the Sleep timer
        i2c_write_data(i2c_dev, TPS880X_REG_SLPTMR1, 0x00);
        i2c_write_data(i2c_dev, TPS880X_REG_SLPTMR2, 0x00);
    }
    else
    {
        // Validate interval
        if (sleep_time < DUALRAYSMOKEAFE_HAL_TIMING_ULPTIMER_MIN_INTERVAL_MS)
        {
            sleep_time = DUALRAYSMOKEAFE_HAL_TIMING_ULPTIMER_MIN_INTERVAL_MS;
        }
        else if (sleep_time > DUALRAYSMOKEAFE_HAL_TIMING_ULPTIMER_MAX_INTERVAL_MS)
        {
            sleep_time = DUALRAYSMOKEAFE_HAL_TIMING_ULPTIMER_MAX_INTERVAL_MS;
        }
    }
    // MSB
    i2c_write_data(i2c_dev, TPS880X_REG_SLPTMR1, sleep_time >> 8);
    // LSB
    i2c_write_data(i2c_dev, TPS880X_REG_SLPTMR2, sleep_time & 0xFF);

    k_timer_init(&si2cSleepTimer, &SleepTimerHandler, nullptr);
    k_timer_user_data_set(&si2cSleepTimer, nullptr);
	StartSleepTimerHandler();
}

uint8_t afe_i2c_status_read_reg(uint8_t reg_addr)
{
    int ret = 0;
    uint8_t status = 0;
    uint8_t status_val = 0;

    ret = i2c_reg_read_byte(i2c_dev, AFE_ADDR, reg_addr, &status);
    if (ret != 0)
    {
        printk("Failed to read Status register\n");
    }
    printk("Status Value: %d\n", status);

    if (reg_addr == TPS880X_REG_STATUS1){
        if (status & VCCLOW)
        {
            printk("VCCLOW\n");
            status_val = VCCLOW;
        }
        if (status & MCULDO_ERR)
        {
            printk("MCULDO_ERR\n");
            status_val = MCULDO_ERR;
        }
        if (status & OTS_ERR)
        {
            printk("OTS_ERR\n");
            status_val = OTS_ERR;
        }
        if (status & OTS_WRN)
        {
            printk("OTS_WRN\n");
            status_val = OTS_WRN;
        }
        if (status & BST_NACT)
        {
            printk("BST_NACT\n");
            status_val = BST_NACT;
        }
        if (status & BST_ERR)
        {
            printk("BST_ERR\n");
            status_val = BST_ERR;
        }
        if (status & INT_UNIT)
        {
            printk("INT_UNIT\n");
            status_val = INT_UNIT;
        }
        if (status & SLP_DONE)
        {
            printk("SLP_DONE\n");
            status_val = SLP_DONE;
        }
    }
    return status_val;
}

根据之前提供的代码、基于计时器的睡眠到唤醒功能按预期工作。


Q1:如何使用 TPS8802 中断引脚 (INT_MCU/GPIO) 配置 TPS8802 以唤醒 MCU?

在当前实现中、我通过写入 I2C 寄存器来启用中断、如下所示:

i2c_write_data(i2c_dev, TPS880X_REG_ENABLE1, 0x3D); // INT_EN = 1 (as per datasheet)

中断引脚连接:

TPS8802 (INT_MCU / GPIO) ----> MCU (GPIO Pin)

但是、当我尝试读取时 INT_MCU / GPIO 在 MCU 的相应 GPIO 引脚上、当 tps8802 将进入睡眠/唤醒时、我不会在 MCU GPIO 上收到任何状态更改。

您能否指导我了解触发中断信号并将其从 TPS8802 读取到 MCU 所需的正确配置或其他步骤?

问题 2:如何使用 MCU GPIO 引脚唤醒 TPS8802(从低电平到高电平转换)?

我还想配置相反方向的设置、MCU 可以使用其中一个 MCU GPIO 引脚通过从低电平切换至高电平来唤醒 TPS8802。

请建议支持此功能所需的正确寄存器设置或硬件配置。

此致、
Pratik Panchal   

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Pratik:

    感谢您为您的问题提供详细信息和背景信息。  

    相关问题 问题 1 ,您使用的代码是屏蔽在 afe_i2c_sleep_timer() 函数开头附近的所有中断。  如果您想查看 来自 TPS8802 的唤醒标志、您还需要取消屏蔽地址 0x03 处掩码寄存器中的 SLP_DONEM 位 7。   更多信息、请参阅数据表第 8.3.12 节和第 8.6.4 节。

    相关问题 Q2 、为了使 MCU 中断 TPS8802、  在这些情况下、代码需要设置 INT_EN = 1 和 INT_DIR = 1。  INT_DIR 是地址 0x07 的 ENABLE2 寄存器中的位 3。  数据表第 8.3.7 节、INT_MCU 引脚上互连驱动程序的说明和第 8.3.12 节简要介绍了该特性。

    此致、

    Jesse

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Jesse、

    感谢您的答复。

    根据您的建议、我更新了中的寄存器设置 afe_i2c_sleep_timer()功能如下:

        // Mask all interrupts, enable INT_MCU
        i2c_write_data(i2c_dev, TPS880X_REG_MASK, 0xFF);
    
        i2c_write_data(i2c_dev, TPS880X_REG_CONFIG1, 0x37); //SLP_MCU = SLP_ANALOG = SLP_BST = 1
    
        i2c_write_data(i2c_dev, TPS880X_REG_ENABLE1, 0x3D); // INT_EN = 1
    
        i2c_write_data(i2c_dev, TPS880X_REG_ENABLE2, 0x8D); // SLP_EN = LEDPIN_EN = INT_DIR = LEDSEL = 1 

    唤醒后,我更新了SLP_DONEMMASK寄存器(地址)中的位0x03,如下所示:

    i2c_write_data(i2c_dev, TPS880X_REG_ENABLE2, 0x8C); //SLP_EN = 0 
    i2c_write_data(i2c_dev, TPS880X_REG_MASK, 0x7F); // SLP_DONEM = 0
     

    但是、我仍然没有收到 TPS8802 的任何中断或状态变化 GPIO/INT_MCU 引脚上保持高电平。 我正在主动监控 MCU 上的相应 GPIO 引脚、但未观察到信号活动。

    请在下面找到控制台输出以供您参考、并
    查看 INT_STATUS 打印、用于监视 INT_MCU/GPIO
    在这两种情况下、 INT_STATUS 变为 0 。 另请查看 STATUS_1 睡眠获取时的寄存器位 VCCLOW 唤醒超时计时的函数 SLP_DONE



    此致、
    Pratik Panchal

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Jesse、

    只是一个温和的提醒—您能花一点时间解决我的问题吗?

    此致、
    Pratik Panchal

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Pratik:

    很抱歉、延迟的回复。  

    为了让 MCU 看到 MCU_INT 上的 SLP_DONE 中断、TPS8802 需要 在中断屏蔽寄存器中显示 SLP_DONEM = 0 和 STATUS_INT = 1、以及 enable1 寄存器中的 IINT_DIR = 0。

    如果在设置 SLP_EN = 1 之前设置睡眠计时器寄存器值、您应该会在持续时间完成时看到 TPS8802 唤醒、并且 MCU 将通过 INT_MCU 上出现的中断收到通知。  然后、您 无需设置 SLP_EN = 0 即可强制 TPS8802 唤醒。

    下面是一个示例,说明我如何更改 afe_i2c_sleep_timer (),假设我了解如何在您的上下文中调用函数:

    void afe_i2c_sleep_timer(uint16_t sleep_time)
    {
        SetSleeptime = sleep_time;
    
        // Mask all interrupts, enable INT_MCU
        i2c_write_data(i2c_dev, TPS880X_REG_MASK, 0x7F); // SLP_DONEM = 0, STATUS_INT = 1 allows SLP_DONE flag to appear on INT_MCU pin
    
        i2c_write_data(i2c_dev, TPS880X_REG_CONFIG1, 0x37); //SLP_MCU = SLP_ANALOG = SLP_BST = 1
    
        i2c_write_data(i2c_dev, TPS880X_REG_ENABLE1, 0x1D); // INT_EN = 0
    
        // Set the sleep timer before setting SLP_EN:
    
        if (sleep_time == 0) {
            // Disable the Sleep timer
            i2c_write_data(i2c_dev, TPS880X_REG_SLPTMR1, 0x00);
            i2c_write_data(i2c_dev, TPS880X_REG_SLPTMR2, 0x00);
        }
        else
        {
            // Validate interval
            if (sleep_time < DUALRAYSMOKEAFE_HAL_TIMING_ULPTIMER_MIN_INTERVAL_MS)
            {
                sleep_time = DUALRAYSMOKEAFE_HAL_TIMING_ULPTIMER_MIN_INTERVAL_MS;
            }
            else if (sleep_time > DUALRAYSMOKEAFE_HAL_TIMING_ULPTIMER_MAX_INTERVAL_MS)
            {
                sleep_time = DUALRAYSMOKEAFE_HAL_TIMING_ULPTIMER_MAX_INTERVAL_MS;
            }
        }
        // MSB
        i2c_write_data(i2c_dev, TPS880X_REG_SLPTMR1, sleep_time >> 8);
        // LSB
        i2c_write_data(i2c_dev, TPS880X_REG_SLPTMR2, sleep_time & 0xFF);
    
        i2c_write_data(i2c_dev, TPS880X_REG_ENABLE2, 0x85); // Put TPS8802 to sleep with SLP_EN = 1, LEDPIN_EN = LEDSEL = 1, INT_DIR = 0
        
        k_timer_init(&si2cSleepTimer, &SleepTimerHandler, nullptr);
        k_timer_user_data_set(&si2cSleepTimer, nullptr);
    	StartSleepTimerHandler();
    }
    

    希望这有所帮助。  如果您仍然遇到问题、请告诉我。

    此致、

    Jesse

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Jesse、

    感谢您的答复。

    根据您的建议、它运行良好。
    每当计时器到期且 TPS8802 唤醒或触发时 SLP_DONEINT_MCU会相应地设置该位。

    INT_STATUS: 0
    Status Value: 0
    re-start tps8802 sleep...
    Sleep Timer Start...
    Elapsed time: 0 ms
    
    INT_STATUS: 0
    Status Value: 64
    VCCLOW
    Elapsed time: 1000 ms
    
    INT_STATUS: 0
    Status Value: 64
    VCCLOW
    Elapsed time: 2000 ms
    
    INT_STATUS: 0
    Status Value: 64
    VCCLOW
    Elapsed time: 3000 ms
    
    INT_STATUS: 0
    Status Value: 64
    VCCLOW
    Elapsed time: 4000 ms
    
    INT_STATUS: 0
    Status Value: 64
    VCCLOW
    Elapsed time: 5000 ms
    
    INT_STATUS: 0
    Status Value: 64
    VCCLOW
    Elapsed time: 6000 ms
    
    INT_STATUS: 0
    Status Value: 64
    VCCLOW
    Elapsed time: 7000 ms
    
    INT_STATUS: 0
    Status Value: 64
    VCCLOW
    Elapsed time: 8000 ms
    
    INT_STATUS: 0
    Status Value: 64
    VCCLOW
    Elapsed time: 9000 ms
    
    INT_STATUS: 1          <------ Yes, INT_MCU gives high bit to MCU 
    Status Value: 192
    VCCLOW
    SLP_DONE
    Elapsed time: 10000 ms
    
    INT_STATUS: 0
    Status Value: 0
    re-start tps8802 sleep...
    Sleep Timer Start...
    Elapsed time: 0 ms
     

    现在、使用从 TPS 唤醒到 MCU INT_MCU中断按预期运行。

    但是、在相反的方向(当 TPS 处于睡眠模式且 MCU 需要将其唤醒)时
    需要进行哪些配置更改? 我们如何执行该 POC?

    如果可能、请提供代码片段。

    此致、
    Pratik Panchal

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Pratik:
    请尝试我在上一个答复中的建议:


    为了让 MCU 中断 TPS8802、代码需要设置 INT_EN = 1 和 INT_DIR = 1。    数据表第 8.3.7 节说明了互连 的功能、   第 8.3.12 节末尾介绍了互连驱动器方向。

    // Put TPS8802 to sleep with the ability to be awakend by the MCU:
    i2c_write_data(i2c_dev, TPS880X_REG_ENABLE1, 0x3D); // INT_EN = 1 (enable interconnect)
    i2c_write_data(i2c_dev, TPS880X_REG_ENABLE2, 0x8D); // Put TPS8802 to sleep with SLP_EN = LEDPIN_EN = LEDSEL = INT_DIR = 1 (sets direction of interrupt from MCU to TPS8802)
    
    

    此致、

    Jesse

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Jesse、

    感谢您的答复。

    根据您的建议、我已将配置更新为设置INT_EN = 1INT_DIR = 1

    目前、我使用基于计时器的睡眠方法、其中 TPS8802 AFE 进入 10 秒睡眠模式。 计时器到期后、STATUS_1寄存器会正确报告SLP_DONE

    现在、我想执行 POC、看看是否可以在使用INT_MCU引脚完成 10 秒睡眠持续时间之前唤醒 TPS8802。 此引脚连接到 MCU 的 1.8V VDD、并可在睡眠期间被驱动为高电平(手动连接)。 【同样,我尝试过但不起作用,像往常一样唤醒定义的到期时间】

    在该 POC 中、我预计、如果INT_MCU在 10 秒计时器到期之前将引脚置为有效、则 STATUS_1寄存器应立即指示SLP_DONE为早期唤醒响应。

    问题 1.

    这种方法是否可行? 如果我的理解不正确、请纠正我。

    问题 2.

    您能建议一种替代方法吗? 具体来说、是否可以在不使用睡眠计时器的情况下直接将 TPS8802 AFE 置于睡眠模式、并使用INT_MCU引脚上来自 MCU 的高电平信号将其唤醒?

    请提供您的建议。

    此致、
    Pratik


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Pratik:

    A.1:  请参阅介绍睡眠模式状态图的数据表第 8.4.1 节中的图 15。  TPS8802 睡眠功能旨在与睡眠计时器一起使用、并响应到期计时器或 SLP_EN = 0。  (当 INT_EN = INT_DIR = 1 时、INT_MCU 是互连的输入、并输出到 INT_UNIT、旨在将来自 MCU 的中断信号从一个 TPS8802 传递到市电有线烟雾报警系统中的其他警报。)

    A.2: 您询问的方法不具有数据表第 8.4.1 节要点中提到的睡眠模式的所有优势(务必仔细考虑这些优势)、但如果这适合您的用例 、另一种方法是 使用寄存器位禁用 MCU 功能、然后通过让 MCU 使用寄存器写入启用这些功能来重新启用这些功能。

    此致、

    Jesse

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Jesse、

    感谢您的答复。

    关于 A.1 点 、根据我的理解、当我们INT_MCU从 MCU 将引脚驱动为高电平时、INT_UNIT也会输出一个高电平信号。 您能否确认此理解是否正确?

    但是、在我们的应用中、我们不需要互连或一次性功能。 我们的主要需求是使用 MCU GPIO 中断将 TPS8802 从睡眠模式唤醒。 您能否请指导我们如何配置此唤醒机制、特别是在 MCU 端、而不涉及互连功能?

    关于 A.2 点、 您提到了一种涉及 MCU 启用或禁用特定寄存器位的替代方法(不使用基于计时器的睡眠模式)。 您能否说明一下您所指的确切寄存器? 此外、您注意到、第 8.4.1 节中列出的功能可能没有任何显著优势。 请确认我们是否应该完全放弃这种方法、或者如果这 种方法仍然可行、请就如何正确实施这种方法提出建议。

    此致、
    Pratik Panchal

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Pratik:

    A.1 的后续行动:  正确。  如数据表第 8.4.1 节(以及图 15 所示)所述、睡眠模式会唤醒至到期计时器或清除 SLP_EN 位、就像您之前使用的那样强制 TPS8802 唤醒。

    A.2 的后续行动:   enable1、ENABLE2 和控制寄存器为器件特性提供 I2C 控制、这些器件特性通常会禁用睡眠模式、如图 8 所示。  您可以在不使用睡眠模式的情况下手动禁用它们。  第 8.4.1 节文本介绍了使用 TPS8802 睡眠模式的好处、以及为什么用替代方法可以消耗更多功率:

    睡眠模式通过三种方式降低功耗:
    •以及快速禁用模拟块来降低功耗
    •在睡眠模式下关断升压和 MCU LDO
    •使 MCU 进入其最低功耗空闲状态


    每个 I2C 事务都需要时间并消耗少量功耗。 SLP_ANALOG 位用于配置
    进入睡眠模式时、睡眠模式可同时禁用高功率放大器和驱动器。 减少
    功能可以节省几个 I2C 事务、并缩短放大器和驱动器完全启用的时间。
    当微控制器执行检测和操作时、该器件可能需要升压转换器和 MCU LDO
    测试操作、但在微控制器处于空闲状态时可能不需要升压和 MCU LDO。
    SLP_BST 和 SLP_MCU 在睡眠模式期间禁用升压转换器和 MCU LDO。 这对于升压转换器来说很重要
    且 MCU LDO 之前已启用、在退出睡眠模式时将重新启用它们。 减少
    在防止系统欠压的同时、MCU LDO 和升压转换器引起的系统电流消耗
    如果 MCU 断电、由于退出睡眠模式会将电力返回给 MCU。

    在睡眠模式运行期间、MCU 可以进入其最低功耗空闲状态并监控的 GPIO 引脚
    SLP_DONE 中断信号。 该监控允许在睡眠计时器发出信号时禁用 MCU 时钟
    以在精确的编程时间后唤醒。

    我将让区域团队通过电子邮件与您联系以继续此讨论。  

    此致、

    Jesse