我所知道的EC====>Deep Sleep Mode

本文介绍了深度休眠模式(DeepSleepMode),一种用于延长笔记本电脑电池续航的技术。当设备处于关机状态时,该模式通过减少能耗来节省电力。文章详细解释了深度休眠的工作原理及其实施方式。

Deep Sleep Mode

  1. What’s this?

 

  顾名思义Deep Sleep Mode指的就是深度休眠。如同动物的冬眠一样,深度休眠就是为了节省能量,保存实力;待到寒冬过去,就能够重新恢复精力继续战斗J,啰嗦了这么多,其实就是为了NB电池省电。大家都知道衡量NB的性能品质,电池的续航能力是一个重要的指标,所以EC FW就要运用各种方法节省电源保持电池的续航能力。

 

  1. How to implement this 

 

  什么时候需要深度休眠呢?答案是在S4/S5的状况下。如果这时只有电池在那么EC FW将会在若干秒以后将会让8051进入Deep Sleep Mode,在进入之前EC FW将会备份各个部分的寄存器内容,清掉pending flags,关掉中断;然后设置可以让FW唤醒的中断源;上述工作全部结束以后EC就进入了Deep Sleep Mode,这时EC的能耗就极低了。

  在满足一定条件的外部事件触发之后,EC FW将会从Deep Sleep Mode中醒来,继续工作了。讲到这里,我想起了以前做过的一个专案,Power team量测发现,机器关机放个一个晚上回来就没有电了,我是觉得不可思议因为量测下来电都掉了,SUS电也没了,最后接上串口debug卡就发现FW老是在进出Deep Sleep Mode,经过更深入的研究发现CIR的中断没有disable,外围线路会有干扰导致CIR 中断不断的被触发。最后将CIR的中断关掉以后就OK了。         

 

 

Peter

