CH573使用内置RC振荡器的低功耗问题

我这边尝试在使用LSI的情况下运行低功耗,但似乎进入睡眠后没法被RTC唤醒,不知道是不是哪里需要改正?


我在数据手册中看到了CK32K这一低功耗配置项目,但是没有找到对应的寄存器,不知道是不是这个配置出现了问题?

然后就是 RB_PWR_LDO_EN 这个定义,在SDK里面也被注释掉了,请问是否是需要手动开启这一个呢?

尽量提供能复现问题的 工程,

官方的蓝牙工程都有用到RTC,在使能宏: HAL_SLEEP=TRUE  后, 都会用到rtc的触发唤醒.

可以参考ble的工程看看.


睡眠模式,RTC唤醒,在BLE例子都有使用,参考MCU.C例子。

image.png


/**
 * @brief 初始化蓝牙协议栈
 * 
 */
static void BLE_Init(void)
{
    bleConfig_t cfg = {
        .MEMAddr = (uint32_t)BLE_Stack_Heap,
        .MEMLen = BLE_MEMHEAP_SIZE,
        .SNVAddr = BLE_SNV_ADDR,
        .SNVBlock = 0, // Default: 512
        .SNVNum = 0, // Default: 1
        .BufMaxLen = BLE_BUFF_MAX_LEN,
        .BufNumber = BLE_BUFF_NUM,
        .TxNumEvent = BLE_TX_NUM_EVENT,
        .TxPower = BLE_TX_POWER,
        .RxNumEvent = 0, // Default: same as BufNumber
        .readFlashCB = Lib_Read_Flash,
        .writeFlashCB = Lib_Write_Flash,
#if (CLK_OSC32K)
        .SelRTCClock = (uint32_t)CLK_OSC32K,
#else
        .SelRTCClock = 0, // Use LSE, BLE use RTC Timer
#endif
        .ConnectNumber = (PERIPHERAL_MAX_CONNECTION & 3) | (CENTRAL_MAX_CONNECTION << 2),
        .WindowWidening = 0, // Default
        .WaitWindow = 0, // Default
        .srandCB = SYS_GetSysTickCnt, // HAL提供的函数
        .tsCB = HAL_GetInterTempValue, // 根据温度变化校准RF和内部RC( 大于7摄氏度 )
#if (CLK_OSC32K)
        .rcCB = Lib_Calibration_LSI, // HAL提供的函数
#else
        .rcCB = NULL, // 使用外部时钟,不需要校准
#endif
        .staCB = NULL, // 无状态Callback
#if (defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE)
        .WakeUpTime = WAKE_UP_RTC_MAX_TIME,
        .sleepCB = CH57X_LowPower, // 启用睡眠,HAL提供的函数
#else
        .WakeUpTime = 0,
        .sleepCB = NULL,
#endif

    };

    if (tmos_memcmp(VER_LIB, VER_FILE, strlen(VER_FILE)) == FALSE) {
        PRINT("BLE Library version is not compatable. Require %s, but %s.\r\n", VER_FILE, VER_LIB);
        while (1)
            ;
    }

    SysTick_Config(SysTick_LOAD_RELOAD_Msk);
    PFIC_DisableIRQ(SysTick_IRQn);

    // 填充芯片的MacAddr
    uint8_t MacAddr[6];
    GetMACAddress(MacAddr);
    for (uint8_t i = 0; i < 6; i++)
        cfg.MacAddr[i] = MacAddr[i]; // 使用芯片mac地址

    // Sanity Check
    if (!cfg.MEMAddr || cfg.MEMLen < 4 * 1024)
        while (1)
            ;

    FLASH_ROM_LOCK(0);
    uint8_t ret = BLE_LibInit(&cfg);
    if (ret) {
        PRINT("LIB init error. Code: %x ...\r\n", ret);
        while (1)
            ;
    }
}

/**
 * @brief 主函数
 * 
 * @return int 
 */
