我这边尝试在使用LSI的情况下运行低功耗,但似乎进入睡眠后没法被RTC唤醒,不知道是不是哪里需要改正?
我在数据手册中看到了CK32K这一低功耗配置项目,但是没有找到对应的寄存器,不知道是不是这个配置出现了问题?
然后就是 RB_PWR_LDO_EN 这个定义,在SDK里面也被注释掉了,请问是否是需要手动开启这一个呢?
我这边尝试在使用LSI的情况下运行低功耗,但似乎进入睡眠后没法被RTC唤醒,不知道是不是哪里需要改正?
我在数据手册中看到了CK32K这一低功耗配置项目,但是没有找到对应的寄存器,不知道是不是这个配置出现了问题?
然后就是 RB_PWR_LDO_EN 这个定义,在SDK里面也被注释掉了,请问是否是需要手动开启这一个呢?
尽量提供能复现问题的 工程,
官方的蓝牙工程都有用到RTC,在使能宏: HAL_SLEEP=TRUE 后, 都会用到rtc的触发唤醒.
可以参考ble的工程看看.
睡眠模式,RTC唤醒,在BLE例子都有使用,参考MCU.C例子。
/** * @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晶振,参考下图。
你好,我就是这么修改的,也是不行。
在CH573的EVT内的BLE文件内的工程Peripheral,如果开启内置晶振,即在工程中定义宏CLK_OSC32K=2
同时工程中定义宏HAL_SLEEP=TRUE,开启休眠模式,则BLE唤醒通过RTC唤醒的。
你可以研究一下此工程,然后再修改自己的工程。
如果后续还有问题,可以提供工程,并告知基于哪个工程修改,修改点列出来。
并告知具体自己的需求点。这样芯片原厂会告知此芯片最优实现办法。
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睡眠函数,如果不需要休眠,加上判断条件。直接退出,不执行休眠即可。如果需要休眠,就可以正常执行休眠。