#include <SPI.h> #include <BLEDevice.h> #include <BLE2902.h> #include <Arduino.h> // ==================== 引脚定义 ==================== #define SCK_PIN 13 #define MISO_PIN 11 #define MOSI_PIN 14 #define CS_PIN 12 // ==================== 启用调试模式 ==================== #define DEBUG_GMD1032 // ==================== GMD1032 命令列表 ==================== const uint16_t CMD_START_MEASUREMENT = 0x2A16; const uint16_t CMD_CLEAR_ADC_RESULTS = 0x243C; const uint16_t CMD_READ_CFG0 = 0xC08E; const uint16_t CMD_READ_STS0 = 0xC9B1; // CELL 分组命令 const uint16_t CMD_READ_CELL_1_3 = 0xD0FE; const uint16_t CMD_READ_CELL_4_6 = 0xD1F9; const uint16_t CMD_READ_CELL_7_9 = 0xD2F0; const uint16_t CMD_READ_CELL_10_12 = 0xD3F7; const uint16_t CMD_READ_CELL_13_15 = 0xD4E2; const uint16_t CMD_READ_CELL_16_18 = 0xD5E5; // DIS 分组命令(暂未使用) const uint16_t CMD_READ_DIS_1_3 = 0xD6EC; const uint16_t CMD_READ_DIS_4_6 = 0xD7EB; const uint16_t CMD_READ_DIS_7_9 = 0xD8C6; const uint16_t CMD_READ_DIS_10_12 = 0xD9C1; const uint16_t CMD_READ_DIS_13_15 = 0xDAC8; const uint16_t CMD_READ_DIS_16_18 = 0xDBCF; // 其他测量命令 const uint16_t CMD_READ_VREF2_V3 = 0xDFD3; const uint16_t CMD_READ_V5_DIETEMP_VSTK = 0xE06E; // ==================== SPI 设置 ==================== SPISettings spiSettings(1000000, MSBFIRST, SPI_MODE3); // 1MHz, Mode3 (CPOL=1, CPHA=1) // ==================== BLE 配置 ==================== #define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b" #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8" BLECharacteristic* pCharacteristic = nullptr; bool deviceConnected = false; // 共享变量:存储原始 ADC 值(不再转 float) uint16_t sharedCellRaw[16] = {0}; uint16_t sharedDieTempRaw = 0; portMUX_TYPE sensorMutex = portMUX_INITIALIZER_UNLOCKED; // 保护共享数据 // 回调类声明 class MyServerCallbacks : public BLEServerCallbacks { void onConnect(BLEServer* pServer) override { deviceConnected = true; Serial.println("设备接入~"); } void onDisconnect(BLEServer* pServer) override { deviceConnected = false; Serial.println("设备断开~"); pServer->startAdvertising(); // 重新开始广播 } }; class MyCharacteristicCallbacks : public BLECharacteristicCallbacks { void onWrite(BLECharacteristic* pCharacteristic) override { std::string value = pCharacteristic->getValue(); if (!value.empty()) { Serial.print("特征值已更新,新值为: "); Serial.println(value.c_str()); } } }; // ==================== 唤醒芯片 ==================== void wakeUpGMD1032() { SPI.beginTransaction(spiSettings); digitalWrite(CS_PIN, LOW); delayMicroseconds(10); SPI.transfer(0x00); digitalWrite(CS_PIN, HIGH); SPI.endTransaction(); delay(5); } // ==================== 发送命令 ==================== bool sendCommand(uint16_t command) { SPI.beginTransaction(spiSettings); digitalWrite(CS_PIN, LOW); SPI.transfer16(command); digitalWrite(CS_PIN, HIGH); SPI.endTransaction(); return true; } // ==================== 解析逆序字段 ==================== void parseReverseFields(uint8_t* buffer, uint16_t* results, int count) { for (int i = 0; i < count; i++) { int bufIdx = i * 2; results[count - 1 - i] = (buffer[bufIdx] << 8) | buffer[bufIdx + 1]; } } // ==================== 读取所有 CELL 原始值 ==================== bool readAllCellRawValues(uint16_t* cellRaw) { const uint16_t cmds[] = { CMD_READ_CELL_1_3, CMD_READ_CELL_4_6, CMD_READ_CELL_7_9, CMD_READ_CELL_10_12, CMD_READ_CELL_13_15, CMD_READ_CELL_16_18 }; const int groupCount = 6; const int perGroup[] = {3, 3, 3, 3, 3, 3}; SPI.beginTransaction(spiSettings); for (int g = 0; g < groupCount; g++) { digitalWrite(CS_PIN, LOW); SPI.transfer16(cmds[g]); uint8_t buffer[8]; for (int i = 0; i < 8; i++) { buffer[i] = SPI.transfer(0x00); } digitalWrite(CS_PIN, HIGH); uint16_t raw[3]; parseReverseFields(buffer, raw, perGroup[g]); for (int i = 0; i < perGroup[g]; i++) { int idx = g * 3 + i; if (idx >= 16) continue; cellRaw[idx] = raw[i]; } } SPI.endTransaction(); return true; } // ==================== 读取 DieTemp 原始值 ==================== bool readDieTempRaw(uint16_t* raw_dieTemp) { uint8_t buffer[8]; SPI.beginTransaction(spiSettings); digitalWrite(CS_PIN, LOW); SPI.transfer16(CMD_READ_V5_DIETEMP_VSTK); for (int i = 0; i < 8; i++) { buffer[i] = SPI.transfer(0x00); } digitalWrite(CS_PIN, HIGH); SPI.endTransaction(); *raw_dieTemp = (buffer[2] << 8) | buffer[3]; // 大端格式 return true; } // ==================== 更新 BLE 特征值(发送二进制原始数据)==================== void updateBLECharacteristic() { uint8_t binBuffer[34]; // 16 cell * 2 + 1 temp * 2 = 34 bytes // 安全拷贝共享数据(加锁) portENTER_CRITICAL(&sensorMutex); for (int i = 0; i < 16; i++) { binBuffer[i * 2] = (sharedCellRaw[i] >> 8) & 0xFF; // 高字节 binBuffer[i * 2 + 1] = sharedCellRaw[i] & 0xFF; // 低字节 } binBuffer[32] = (sharedDieTempRaw >> 8) & 0xFF; binBuffer[33] = sharedDieTempRaw & 0xFF; portEXIT_CRITICAL(&sensorMutex); // 发送二进制数据包 if (pCharacteristic && deviceConnected) { pCharacteristic->setValue(binBuffer, 34); pCharacteristic->notify(); // 触发通知给客户端 } #ifdef DEBUG_GMD1032 Serial.print("BLE Raw Data Sent (hex): "); for (int i = 0; i < 34; i++) { Serial.printf("%02X ", binBuffer[i]); } Serial.println(); #endif } // ==================== 核心 0:传感器采集任务 ==================== void sensorTask(void *parameter) { for (;;) { yield(); // 让出时间片 wakeUpGMD1032(); delay(2); sendCommand(CMD_START_MEASUREMENT); delay(10); // 等待转换完成 uint16_t cellRaw[16] = {0}; uint16_t dieTempRaw = 0; readAllCellRawValues(cellRaw); readDieTempRaw(&dieTempRaw); // 写入共享变量(加锁) portENTER_CRITICAL(&sensorMutex); memcpy(sharedCellRaw, cellRaw, sizeof(cellRaw)); sharedDieTempRaw = dieTempRaw; portEXIT_CRITICAL(&sensorMutex); #ifdef DEBUG_GMD1032 Serial.println("============== GMD1032 原始 ADC 数据 =============="); for (int i = 0; i < 16; i++) { if (i % 4 == 0) Serial.print(" "); Serial.printf("CELL%2d:%5d ", i + 1, cellRaw[i]); if ((i + 1) % 4 == 0 || i == 15) Serial.println(); } Serial.printf("DieTemp Raw: %d\n", dieTempRaw); Serial.println("---------------------------------------------"); #endif delay(1000); // 每秒采集一次 } } // ==================== 核心 1:BLE 服务任务 ==================== void bleTask(void *parameter) { BLEDevice::init("GMD1032-BLE-Slave"); bool mtuSet = BLEDevice::setMTU(256); Serial.printf("MTU 设置 %s\n", mtuSet ? "成功" : "失败"); BLEServer* pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); BLEService* pService = pServer->createService(SERVICE_UUID); pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY ); pCharacteristic->addDescriptor(new BLE2902()); // 支持 Notify pCharacteristic->setCallbacks(new MyCharacteristicCallbacks()); pCharacteristic->setValue("Ready"); // 初始值 pService->start(); BLEAdvertising* pAdvertising = pServer->getAdvertising(); pAdvertising->addServiceUUID(SERVICE_UUID); pAdvertising->start(); Serial.println("BLE 广播已启动,等待连接... (运行于 Core 1)"); for (;;) { if (deviceConnected) { updateBLECharacteristic(); } delay(1000); // 每秒尝试推送一次(与 sensorTask 同步) } } // ==================== setup() ==================== void setup() { Serial.begin(115200); while (!Serial && millis() < 3000); #ifdef DEBUG_GMD1032 Serial.println("[DEBUG] GMD1032 调试模式已启用"); #endif // === 初始化 SPI === pinMode(CS_PIN, OUTPUT); digitalWrite(CS_PIN, HIGH); SPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN, CS_PIN); // === 创建两个独立任务,分别绑定到不同核心 === xTaskCreatePinnedToCore(sensorTask, "SensorTask", 4096, NULL, 1, NULL, 0); // Core 0 xTaskCreatePinnedToCore(bleTask, "BleTask", 4096, NULL, 2, NULL, 1); // Core 1 } // ==================== loop() ==================== void loop() { // 所有功能由 FreeRTOS 任务接管,loop 留空 } 目前该代码功耗比较高,有没有什么优化方案
最新发布
10-16
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值