int main(void)
{
    PWR_DCDCCfg(ENABLE);
    SetSysClock(CLK_SOURCE_PLL_32MHz);
#ifdef DEBUG
    GPIOA_SetBits(bTXD1);
    GPIOA_ModeCfg(bTXD1, GPIO_ModeOut_PP_5mA);
    UART1_DefInit();
    uint8_t str[] = "Hello world.\r\n";
    UART1_SendString(str, sizeof(str));
#endif
    PRINT("Build on %s %s\r\n", __DATE__, __TIME__);
    PRINT("%s\r\n", VER_LIB);
    BLE_Init();
    HAL_Init(); // HAL提供的函数
    // ...
    Main_Circulation();
}


部分初始化代码见上方,如果需要完整工程的话我这边也可以提供。

我这边观察到的问题是,如果设置了CLK_OSC32K=1或2的话,就会出现睡眠下去后没办法自动唤醒;而如果保持CLK_OSC32K=0,那么在睡眠唤醒几次后也会无法自动唤醒。




请右击工程,修改内置低频32K晶振,参考下图。

image.png


你好,我就是这么修改的,也是不行。


在CH573的EVT内的BLE文件内的工程Peripheral,如果开启内置晶振,即在工程中定义宏CLK_OSC32K=2

同时工程中定义宏HAL_SLEEP=TRUE,开启休眠模式,则BLE唤醒通过RTC唤醒的。

你可以研究一下此工程,然后再修改自己的工程。

image.png


如果后续还有问题,可以提供工程,并告知基于哪个工程修改,修改点列出来。

并告知具体自己的需求点。这样芯片原厂会告知此芯片最优实现办法。


OK,我这边现在定位问题到了USB上,好像是启用了USB之后就出现了这种问题,我把USB相关的代码注释掉后就没有这种问题了。请问一下USB和睡眠是否有冲突需要手动处理呢?


是的,BLE的休眠唤醒源是RTC,在休眠过程中,USB无法运行。

你可以给我私发一下邮箱,给你一个BLE和USB共同运行的例程。


你好,邮箱已经私发了。也就是说,开着USB的情况下是没办法进入低功耗模式的对吗?


-------


更新:是我USB中断处理的问题。我在USB BUS Reset的时候添加了PRINT打印事件。我关掉这个之后就能正常唤醒了。多谢上面的几位技术人员帮我一起找BUG


@zpf_wch 你好,你们的USB和蓝牙同时工作的案例是没有低功耗管理的,请问有带低功耗管理的例子吗?


用USB功能是没法低功耗的,开了低功耗USB这边就没法工作了。


那么,有什么办法能在低功耗的时候检测USB插入然后退出低功耗模式吗?


用USB功能是没法低功耗的,开了低功耗USB这边就没法工作了。

--------------------------------------------------

实际产品里同时用到USB和BLE,还得需要低功耗怎么办?

使用场景是:USB接入的时候不需要低功耗,但是USB断开,BLE工作的时候需要低功耗模式,那么当USB再次接入的时候,

如果判断USB插入了呢?需要在判断出USB插入后,退出低功耗模式,同时还要保证BLE工作在低功耗模式下,当USB插入时可以正常枚举、识别。



我的使用是:当USB断开的时候,进入到低功耗,USB如果连接的话不进低功耗的。

但是现在遇到一个问题,我把HAL_SLEEP宏打开之后,USB断开之后,没有suspend中断产生,这样就没法判断出usb断了这个动作,请问是什么原因? 我测试发现,如果HAL_SLEEP宏不打开,USB断开之后,有suspend中断产生,我是能判断出断开这种状态的。


suspend 中断来判断USB连接和移除是不够的,在枚举过程中都会多次参数suspend,甚至电脑休眠,也会产生suspend
除了判断suspend外,判断USB是否在正常工作,可以根据设备是否有规律的周期通讯。
开启HAL_SLEEP ,实际要休眠的时候会进sleep睡眠函数,如果不需要休眠,加上判断条件。直接退出,不执行休眠即可。如果需要休眠,就可以正常执行休眠。


只有登录才能回复,可以选择微信账号登录