CSDN专栏:
- 嵌入式程序开发实战
- 嵌入式双范式AI编程
- 嵌入式开发必掌握
- 嵌入式求职面试技术资料
第50讲:低功耗固件Spec——休眠条件、唤醒源、功耗约束
一、低功耗固件Spec的重要性
低功耗是电池供电设备的关键指标,必须通过Spec严格约束休眠和唤醒机制。
1.1 为什么需要低功耗Spec
原因一:电池寿命要求
电池寿命计算:
- 电池容量:1000mAh
- 平均功耗:1mA
- 电池寿命:1000小时≈42天
功耗降低10倍,电池寿命延长10倍
原因二:功耗优化复杂
功耗优化涉及:
- 硬件选择:低功耗器件
- 休眠模式:多种休眠模式选择
- 唤醒机制:唤醒源配置
- 软件优化:减少CPU运行时间
必须系统化设计,才能达到低功耗目标
原因三:功耗与功能平衡
功耗与功能矛盾:
- 休眠深:功耗低,但唤醒慢、功能受限
- 休眠浅:功耗高,但唤醒快、功能完整
必须根据应用场景选择合适的休眠模式
1.2 低功耗Spec的组成
二、休眠模式定义Spec
2.1 休眠模式定义Spec模板
## 休眠模式定义Spec ### 2.1 休眠模式类型 - DES-001:[休眠模式名称] - 模式类型:[睡眠/停止/待机] - 功耗:[功耗值] - 唤醒时间:[唤醒时间] - 可用功能:[可用功能列表] ### 2.2 休眠条件 - DES-002:休眠条件 - 条件1:[条件] - 条件2:[条件] - 条件3:[条件] ### 2.3 休眠进入流程 - DES-003:休眠流程 - 步骤1:[步骤] - 步骤2:[步骤] - 步骤3:[步骤]2.2 休眠模式定义Spec示例:STM32
示例一:STM32休眠模式
## 休眠模式定义Spec:STM32F103 ### 2.1 休眠模式类型 #### 2.1.1 睡眠模式(Sleep) - DES-001:睡眠模式 - 模式类型:睡眠模式(Sleep Mode) - 功耗:约2mA(@3.3V,72MHz) - 唤醒时间:<1us - 可用功能: - CPU停止运行 - 所有外设继续运行 - SRAM和寄存器内容保持 - 唤醒源:任何中断 #### 2.1.2 停止模式(Stop) - DES-002:停止模式 - 模式类型:停止模式(Stop Mode) - 功耗:约20uA(@3.3V) - 唤醒时间:约10us - 可用功能: - CPU停止运行 - 所有时钟停止 - SRAM和寄存器内容保持 - RTC、外部中断可用 - 唤醒源:外部中断、RTC闹钟、USB唤醒 #### 2.1.3 待机模式(Standby) - DES-003:待机模式 - 模式类型:待机模式(Standby Mode) - 功耗:约2uA(@3.3V) - 唤醒时间:约50ms - 可用功能: - CPU停止运行 - 所有时钟停止 - SRAM和寄存器内容丢失(除备份域) - 仅RTC、外部复位、WKUP引脚可用 - 唤醒源:WKUP引脚、RTC闹钟、外部复位、看门狗复位 ### 2.2 休眠条件 #### 2.2.1 睡眠模式条件 - DES-004:睡眠模式条件 - 条件1:无任务需要执行 - 条件2:等待中断唤醒 - 条件3:需要快速唤醒(<1us) #### 2.2.2 停止模式条件 - DES-005:停止模式条件 - 条件1:长时间无任务(>100ms) - 条件2:允许唤醒延迟(~10us) - 条件3:需要保持SRAM内容 #### 2.2.3 待机模式条件 - DES-006:待机模式条件 - 条件1:极长时间无任务(>1s) - 条件2:允许唤醒延迟(~50ms) - 条件3:允许SRAM内容丢失 ### 2.3 休眠进入流程 #### 2.3.1 睡眠模式流程 - DES-007:睡眠模式流程 ```c void Enter_Sleep_Mode(void) { // 清除SLEEPDEEP位 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; // 进入睡眠模式 __WFI(); // 或 __WFE() }2.3.2 停止模式流程
- DES-008:停止模式流程
voidEnter_Stop_Mode(void){// 关闭不必要的外设RCC->APB2ENR&=~(RCC_APB2ENR_IOPAEN|RCC_APB2ENR_IOPBEN);// 设置SLEEPDEEP位SCB->SCR|=SCB_SCR_SLEEPDEEP_Msk;// 选择电压调节器为低功耗模式PWR->CR|=PWR_CR_LPDS;// 进入停止模式__WFI();// 唤醒后:重新初始化时钟SystemClock_Config();}2.3.3 待机模式流程
- DES-009:待机模式流程
voidEnter_Standby_Mode(void){// 使能WKUP引脚PWR->CSR|=PWR_CSR_EWUP;// 清除唤醒标志PWR->CR|=PWR_CR_CWUF;// 设置SLEEPDEEP位SCB->SCR|=SCB_SCR_SLEEPDEEP_Msk;// 进入待机模式PWR->CR|=PWR_CR_PDDS;__WFI();// 唤醒后:系统复位,重新启动}## 三、唤醒源定义Spec ### 3.1 唤醒源定义Spec模板 ```markdown ## 唤醒源定义Spec ### 3.1 唤醒源类型 - DES-001:[唤醒源名称] - 唤醒源类型:[外部中断/RTC/串口/...] - 支持的休眠模式:[模式列表] - 唤醒延迟:[延迟时间] ### 3.2 唤醒条件 - DES-002:唤醒条件 - 触发条件:[条件] - 触发方式:[上升沿/下降沿/电平] ### 3.3 唤醒流程 - DES-003:唤醒流程 - 步骤1:[步骤] - 步骤2:[步骤] - 步骤3:[步骤]3.2 唤醒源定义Spec示例
示例一:外部中断唤醒
## 唤醒源定义Spec:外部中断唤醒 ### 3.1 唤醒源类型 - DES-001:EXTI0唤醒 - 唤醒源类型:外部中断(EXTI0) - 支持的休眠模式:睡眠模式、停止模式 - 唤醒延迟:<1us(睡眠模式),~10us(停止模式) ### 3.2 唤醒条件 - DES-002:唤醒条件 - 触发源:PA0引脚(按键) - 触发方式:上升沿(按键按下) ### 3.3 唤醒配置 - DES-003:唤醒配置代码 ```c void EXTI0_Wakeup_Init(void) { // 配置PA0为输入 RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; GPIOA->CRL &= ~GPIO_CRL_MODE0; // 输入模式 GPIOA->CRL &= ~GPIO_CRL_CNF0; // 浮空输入 // 配置EXTI0 RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI0_PA; // PA0 EXTI->IMR |= EXTI_IMR_IM0; // 使能中断线0 EXTI->RTSR |= EXTI_RTSR_RT0; // 上升沿触发 // 配置NVIC(停止模式唤醒不需要使能中断) // NVIC_EnableIRQ(EXTI0_IRQn); }**示例二:RTC闹钟唤醒** ```markdown ## 唤醒源定义Spec:RTC闹钟唤醒 ### 3.1 唤醒源类型 - DES-001:RTC闹钟唤醒 - 唤醒源类型:RTC闹钟 - 支持的休眠模式:睡眠模式、停止模式、待机模式 - 唤醒延迟:<1us(睡眠),~10us(停止),~50ms(待机) ### 3.2 唤醒条件 - DES-002:唤醒条件 - 触发源:RTC闹钟 - 触发方式:RTC计数器等于闹钟值 ### 3.3 唤醒配置 - DES-003:唤醒配置代码 ```c void RTC_Alarm_Wakeup_Init(void) { // 使能PWR和BKP时钟 RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN; // 使能RTC和备份域写访问 PWR->CR |= PWR_CR_DBP; // 配置RTC RCC->BDCR |= RCC_BDCR_RTCEN; // 使能RTC // 设置RTC预分频 RTC->PRLH = 0; RTC->PRLL = 32768 - 1; // 1Hz // 设置闹钟(10秒后唤醒) RTC->ALRH = 0; RTC->ALRL = RTC->CNTH << 16 | RTC->CNTL + 10; // 使能闹钟中断 RTC->CRH |= RTC_CRH_ALRIE; // 配置NVIC NVIC_EnableIRQ(RTCAlarm_IRQn); // 使能RTC闹钟唤醒(待机模式) PWR->CSR |= PWR_CSR_EWUP; }**示例三:串口唤醒** ```markdown ## 唤醒源定义Spec:USART唤醒 ### 3.1 唤醒源类型 - DES-001:USART唤醒 - 唤醒源类型:USART接收中断 - 支持的休眠模式:睡眠模式、停止模式 - 唤醒延迟:<1us(睡眠),~10us(停止) ### 3.2 唤醒条件 - DES-002:唤醒条件 - 触发源:USART接收寄存器非空 - 触发方式:接收到数据 ### 3.3 唤醒配置 - DES-003:唤醒配置代码 ```c void USART_Wakeup_Init(void) { // 配置USART USART1->CR1 |= USART_CR1_RXNEIE; // 使能接收中断 // 配置NVIC(停止模式唤醒需要使能中断) NVIC_EnableIRQ(USART1_IRQn); }## 四、功耗约束Spec ### 4.1 功耗约束Spec模板 ```markdown ## 功耗约束Spec ### 4.1 各模式功耗 - DES-001:[模式名称]功耗 - 典型功耗:[功耗值] - 最大功耗:[功耗值] - 测量条件:[条件] ### 4.2 平均功耗 - DES-002:平均功耗 - 计算方法:[方法] - 目标功耗:[目标值] - 实际功耗:[实际值] ### 4.3 峰值功耗 - DES-003:峰值功耗 - 峰值场景:[场景] - 峰值功耗:[功耗值] - 持续时间:[时间]4.2 功耗约束Spec示例
示例一:温湿度传感器节点功耗
## 功耗约束Spec:温湿度传感器节点 ### 4.1 各模式功耗 #### 4.1.1 运行模式功耗 - DES-001:运行模式功耗 - 典型功耗:10mA(@3.3V) - 最大功耗:15mA(@3.3V,全速运行) - 测量条件:CPU运行@72MHz,外设全开 #### 4.1.2 睡眠模式功耗 - DES-002:睡眠模式功耗 - 典型功耗:2mA(@3.3V) - 最大功耗:3mA(@3.3V) - 测量条件:CPU休眠,外设运行 #### 4.1.3 停止模式功耗 - DES-003:停止模式功耗 - 典型功耗:20uA(@3.3V) - 最大功耗:50uA(@3.3V) - 测量条件:CPU和时钟停止,RTC运行 #### 4.1.4 待机模式功耗 - DES-004:待机模式功耗 - 典型功耗:2uA(@3.3V) - 最大功耗:5uA(@3.3V) - 测量条件:仅RTC和WKUP引脚可用 ### 4.2 平均功耗计算 #### 4.2.1 工作模式 - DES-005:工作模式 - 采集周期:10秒 - 采集时间:100ms(读取传感器+发送数据) - 休眠时间:9.9秒(停止模式) #### 4.2.2 平均功耗计算 - DES-006:平均功耗 - 运行功耗:10mA × 100ms = 1mA·s - 休眠功耗:20uA × 9900ms = 198uA·s - 平均功耗:(1mA·s + 198uA·s) / 10s = 118uA - 目标功耗:<200uA - 结论:满足要求 #### 4.2.3 电池寿命估算 - DES-007:电池寿命 - 电池容量:1000mAh(CR2032) - 平均功耗:118uA - 电池寿命:1000mAh / 0.118mA ≈ 8475小时 ≈ 353天 - 目标寿命:>1年 - 结论:满足要求 ### 4.3 峰值功耗 #### 4.3.1 峰值场景 - DES-008:峰值场景 - 场景:发送数据时 - 峰值功耗:15mA(运行模式)+ 20mA(无线发送)= 35mA - 持续时间:50ms - 电源承受能力:需确保电源能提供35mA峰值电流五、低功耗策略Spec
5.1 低功耗策略Spec模板
## 低功耗策略Spec ### 5.1 外设管理 - DES-001:外设管理策略 - 策略:[策略描述] - 外设列表:[外设列表] - 管理方法:[方法] ### 5.2 时钟管理 - DES-002:时钟管理策略 - 策略:[策略描述] - 时钟配置:[配置] - 切换方法:[方法] ### 5.3 唤醒后处理 - DES-003:唤醒后处理 - 处理流程:[流程] - 恢复操作:[操作]5.2 低功耗策略Spec示例
示例一:外设管理策略
## 低功耗策略Spec:外设管理 ### 5.1 外设管理策略 - DES-001:外设管理策略 - 策略:进入休眠前关闭不必要的外设,唤醒后重新初始化 - 外设列表: - GPIO:保持必要引脚配置 - USART:休眠前关闭,唤醒后重新初始化 - SPI:休眠前关闭,唤醒后重新初始化 - I2C:休眠前关闭,唤醒后重新初始化 - ADC:休眠前关闭,唤醒后重新初始化 - TIM:保持RTC定时器,关闭其他定时器 ### 5.2 外设关闭代码 ```c void Disable_Peripherals(void) { // 关闭USART1 USART1->CR1 &= ~USART_CR1_UE; RCC->APB2ENR &= ~RCC_APB2ENR_USART1EN; // 关闭SPI1 SPI1->CR1 &= ~SPI_CR1_SPE; RCC->APB2ENR &= ~RCC_APB2ENR_SPI1EN; // 关闭I2C1 I2C1->CR1 &= ~I2C_CR1_PE; RCC->APB1ENR &= ~RCC_APB1ENR_I2C1EN; // 关闭ADC1 ADC1->CR2 &= ~ADC_CR2_ADON; RCC->APB2ENR &= ~RCC_APB2ENR_ADC1EN; // 关闭TIM2、TIM3 TIM2->CR1 &= ~TIM_CR1_CEN; TIM3->CR1 &= ~TIM_CR1_CEN; RCC->APB1ENR &= ~(RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN); }5.3 外设恢复代码
voidEnable_Peripherals(void){// 重新初始化外设USART_Init();SPI_Init();I2C_Init();ADC_Init();TIM_Init();}**示例二:时钟管理策略** ```markdown ## 低功耗策略Spec:时钟管理 ### 5.1 时钟管理策略 - DES-001:时钟管理策略 - 策略:运行时使用HSE+PLL(72MHz),休眠时切换到HSI(8MHz) - 时钟配置: - 运行时钟:HSE(8MHz)+ PLL(×9)= 72MHz - 休眠时钟:HSI(8MHz) - 切换方法:进入休眠前切换到HSI,唤醒后切换回PLL ### 5.2 时钟切换代码 ```c void Switch_To_HSI(void) { // 使能HSI RCC->CR |= RCC_CR_HSION; while ((RCC->CR & RCC_CR_HSIRDY) == 0); // 切换系统时钟到HSI RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_HSI; while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI); // 关闭PLL RCC->CR &= ~RCC_CR_PLLON; } void Switch_To_PLL(void) { // 使能HSE RCC->CR |= RCC_CR_HSEON; while ((RCC->CR & RCC_CR_HSERDY) == 0); // 配置PLL RCC->CFGR |= RCC_CFGR_PLLSRC; RCC->CFGR |= RCC_CFGR_PLLMULL9; // 使能PLL RCC->CR |= RCC_CR_PLLON; while ((RCC->CR & RCC_CR_PLLRDY) == 0); // 切换系统时钟到PLL RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_PLL; while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); }**示例三:唤醒后处理** ```markdown ## 低功耗策略Spec:唤醒后处理 ### 5.1 唤醒后处理流程 - DES-001:唤醒后处理流程 - 步骤1:恢复时钟(如果是停止模式) - 步骤2:重新初始化外设 - 步骤3:恢复系统状态 - 步骤4:执行唤醒任务 ### 5.2 唤醒处理代码 ```c void Wakeup_Handler(void) { // 判断唤醒源 if (PWR->CSR & PWR_CSR_WUF) { // 清除唤醒标志 PWR->CR |= PWR_CR_CWUF; // 恢复时钟 Switch_To_PLL(); // 重新初始化外设 Enable_Peripherals(); // 恢复系统状态 Restore_System_State(); // 执行唤醒任务 Execute_Wakeup_Task(); } }## 六、低功耗固件Spec完整示例 ### 6.1 完整低功耗固件Spec:温湿度传感器节点 ```markdown ## 低功耗固件Spec:温湿度传感器节点 ### 1. 休眠模式定义 #### 1.1 主要休眠模式 - DES-001:停止模式 - 模式类型:停止模式(Stop Mode) - 功耗:约20uA - 唤醒时间:约10us - 唤醒源:RTC闹钟 ### 2. 唤醒源定义 #### 2.1 RTC闹钟唤醒 - DES-002:RTC闹钟唤醒 - 唤醒周期:10秒 - 唤醒任务:读取传感器数据并发送 ### 3. 功耗约束 #### 3.1 目标功耗 - DES-003:目标功耗 - 平均功耗:<200uA - 电池寿命:>1年(CR2032电池) #### 3.2 实际功耗 - DES-004:实际功耗 - 运行功耗:10mA(100ms) - 休眠功耗:20uA(9.9s) - 平均功耗:118uA - 电池寿命:353天 ### 4. 低功耗策略 #### 4.1 外设管理 - DES-005:外设管理 - 休眠前关闭所有外设 - 唤醒后重新初始化必要外设 #### 4.2 时钟管理 - DES-006:时钟管理 - 休眠前切换到HSI(8MHz) - 唤醒后切换到PLL(72MHz) ### 5. 完整工作流程代码 ```c void LowPower_Main(void) { // 初始化 System_Init(); RTC_Alarm_Wakeup_Init(); while (1) { // 读取传感器数据 float temperature, humidity; SHT30_Read(&temperature, &humidity); // 发送数据 Wireless_Send(temperature, humidity); // 关闭外设 Disable_Peripherals(); // 切换到低频时钟 Switch_To_HSI(); // 设置RTC闹钟(10秒后唤醒) RTC_SetAlarm(10); // 进入停止模式 Enter_Stop_Mode(); // 唤醒后处理 // 恢复时钟 Switch_To_PLL(); // 重新初始化外设 Enable_Peripherals(); } }## 七、本讲核心要点 ### 7.1 记住这三句话 1. **低功耗Spec定义休眠机制:休眠模式、唤醒源、功耗约束、低功耗策略** 2. **选择合适休眠模式:平衡功耗、唤醒时间、功能可用性** 3. **功耗优化系统化:外设管理、时钟管理、唤醒后处理** ### 7.2 实践建议 **对于新手**: - 学习STM32低功耗模式 - 学习唤醒源配置 - 学习功耗测量方法 **对于有经验工程师**: - 建立低功耗Spec模板 - 使用Spec约束低功耗设计 - 使用Spec指导功耗优化 **对于团队负责人**: - 建立低功耗Spec编写规范 - 培训团队低功耗设计方法 - 建立功耗审查流程 ### 7.3 下讲预告 第51讲将详细讲解:**工控固件安全Spec:禁止野指针、禁止死循环、看门狗约束** 如何定义工控固件安全Spec、保证系统安全?下一讲将详细讲解。