mirror of
https://github.com/m5stack/M5PM1.git
synced 2026-05-20 11:49:32 -07:00
1. initial construction
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"src/M5PM1.cpp"
|
||||
INCLUDE_DIRS
|
||||
"src"
|
||||
REQUIRES
|
||||
"driver"
|
||||
"espressif__i2c_bus"
|
||||
)
|
||||
@@ -1,48 +1,207 @@
|
||||
# Product Name
|
||||
# M5PM1
|
||||
|
||||
## Overview
|
||||
|
||||
### SKU:xxx
|
||||
**SKU: N/A**
|
||||
|
||||
Description of the product
|
||||
M5PM1 is a dual-platform (ESP-IDF & Arduino) driver library for M5Stack PM1 Power Management IC. It provides comprehensive power management features including:
|
||||
|
||||
## Related Link
|
||||
- Battery charging and monitoring
|
||||
- Multiple power rails (DCDC 5V, LDO 3.3V)
|
||||
- 5 GPIO pins with various functions (GPIO/IRQ/WAKE/PWM/ADC)
|
||||
- PWM output (2 channels)
|
||||
- ADC input (2 channels + temperature)
|
||||
- NeoPixel LED control (up to 32 LEDs)
|
||||
- Watchdog timer
|
||||
- RTC RAM (32 bytes, retained in sleep)
|
||||
- I2C auto-sleep/wake feature
|
||||
|
||||
- [Document & Datasheet](https://docs.m5stack.com/en/unit/product_Link)
|
||||
## Features
|
||||
|
||||
## Required Libraries:
|
||||
- **Dual-Platform Support**: Works with both Arduino and ESP-IDF frameworks
|
||||
- **Arduino-Style API**: Familiar `pinMode()`, `digitalWrite()`, `digitalRead()` functions
|
||||
- **I2C Auto-Wake**: Automatically handles PM1 sleep mode wake-up
|
||||
- **Comprehensive Power Management**: Battery charging, voltage monitoring, power hold
|
||||
|
||||
- [Adafruit_BMP280_Library](https://github.com/adafruit/Required_Libraries_Link)
|
||||
## Hardware
|
||||
|
||||
## License
|
||||
- **I2C Address**: 0x6E (default)
|
||||
- **I2C Speed**: 100KHz (default), 400KHz (configurable)
|
||||
- **GPIO Pins**: 5 (GPIO0-GPIO4)
|
||||
- **PWM Channels**: 2 (GPIO3, GPIO4)
|
||||
- **ADC Channels**: 2 (GPIO1, GPIO2) + Internal Temperature
|
||||
|
||||
- [Product Name- MIT](LICENSE)
|
||||
## Pin Functions
|
||||
|
||||
## Remaining steps(Editorial Staff Look,After following the steps, remember to delete all the content below)
|
||||
| GPIO | Special Function | Description |
|
||||
|------|-----------------|-------------|
|
||||
| GPIO0 | LED_EN | NeoPixel LED enable |
|
||||
| GPIO1 | ADC1 | Analog input channel 1 |
|
||||
| GPIO2 | ADC2 | Analog input channel 2 |
|
||||
| GPIO3 | PWM0 | PWM output channel 0 |
|
||||
| GPIO4 | PWM1 | PWM output channel 1 |
|
||||
|
||||
1. Change [clang format check path](./.github/workflows/clang-format-check.yml#L42-L47).
|
||||
2. Add License content to [LICENSE](/LICENSE).
|
||||
3. Change link on line 78 of [bug-report.yml](./.github/ISSUE_TEMPLATE/bug-report.yml#L79).
|
||||
## Usage
|
||||
|
||||
### Arduino
|
||||
|
||||
```cpp
|
||||
Example
|
||||
# M5Unit-ENV
|
||||
#include <M5PM1.h>
|
||||
|
||||
## Overview
|
||||
M5PM1 pm1;
|
||||
|
||||
### SKU:U001 & U001-B & U001-C
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Wire.begin(38, 39); // SDA, SCL
|
||||
|
||||
Contains M5Stack-**UNIT ENV** series related case programs.ENV is an environmental sensor with integrated SHT30 and QMP6988 internally to detect temperature, humidity, and atmospheric pressure data.
|
||||
if (pm1.begin(&Wire) != M5PM1_OK) {
|
||||
Serial.println("PM1 init failed!");
|
||||
while (1) delay(100);
|
||||
}
|
||||
|
||||
// Use Arduino-style API
|
||||
pm1.pinMode(0, OUTPUT);
|
||||
pm1.digitalWrite(0, HIGH);
|
||||
|
||||
// Read battery voltage
|
||||
uint16_t vbat;
|
||||
if (pm1.readVbat(&vbat) == M5PM1_OK) {
|
||||
Serial.printf("Battery: %d mV\n", vbat);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Toggle GPIO0
|
||||
pm1.digitalWrite(0, HIGH);
|
||||
delay(500);
|
||||
pm1.digitalWrite(0, LOW);
|
||||
delay(500);
|
||||
}
|
||||
```
|
||||
|
||||
### ESP-IDF
|
||||
|
||||
```cpp
|
||||
#include "M5PM1.h"
|
||||
|
||||
M5PM1 pm1;
|
||||
|
||||
void app_main() {
|
||||
// Initialize with self-created I2C bus
|
||||
if (pm1.begin(I2C_NUM_0, M5PM1_DEFAULT_ADDR, 21, 22, 100000) != M5PM1_OK) {
|
||||
ESP_LOGE("PM1", "Init failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Or use existing i2c_master_bus_handle_t
|
||||
// pm1.begin(existing_bus_handle, M5PM1_DEFAULT_ADDR, 100000);
|
||||
|
||||
// Configure GPIO
|
||||
pm1.gpioSetFunc(M5PM1_GPIO_NUM_0, M5PM1_GPIO_FUNC_GPIO);
|
||||
pm1.gpioSetMode(M5PM1_GPIO_NUM_0, M5PM1_GPIO_MODE_OUTPUT);
|
||||
pm1.gpioSetOutput(M5PM1_GPIO_NUM_0, 1);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### Initialization
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `begin()` | Initialize the PM1 device |
|
||||
| `setAutoWakeEnable()` | Enable/disable auto-wake feature |
|
||||
| `sendWakeSignal()` | Manually send wake signal |
|
||||
|
||||
### GPIO Functions
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `pinMode()` | Set GPIO mode (Arduino-style) |
|
||||
| `digitalWrite()` | Set GPIO output (Arduino-style) |
|
||||
| `digitalRead()` | Read GPIO input (Arduino-style) |
|
||||
| `gpioSetFunc()` | Set GPIO function (GPIO/IRQ/WAKE/OTHER) |
|
||||
| `gpioSetMode()` | Set GPIO direction |
|
||||
| `gpioSetOutput()` | Set GPIO output level |
|
||||
| `gpioGetInput()` | Get GPIO input level |
|
||||
| `gpioSetPull()` | Set GPIO pull-up/pull-down |
|
||||
| `gpioSetDrive()` | Set GPIO drive mode |
|
||||
|
||||
### Power Management
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `getPowerSource()` | Get current power source |
|
||||
| `getWakeSource()` | Get wake source flags |
|
||||
| `setPowerConfig()` | Set power configuration |
|
||||
| `setChargeEnable()` | Enable/disable battery charging |
|
||||
| `setDcdcEnable()` | Enable/disable 5V DCDC |
|
||||
| `setLdoEnable()` | Enable/disable 3.3V LDO |
|
||||
| `shutdown()` | Shutdown the system |
|
||||
| `reboot()` | Reboot the system |
|
||||
|
||||
### Voltage Reading
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `readVref()` | Read reference voltage |
|
||||
| `readVbat()` | Read battery voltage |
|
||||
| `readVin()` | Read VIN voltage |
|
||||
| `read5VInOut()` | Read 5VINOUT voltage |
|
||||
|
||||
### PWM Functions
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `setPwmFrequency()` | Set PWM frequency |
|
||||
| `getPwmFrequency()` | Get PWM frequency |
|
||||
| `setPwmDuty()` | Set PWM duty (percentage) |
|
||||
| `getPwmDuty()` | Get PWM duty (percentage) |
|
||||
| `setPwmDuty12bit()` | Set PWM duty (12-bit) |
|
||||
| `getPwmDuty12bit()` | Get PWM duty (12-bit) |
|
||||
| `analogWrite()` | Arduino-compatible PWM output |
|
||||
|
||||
### ADC Functions
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `analogRead()` | Read ADC value |
|
||||
| `isAdcBusy()` | Check ADC busy status |
|
||||
| `disableAdc()` | Disable ADC conversion |
|
||||
|
||||
### NeoPixel Functions
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `setLeds()` | Configure and set all LEDs |
|
||||
| `setLedCount()` | Set LED count |
|
||||
| `setLedColor()` | Set LED color |
|
||||
| `refreshLeds()` | Refresh LED display |
|
||||
| `disableLeds()` | Disable LED output |
|
||||
|
||||
### Watchdog Functions
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `wdtSet()` | Set watchdog timeout |
|
||||
| `wdtFeed()` | Feed the watchdog |
|
||||
| `wdtGetCount()` | Get watchdog countdown |
|
||||
|
||||
### RTC RAM Functions
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `writeRtcRAM()` | Write to RTC RAM |
|
||||
| `readRtcRAM()` | Read from RTC RAM |
|
||||
|
||||
## Related Link
|
||||
|
||||
- [Document & Datasheet](https://docs.m5stack.com/en/unit/envIII)
|
||||
- [Document & Datasheet](https://docs.m5stack.com/en/unit/pm1)
|
||||
|
||||
## Required Libraries:
|
||||
## Required Libraries
|
||||
|
||||
- [Adafruit_BMP280_Library](https://github.com/adafruit/Adafruit_BMP280_Library)
|
||||
- None (standalone library)
|
||||
|
||||
## License
|
||||
|
||||
- [M5Unit-ENV - MIT](LICENSE)
|
||||
```
|
||||
- [M5PM1 - MIT](LICENSE)
|
||||
|
||||
+273
@@ -0,0 +1,273 @@
|
||||
PY32 PMIC 说明手册
|
||||
================================================================================
|
||||
基本信息
|
||||
================================================================================
|
||||
I2C 地址: 0x6E
|
||||
硬件/固件版本: HW:5 / SW:6 (硬件修订: 5, 固件主版本: 6)
|
||||
文档版本: 1.7 (2025-12-13)
|
||||
代码仓库: stamp_timerpower2_code
|
||||
后续软件工程师: @任张涛
|
||||
|
||||
================================================================================
|
||||
一、 芯片概述
|
||||
================================================================================
|
||||
[功能]
|
||||
1. 电源管理: 支持 3.3V LDO/DCDC、5V IN/OUT、充电控制
|
||||
2. GPIO 控制: 5路可复用 GPIO (输入/输出、NeoPixel、ADC、PWM、Wake In、IRQ Out)
|
||||
3. 定时唤醒: 32-bit 定时器 (最大 214748364 秒), 支持多种唤醒动作
|
||||
4. 安全监控: 看门狗, 低压保护
|
||||
5. 存储备份: 32 字节 RTC RAM
|
||||
|
||||
[接口]
|
||||
I2C 协议 (支持 100kHz/400kHz 模式, 默认支持 100kHz, 400kHz 需要配置)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
GPIO 功能分布表
|
||||
--------------------------------------------------------------------------------
|
||||
| 序号 | PIN | GPIO | WAKE支持情况 | IRQ | 复用功能 |
|
||||
|-------|-----|------|---------------------|------|-----------|
|
||||
| GPIO0 | 3 | 支持 | 支持 (与GPIO2互斥) | 支持 | Neopixel |
|
||||
| GPIO1 | 17 | 支持 | 不支持 | 支持 | ADC |
|
||||
| GPIO2 | 20 | 支持 | 支持 (与GPIO0互斥) | 支持 | ADC |
|
||||
| GPIO3 | 13 | 支持 | 支持 (与GPIO4互斥) | 支持 | PWM |
|
||||
| GPIO4 | 12 | 支持 | 支持 (与GPIO3互斥) | 支持 | PWM |
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
内部 Pin 功能分布表
|
||||
--------------------------------------------------------------------------------
|
||||
| PIN | IO类型 | 上下拉 | 功能描述 |
|
||||
|-----|----------|--------|----------|
|
||||
| 1 | 模拟输出 | 无 | 开关电流采样: 高电平开启采样, 低电平关闭采样。默认为高电平 |
|
||||
| 2 | 模拟输出 | 无 | 使能电池充电: 低电平停止充电, 高电平开启充电。默认为高电平 |
|
||||
| 3 | GPIO | 无 | GPIO0, 默认为输入 |
|
||||
| 4 | 电源VSS | 无 | 无 |
|
||||
| 5 | 模拟输出 | 无 | LED灯控制, 输出低电平或高电平, 默认为高电平 |
|
||||
| 6 | 电源VCC | 无 | 无 |
|
||||
| 7 | 输入 | 上拉 | 按键检测 |
|
||||
| 8 | I2C | 无 | I2C SDA |
|
||||
| 9 | I2C | 无 | I2C SCL |
|
||||
| 10 | 模拟输出 | 无 | 5V DC/DC控制, 输出低电平或高电平, 默认为低电平 |
|
||||
| 11 | ADC | 无 | 电池ADC输入 (分压系数为1:1) |
|
||||
| 12 | GPIO | 无 | GPIO4, 默认为输入 |
|
||||
| 13 | GPIO | 无 | GPIO3, 默认为输入 |
|
||||
| 14 | 模拟输出 | 无 | 3V3 DC/DC控制, 输出低电平或高电平, 默认为高电平 |
|
||||
| 15 | 开漏输出 | 无 | 控制ESP32 BOOT, 默认为高电平 |
|
||||
| 16 | ADC | 无 | 5VIN ADC输入 (分压系数为1:1) |
|
||||
| 17 | GPIO | 无 | GPIO1, 默认为输入 |
|
||||
| 18 | 模拟输出 | 无 | 3V3 LDO控制, 输出低电平或高电平, 默认为高电平 |
|
||||
| 19 | ADC | 无 | 5VOUT ADC值输入 (分压系数为1:1) |
|
||||
| 20 | GPIO | 无 | GPIO2, 默认为输入 |
|
||||
|
||||
================================================================================
|
||||
二、 注意事项
|
||||
================================================================================
|
||||
1. 内部通道 ADC 的使用
|
||||
- 3个通道都有特定功能, 必须严格对应接入。
|
||||
- ADC 5VOUT:
|
||||
* 5VOUT 有输入和输出功能, 5VOUT 升压打开前, 需要先检测 5VOUT 的电压, 确保上面没有电源输入才能打开升压, 否则保持输入。
|
||||
* 低电压阈值检测。
|
||||
* 5VOUT 电源插入唤醒。
|
||||
* 5VOUT 电源移除与插入检测。
|
||||
- ADC BAT:
|
||||
* 低电压阈值检测。
|
||||
* 电池插入移除检测。
|
||||
- ADC 5VIN:
|
||||
* 低电压阈值检测。
|
||||
* 5VIN 插入移除检测。
|
||||
|
||||
2. 低电压自动关机
|
||||
- 低电压阈值由寄存器 BATT_LVP(0x08) 决定。
|
||||
- 在 5VIN 或 5VINOUT 没有插入的前提下, 电池电压低于阈值, 会自动关机。
|
||||
|
||||
================================================================================
|
||||
逻辑流程描述
|
||||
================================================================================
|
||||
|
||||
[流程1: 低电压保护 (LVP) 与自动关机]
|
||||
步骤:
|
||||
1. 检测是否触发 LVP (低电压保护)。
|
||||
2. 判断: 5VIN 或 5VINOUT 是否有电?
|
||||
- 是: 进入 [正常运行]。
|
||||
- 否: 判断 VBAT 是否大于最低电压?
|
||||
- 是: 进入 [正常运行]。
|
||||
- 否: 进入 [DeepSleep待机]。
|
||||
注: 在没有插入 Vin 的情况下, 需要 BAT 电压大于 BATT_LVP 电压 + 100mV, 才能退出低电压待机循环。
|
||||
|
||||
[流程2: 关机逻辑]
|
||||
步骤:
|
||||
1. 接收到关机指令。
|
||||
2. 检查寄存器 gpio_power_hold_cfg 的 bit5/6 是否为 1?
|
||||
- 否: bit5=0 (3.3V LDO关闭); bit6=0 (5V VOUT关闭)。
|
||||
- 是: bit5=1 (3.3V LDO保持); bit6=1 (5V VOUT保持)。
|
||||
3. 执行操作:
|
||||
(1) 3.3V DCDC 关闭。
|
||||
(2) LED_EN 关闭。
|
||||
(3) 充电使能不受影响。
|
||||
|
||||
[流程3: 下载模式]
|
||||
步骤:
|
||||
1. 进入下载模式。
|
||||
2. 复位电源与gpio寄存器; 置位 power_gpio_hold 寄存器。
|
||||
3. 下电。
|
||||
4. BOOT_OUT 输出低电平。
|
||||
5. 延时 300ms。
|
||||
6. 上电。
|
||||
7. 延时 500ms。
|
||||
8. BOOT_OUT 输出高电平。
|
||||
|
||||
[流程4: 复位模式]
|
||||
步骤:
|
||||
1. 进入复位模式。
|
||||
2. 复位电源与gpio寄存器; 置位 power_gpio_hold 寄存器。
|
||||
3. 下电。
|
||||
4. 延时 500ms。
|
||||
5. 上电。
|
||||
|
||||
================================================================================
|
||||
特殊功能细节与寄存器访问限制
|
||||
================================================================================
|
||||
[寄存器访问]
|
||||
I2C Burst 读写支持连续读写特定区块:
|
||||
0x00~0x0C, 0x10~0x19, 0x20~0x2A, 0x30~0x35, 0x38~0x3D, 0x40~0x45, 0x48~0x4A, 0x50、0x53, 0x60~0x9F, 0xA0~0xBF。
|
||||
超出范围需分次操作。
|
||||
|
||||
[GPIO 限制]
|
||||
1. GPIO1 与 SDA 共用中断线, 不可用干唤醒。
|
||||
2. GPIO0/2 共用中断线; GPIO3/4 共用中断线 (均为互斥使用)。
|
||||
3. GPIO_WAKE_EN (0x18) 和 GPIO_WAKE_CFG (0x19) 的配置不会因为进入下载模式、复位和关机而失效。
|
||||
4. WAKE 是否启用上下拉由 GPIO_PU/PD_0 (0x14) 和 GPIO_PU/PD_1 (0x15) 控制。
|
||||
5. GPIO_DRV (0x13) 输出类型拥有最高优先级, 不会随复用功能失效。默认为开漏, 即使复用为 PWM 或 Neopixel, 若配置为开漏则仍为开漏。
|
||||
|
||||
[电源事件]
|
||||
IRQ Status 2 中的电池插入/移除事件仅在充电未使能 (CHG_EN=0) 时有效; 5VINOUT 事件仅在 INPUT 模式 (5VIN/OUT=0) 有效。
|
||||
|
||||
[NeoPixel 数据]
|
||||
数据存储在 PIX0_L=0x60 ... PIX31_H=0x9F (共64字节)。刷新时 (REFRESH=1) 禁止 I2C 中断约 7ms。
|
||||
|
||||
[PWM 配置]
|
||||
PWM0/1 的高低位配置分为两个字节, 需一次写入两个字节, 否则可能在极短时间内出现参数不一致。
|
||||
|
||||
[按键逻辑]
|
||||
单击复位; 双击关机; 长按进入下载模式; 具体时间由 BTN_CFG_1 决定。
|
||||
|
||||
================================================================================
|
||||
三、 寄存器映射表 (Register Map)
|
||||
================================================================================
|
||||
说明: 以下表格中 "Def" 代表默认值 (Default)。
|
||||
Reset行为包括: 按键复位, 命令复位, I2C看门狗复位, 用户定时器复位。
|
||||
关机行为包括: 按键关机, 命令关机, 用户定时器关机。
|
||||
|
||||
| Register | Type | Addr | Bits | R/W | Def | 描述 | Reset后状态 | Download后状态 | 关机后状态 |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
| Device_ID | Sys | 0x00 | [7:0] | R | 0x50 | 设备类型 | - | - | - |
|
||||
| Device_Model | Sys | 0x01 | [7:0] | R | 0x20 | 设备型号 | - | - | - |
|
||||
| HW_REV | Sys | 0x02 | [7:0] | R | 0x05 | 硬件版本号 | - | - | - |
|
||||
| SW_REV | Sys | 0x03 | [7:0] | R | 0x06 | 固件版本号 | - | - | - |
|
||||
| PWR_SRC | Sys | 0x04 | [7:3] Rsv; [2:0] VALID | R | - | 电源来源位图 | - | - | - |
|
||||
| WAKE_SRC | Sys | 0x05 | [7] Rsv; [6:0] FLAGS | R/W | - | 唤醒源标志 | - | - | - |
|
||||
| PWR_CFG | Sys | 0x06 | [7:5] Rsv; [4] LED CTRL; [3] 5V IO; [2] 3V3 LDO; [1] 3V3 DCDC; [0] CHG EN | R/W | 0x17 | 电源管理位 | 0b00010011x (充电状态不受复位影响) | 0b00010011x (充电状态不受复位影响) | 0b00010011x (充电状态不受关机影响) |
|
||||
| HOLD_CFG | Sys | 0x07 | [7] Rsv; [6] 5V IO; [5] 3V3 LDO; [4:0] GPIO4~0 | R/W | 0x00 | 置1则对应状态在关机后保留; 复位或下载模式时此寄存器复位为0 | 0x00 | 0x00 | - |
|
||||
| BATT_LVP | Sys | 0x08 | [7:0] | R/W | 0x40 | 低压阈值: 2000mV + n*7.81mV | - | - | - |
|
||||
| I2C_CFG | Sys | 0x09 | [7:4] Rsv; [4] SPD; [3:0] SLP_TO | R/W | 0x00 | SPD: 0=100k, 1=400k; SLP_TO: I2C超时休眠(秒)。PWM使能或下载模式时禁止休眠 | - | - | - |
|
||||
| WDT_CNT | Sys | 0x0A | [7:0] | R/W | 0x00 | 看门狗倒计时(秒), 0=关闭 | - | - | - |
|
||||
| WDT_KEY | Sys | 0x0B | [7:0] | W | - | 写 0xA5 清零/复位 | - | - | - |
|
||||
| SYS_CMD | Sys | 0x0C | [7:4] KEY(0xA); [1:0] CMD | W | - | CMD: 01=关机, 10=重启, 11=下载 | - | - | - |
|
||||
| GPIO_MODE | GPIO | 0x10 | [7:5] Rsv; [4:0] GPIO4~0 | R/W | 0x00 | 1=输出, 0=输入 (需GPIO_FUNC=00) | 由Hold寄存器决定 (1=保持, 0=复位) | 0x00 | 由Hold寄存器决定 |
|
||||
| GPIO_OUT | GPIO | 0x11 | [7:5] Rsv; [4:0] GPIO4~0 | R/W | 0x00 | 写1=高电平 | 由Hold寄存器决定 | 0x00 | 由Hold寄存器决定 |
|
||||
| GPIO_IN | GPIO | 0x12 | 同上 | R | - | 实时输入值 | - | - | - |
|
||||
| GPIO_DRV | GPIO | 0x13 | [7:6] Rsv; [5] LED; [4:0] GPIO | R/W | 0x1F | 1=开漏, 0=推挽 | 由Hold寄存器决定 (LED不受影响) | 0x1F | 由Hold寄存器决定 |
|
||||
| GPIO_PU/PD_0 | GPIO | 0x14 | [7:6] G3; [5:4] G2; [3:2] G1; [1:0] G0 | R/W | 0x00 | 00=无, 01=上拉, 10=下拉 | 由Hold寄存器决定 | 0x00 | 由Hold寄存器决定 |
|
||||
| GPIO_PU/PD_1 | GPIO | 0x15 | [7:2] Rsv; [1:0] GPIO4 | R/W | 0x00 | 同上 | 由Hold寄存器决定 | 0x00 | 由Hold寄存器决定 |
|
||||
| GPIO_FUNC0 | GPIO | 0x16 | [7:6] G3; [5:4] G2; [3:2] G1; [1:0] G0 | R/W | 0x00 | 00=GPIO, 01=IRQ, 11=特殊, 10=保留 | 由Hold寄存器决定 | 0x00 | 由Hold寄存器决定 |
|
||||
| GPIO_FUNC1 | GPIO | 0x17 | [7:2] Rsv; [1:0] GPIO4 | R/W | 0x00 | 同上 | 由Hold寄存器决定 | 0x00 | 由Hold寄存器决定 |
|
||||
| GPIO_WAKE_EN | GPIO | 0x18 | [7:5] Rsv; [4:0] GPIO4~0 | R/W | 0x00 | 1=使能WAKE; 注意中断线互斥规则 | - | - | - |
|
||||
| GPIO_WAKE_CFG | GPIO | 0x19 | [7:5] Rsv; [4:0] GPIO4~0 | R/W | 0x00 | 1=上升沿, 0=下降沿 | - | - | - |
|
||||
| VREF_L/H | ADC | 0x20 | [7:0] | R | - | MCU ADC 参考电压 (L:0x20, H:0x21) | - | - | - |
|
||||
| VBAT_L/H | ADC | 0x22 | [7:0] | R | - | 电池电压 (L:0x22, H:0x23) | - | - | - |
|
||||
| VIN_L/H | ADC | 0x24 | [7:0] | R | - | 5VIN 电压 (L:0x24, H:0x25) | - | - | - |
|
||||
| 5VOUT_L/H | ADC | 0x26 | [7:0] | R | - | 5VOUT 电压 (L:0x26, H:0x27) | - | - | - |
|
||||
| ADC_RES_L/H | ADC | 0x28 | [7:0] / [3:0] Data | R | - | ADC 转换结果 | - | - | - |
|
||||
| ADC_CTRL | ADC | 0x2A | [3:1] CH_SEL; [0] START | R/W | 0x00 | START=1开始; CH_SEL: 1/2=GPIO, 6=Temp | - | - | - |
|
||||
| PWM0_L/HC | PWM | 0x30 | [7:0] / [5] POL [4] EN | R/W | 0x00 | PWM0 控制 | - | - | - |
|
||||
| PWM1_L/HC | PWM | 0x32 | [7:0] / [5] POL [4] EN | R/W | 0x00 | PWM1 控制 | - | - | - |
|
||||
| PWM_FREQ_L/H | PWM | 0x34 | [7:0] | R/W | F4/01 | PWM 频率 (16bit) | - | - | - |
|
||||
| TIM_CNT_BYTE | Tim | 0x38 | [7:0] (0x38-0x3B) | R/W | 0x00 | 定时唤醒计数器 (32bit, 秒) | - | - | - |
|
||||
| TIM_CFG | Tim | 0x3C | [3] ARM; [2:0] ACTION | R/W | 0x00 | ACTION: 000=停, 001=标志, 010=重启, 011=上电, 100=关机 | - | - | - |
|
||||
| TIM_KEY | Tim | 0x3D | [7:0] | W | - | 写 0xA5 清零重载 | - | - | - |
|
||||
| IRQ Status 1 | IRQ | 0x40 | [4:0] GPIO4~0 | R/W | 0x00 | GPIO 电平变化 | - | - | - |
|
||||
| IRQ Status 2 | IRQ | 0x41 | [5/4] Bat Rm/Add; [3/2] 5Vout Rm/Add; [1/0] 5Vin Rm/Add | R/W | 0x00 | 电源事件 (写1清零) | - | - | - |
|
||||
| IRQ Status 3 | IRQ | 0x42 | [2] Dbl Click; [1] Wake; [0] Click | R/W | 0x00 | 按键/唤醒事件 (bit0=RST中断, bit1=Wakeup中断, bit2=双击中断) | - | - | - |
|
||||
| IRQ Mask 1/2/3| IRQ | 0x43 | 对应 Status 位 | R/W | 0x00 | 写1屏蔽对应中断 (0x43~0x45) | - | - | - |
|
||||
| BTN_Status | BTN | 0x48 | [7] Event; [0] Status | R | 0x00 | 按键状态 | - | - | - |
|
||||
| BTN_CFG_1 | BTN | 0x49 | [7] Lock; [6:5] Dbl; [4:3] Long; [2:1] Single; [0] Sngl_Rst_Dis | R/W | 0x2A | 按键时间配置; bit0=1禁止单击复位 | - | - | - |
|
||||
| BTN_CFG_2 | BTN | 0x4A | [0] Dbl_Off_Dis | R/W | 0x00 | bit0=1禁止双击关机 | - | - | - |
|
||||
| NEO_CFG | RGB | 0x50 | [6] Refresh; [5:0] Count | R/W | 0x00 | NeoPixel控制 | - | - | - |
|
||||
| PULSE_CTRL | Pulse| 0x53 | [7] Refresh; [6:5] Num; [4:0] GPIO | R/W | 0x00 | AW8737A 脉冲触发 | - | - | - |
|
||||
| NEO_PIXn | RGB | 0x60 | [7:0] | R/W | 0x00 | 0x60-0x9F RGB数据缓存 | - | - | - |
|
||||
| RTC_MEM | RTC | 0xA0 | [7:0] | R/W | 0x00 | 0xA0-0xBF RTC数据缓存 | - | - | - |
|
||||
|
||||
================================================================================
|
||||
四、 关键寄存器功能详解
|
||||
================================================================================
|
||||
1. PWR_SRC (0x04) - 电源来源状态
|
||||
- [2] BAT: 电池有效
|
||||
- [1] 5VINOUT: 5VINOUT 有效 (仅当 5V 升压关闭时有效)
|
||||
- [0] 5VIN: 5VIN 有效
|
||||
- 注: 系统通过 ADC 检测电压判断电源来源。建议无电池时关闭电池充电。
|
||||
|
||||
2. WAKE_SRC (0x05) - 唤醒来源
|
||||
- [6] 5V INOUT 插入唤醒 (仅当 5V 升压关闭时)
|
||||
- [5] EXT_WAKE: GPIO 唤醒
|
||||
- [4] CMD_RST: 复位命令
|
||||
- [3] RSTBTN: 按键复位
|
||||
- [2] PWRBTN: 电源按钮
|
||||
- [1] VIN: 5VIN 插入
|
||||
- [0] TIM: 定时器
|
||||
|
||||
3. HOLD_CFG (0x07) - 状态保持
|
||||
- 将对应位设为 1, 则关机后对应的 GPIO、LDO 或 5VINOUT 状态会保持原样。
|
||||
- 注意: 进入下载模式或触发任何 Reset (包括看门狗), 该寄存器会清零。
|
||||
|
||||
4. BATT_LVP (0x08) - 低压保护
|
||||
- 低压阈值计算: 2.0 V + (reg_value * 7.81 mV)。
|
||||
- 重新开机条件: 电池电压 > 阈值+100mV; 或插入 5VIN; 或插入 5VINOUT。
|
||||
|
||||
5. I2C_CFG (0x09) - I2C配置
|
||||
- SPD: 0=100k, 1=400k。
|
||||
- SLP_TO: 若设置非0, 代表 I2C 总线空闲多少秒后芯片休眠。
|
||||
- 限制: PWM 使能或下载模式下, I2C 空闲休眠强制关闭。
|
||||
|
||||
6. GPIO_MODE / OUT / DRV
|
||||
- GPIO_MODE: 1=输出, 0=输入。需 GPIO_FUNC 设置为 00 才生效。
|
||||
- GPIO_OUT: 1=高, 0=低。
|
||||
- GPIO_DRV: 1=开漏, 0=推挽。DRV 优先级最高, 若复用功能开启但 DRV=1, 仍为开漏。
|
||||
|
||||
7. ADC_CTRL (0x2A) - ADC控制
|
||||
- CH_SEL: 通道选择。1=GPIO1, 2=GPIO2, 6=内部温度。
|
||||
- 使用 GPIO 作 ADC 输入时, 必须将对应的 GPIO_FUNC 设为 11。
|
||||
|
||||
8. IRQ Status 注意事项
|
||||
- 若没有 GPIO 被配置为 IRQ 引脚, Status 寄存器会自动清零。
|
||||
- 若要使用 Wakeup IRQ (Status 3 bit1), 请勿清除 WAKE_SRC 寄存器, 直到重新配置 GPIO 为 IRQ 引脚。
|
||||
|
||||
================================================================================
|
||||
五、 附加功能说明与变更记录 (Change Log)
|
||||
================================================================================
|
||||
[附加功能说明]
|
||||
(1) 32-bit 定时器最大秒数限制为 214749364 秒。
|
||||
(2) 关机时, GPIO 恢复为默认输入无上下拉; 电源恢复默认状态 (除非 HOLD_CFG 对应位为 1)。
|
||||
(3) 进入下载模式, HOLD_CFG 清零, I2C 看门狗/休眠/用户定时器停止, GPIO 恢复默认。
|
||||
(4) LED 提示逻辑: 复位闪烁1次; 下载模式 500ms 间隔闪烁; 屏蔽按键复位且有 IRQ 时 200ms 间隔闪烁; 屏蔽关机且有 IRQ 时 100ms 间隔闪烁。
|
||||
(5) 充电功能默认打开。
|
||||
|
||||
[文档变更记录]
|
||||
| 版本 | 日期 | 变更描述 |
|
||||
|------|------------|----------|
|
||||
| 1.0 | 2025-06-30 | 初始版本 |
|
||||
| 1.1 | 2025-07-23 | 硬件修订: 3, 固件主版本: 2 |
|
||||
| 1.2 | 2025-08-04 | 修订部分描述错误 |
|
||||
| 1.3 | 2025-09-01 | 硬件修订: 4, 固件主版本: 3 |
|
||||
| 1.4 | 2025-09-10 | 对关键寄存器详解进行了补充 |
|
||||
| 1.5 | 2025-09-17 | 硬件修订: 5, 固件主版本: 4; (1) LED 指示灯在单击或双击中断触发指示; (2) 升级失败时 GPIO 和 bootout 设置为开漏; (3) 改用 ADC 采样判断 5VINOUT; (4) PIN1 逻辑修改。 |
|
||||
| 1.6 | 2025-11-04 | 硬件修订: 5, 固件主版本: 5; (1) 添加 AW8737A 调频脉冲输出; (2) 添加 DCDC_5V 保持功能; (3) 看门狗默认关闭。 |
|
||||
| 1.7 | 2025-12-13 | 硬件修订: 5, 固件主版本: 6; (1) 更新寄存器映射; (2) 新增 BTN_Status (0x48); (3) 移除 UID 寄存器, 新增 Device_ID/Model。 |
|
||||
@@ -0,0 +1,14 @@
|
||||
description: "M5Stack M5PM1 Power Management IC Library"
|
||||
maintainers:
|
||||
- "M5Stack"
|
||||
license: MIT
|
||||
tags:
|
||||
- "m5stack"
|
||||
- "power-management"
|
||||
dependencies:
|
||||
idf:
|
||||
version: ">=4.4"
|
||||
espressif/i2c_bus:
|
||||
version: "^1.0.0"
|
||||
public: true
|
||||
version: "1.0.1"
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "M5PM1",
|
||||
"version": "1.0.1",
|
||||
"description": "M5Stack PM1 Power Management IC Driver Library",
|
||||
"keywords": [
|
||||
"m5stack",
|
||||
"pm1",
|
||||
"power-management",
|
||||
"i2c",
|
||||
"esp32",
|
||||
"arduino"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/m5stack/M5PM1.git"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "M5Stack",
|
||||
"email": "m5stack@m5stack.com",
|
||||
"url": "https://m5stack.com",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/m5stack/M5PM1",
|
||||
"frameworks": [
|
||||
"arduino",
|
||||
"espidf"
|
||||
],
|
||||
"platforms": [
|
||||
"espressif32"
|
||||
],
|
||||
"export": {
|
||||
"include": [
|
||||
"src/*",
|
||||
"library.json",
|
||||
"library.properties",
|
||||
"CMakeLists.txt",
|
||||
"idf_component.yml",
|
||||
"LICENSE",
|
||||
"README.md"
|
||||
]
|
||||
},
|
||||
"build": {
|
||||
"srcDir": "src",
|
||||
"includeDir": "src"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
name=M5PM1
|
||||
version=1.0.1
|
||||
author=M5Stack
|
||||
maintainer=M5Stack
|
||||
sentence=M5Stack PM1 Power Management IC Driver Library
|
||||
paragraph=Dual-platform (ESP-IDF & Arduino) driver for PM1 power management IC with battery charging, GPIO, PWM, ADC, NeoPixel, and watchdog support.
|
||||
category=Device Control
|
||||
url=https://github.com/m5stack/M5PM1
|
||||
architectures=esp32
|
||||
includes=M5PM1.h
|
||||
+4140
File diff suppressed because it is too large
Load Diff
+1484
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef __M5PM1_I2C_COMPAT_H__
|
||||
#define __M5PM1_I2C_COMPAT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
#include "Wire.h"
|
||||
|
||||
// ============================
|
||||
// Arduino I2C Functions
|
||||
// Arduino I2C 功能
|
||||
// ============================
|
||||
|
||||
#ifndef M5PM1_I2C_READ_BYTE
|
||||
static inline bool M5PM1_I2C_READ_BYTE(TwoWire *wire, uint8_t addr, uint8_t reg, uint8_t *data) {
|
||||
wire->beginTransmission(addr);
|
||||
wire->write(reg);
|
||||
if (wire->endTransmission(false) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (wire->requestFrom(addr, (uint8_t)1) != 1) {
|
||||
return false;
|
||||
}
|
||||
*data = wire->read();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_READ_BYTES
|
||||
static inline bool M5PM1_I2C_READ_BYTES(TwoWire *wire, uint8_t addr, uint8_t start_reg, size_t len, uint8_t *data) {
|
||||
wire->beginTransmission(addr);
|
||||
wire->write(start_reg);
|
||||
if (wire->endTransmission(false) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (wire->requestFrom(addr, (uint8_t)len) != len) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
data[i] = wire->read();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_READ_REG16
|
||||
static inline bool M5PM1_I2C_READ_REG16(TwoWire *wire, uint8_t addr, uint8_t reg, uint16_t *data) {
|
||||
uint8_t buf[2];
|
||||
if (!M5PM1_I2C_READ_BYTES(wire, addr, reg, 2, buf)) {
|
||||
return false;
|
||||
}
|
||||
// Little-endian: low byte first
|
||||
// 小端模式:低字节在前
|
||||
*data = (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_WRITE_BYTE
|
||||
static inline bool M5PM1_I2C_WRITE_BYTE(TwoWire *wire, uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
wire->beginTransmission(addr);
|
||||
wire->write(reg);
|
||||
wire->write(data);
|
||||
if (wire->endTransmission() != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_WRITE_BYTES
|
||||
static inline bool M5PM1_I2C_WRITE_BYTES(TwoWire *wire, uint8_t addr, uint8_t start_reg, size_t len, const uint8_t *data) {
|
||||
wire->beginTransmission(addr);
|
||||
wire->write(start_reg);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
wire->write(data[i]);
|
||||
}
|
||||
if (wire->endTransmission() != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_WRITE_REG16
|
||||
static inline bool M5PM1_I2C_WRITE_REG16(TwoWire *wire, uint8_t addr, uint8_t reg, uint16_t data) {
|
||||
uint8_t buf[2];
|
||||
// Little-endian: low byte first
|
||||
// 小端模式:低字节在前
|
||||
buf[0] = (uint8_t)(data & 0xFF);
|
||||
buf[1] = (uint8_t)((data >> 8) & 0xFF);
|
||||
return M5PM1_I2C_WRITE_BYTES(wire, addr, reg, 2, buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Wake signal for PM1 sleep mode
|
||||
// PM1睡眠模式唤醒信号
|
||||
#ifndef M5PM1_I2C_SEND_WAKE
|
||||
static inline void M5PM1_I2C_SEND_WAKE(TwoWire *wire, uint8_t addr) {
|
||||
// Send START signal to generate SDA falling edge for PM1 wake
|
||||
// PM1 uses SDA pin (PB4) falling edge to trigger EXTI4 interrupt for wakeup
|
||||
wire->beginTransmission(addr);
|
||||
wire->endTransmission(false); // Send START without STOP
|
||||
}
|
||||
#endif
|
||||
|
||||
#else // ESP-IDF
|
||||
|
||||
#include <esp_err.h>
|
||||
#include <driver/i2c_master.h> // ESP-IDF native i2c_master driver
|
||||
#include <i2c_bus.h> // esp-idf-lib i2c_bus component
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// ============================
|
||||
// I2C Driver Type Selection
|
||||
// I2C 驱动类型选择
|
||||
// ============================
|
||||
typedef enum {
|
||||
M5PM1_I2C_DRIVER_NONE = 0, // Not initialized / 未初始化
|
||||
M5PM1_I2C_DRIVER_SELF_CREATED, // Self-created using i2c_port_t / 使用 i2c_port_t 自创建
|
||||
M5PM1_I2C_DRIVER_MASTER, // ESP-IDF native i2c_master driver / ESP-IDF 原生 i2c_master 驱动
|
||||
M5PM1_I2C_DRIVER_BUS // esp-idf-lib i2c_bus component / esp-idf-lib i2c_bus 组件
|
||||
} m5pm1_i2c_driver_t;
|
||||
|
||||
// ============================
|
||||
// ESP-IDF I2C Functions (i2c_bus)
|
||||
// ESP-IDF I2C 函数 (i2c_bus)
|
||||
// ============================
|
||||
|
||||
#ifndef M5PM1_I2C_READ_BYTE
|
||||
static inline esp_err_t M5PM1_I2C_READ_BYTE(i2c_bus_device_handle_t dev, uint8_t reg, uint8_t *data) {
|
||||
return i2c_bus_read_byte(dev, reg, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_READ_BYTES
|
||||
static inline esp_err_t M5PM1_I2C_READ_BYTES(i2c_bus_device_handle_t dev, uint8_t start_reg, size_t len, uint8_t *data) {
|
||||
return i2c_bus_read_bytes(dev, start_reg, len, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_READ_REG16
|
||||
static inline esp_err_t M5PM1_I2C_READ_REG16(i2c_bus_device_handle_t dev, uint8_t reg, uint16_t *data) {
|
||||
uint8_t buf[2];
|
||||
esp_err_t ret = i2c_bus_read_bytes(dev, reg, 2, buf);
|
||||
if (ret == ESP_OK) {
|
||||
// Little-endian: low byte first
|
||||
// 小端模式:低字节在前
|
||||
*data = (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_WRITE_BYTE
|
||||
static inline esp_err_t M5PM1_I2C_WRITE_BYTE(i2c_bus_device_handle_t dev, uint8_t reg, uint8_t data) {
|
||||
return i2c_bus_write_byte(dev, reg, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_WRITE_BYTES
|
||||
static inline esp_err_t M5PM1_I2C_WRITE_BYTES(i2c_bus_device_handle_t dev, uint8_t start_reg, size_t len, const uint8_t *data) {
|
||||
return i2c_bus_write_bytes(dev, start_reg, len, (uint8_t*)data);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_WRITE_REG16
|
||||
static inline esp_err_t M5PM1_I2C_WRITE_REG16(i2c_bus_device_handle_t dev, uint8_t reg, uint16_t data) {
|
||||
uint8_t buf[2];
|
||||
// Little-endian: low byte first
|
||||
// 小端模式:低字节在前
|
||||
buf[0] = (uint8_t)(data & 0xFF);
|
||||
buf[1] = (uint8_t)((data >> 8) & 0xFF);
|
||||
return i2c_bus_write_bytes(dev, reg, 2, buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
// ============================
|
||||
// ESP-IDF I2C Functions (i2c_master - native driver)
|
||||
// ESP-IDF I2C 函数 (i2c_master - 原生驱动)
|
||||
// ============================
|
||||
|
||||
#ifndef M5PM1_I2C_MASTER_READ_BYTE
|
||||
static inline esp_err_t M5PM1_I2C_MASTER_READ_BYTE(i2c_master_dev_handle_t dev, uint8_t reg, uint8_t *data) {
|
||||
return i2c_master_transmit_receive(dev, ®, 1, data, 1, -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_MASTER_READ_BYTES
|
||||
static inline esp_err_t M5PM1_I2C_MASTER_READ_BYTES(i2c_master_dev_handle_t dev, uint8_t start_reg, size_t len, uint8_t *data) {
|
||||
return i2c_master_transmit_receive(dev, &start_reg, 1, data, len, -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_MASTER_READ_REG16
|
||||
static inline esp_err_t M5PM1_I2C_MASTER_READ_REG16(i2c_master_dev_handle_t dev, uint8_t reg, uint16_t *data) {
|
||||
uint8_t buf[2];
|
||||
esp_err_t ret = i2c_master_transmit_receive(dev, ®, 1, buf, 2, -1);
|
||||
if (ret == ESP_OK) {
|
||||
// Little-endian: low byte first
|
||||
// 小端模式:低字节在前
|
||||
*data = (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_MASTER_WRITE_BYTE
|
||||
static inline esp_err_t M5PM1_I2C_MASTER_WRITE_BYTE(i2c_master_dev_handle_t dev, uint8_t reg, uint8_t data) {
|
||||
uint8_t buf[2] = {reg, data};
|
||||
return i2c_master_transmit(dev, buf, 2, -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_MASTER_WRITE_BYTES
|
||||
static inline esp_err_t M5PM1_I2C_MASTER_WRITE_BYTES(i2c_master_dev_handle_t dev, uint8_t start_reg, size_t len, const uint8_t *data) {
|
||||
// Need to prepend register address
|
||||
// 需要在数据前添加寄存器地址
|
||||
uint8_t *buf = (uint8_t*)malloc(len + 1);
|
||||
if (buf == NULL) return ESP_ERR_NO_MEM;
|
||||
buf[0] = start_reg;
|
||||
memcpy(buf + 1, data, len);
|
||||
esp_err_t ret = i2c_master_transmit(dev, buf, len + 1, -1);
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M5PM1_I2C_MASTER_WRITE_REG16
|
||||
static inline esp_err_t M5PM1_I2C_MASTER_WRITE_REG16(i2c_master_dev_handle_t dev, uint8_t reg, uint16_t data) {
|
||||
uint8_t buf[3];
|
||||
buf[0] = reg;
|
||||
// Little-endian: low byte first
|
||||
// 小端模式:低字节在前
|
||||
buf[1] = (uint8_t)(data & 0xFF);
|
||||
buf[2] = (uint8_t)((data >> 8) & 0xFF);
|
||||
return i2c_master_transmit(dev, buf, 3, -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Wake signal for PM1 sleep mode using i2c_bus
|
||||
// 使用i2c_bus的PM1睡眠模式唤醒信号
|
||||
#ifndef M5PM1_I2C_SEND_WAKE
|
||||
static inline esp_err_t M5PM1_I2C_SEND_WAKE(i2c_bus_device_handle_t dev, uint8_t reg) {
|
||||
// Read any register to generate I2C start signal for wake
|
||||
uint8_t dummy;
|
||||
return i2c_bus_read_byte(dev, reg, &dummy);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Wake signal for PM1 sleep mode using i2c_master
|
||||
// 使用i2c_master的PM1睡眠模式唤醒信号
|
||||
#ifndef M5PM1_I2C_MASTER_SEND_WAKE
|
||||
static inline esp_err_t M5PM1_I2C_MASTER_SEND_WAKE(i2c_master_bus_handle_t bus, uint8_t addr) {
|
||||
// Use i2c_master_probe to generate START signal for wake
|
||||
return i2c_master_probe(bus, addr, 10);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ARDUINO
|
||||
|
||||
#endif // __M5PM1_I2C_COMPAT_H__
|
||||
Reference in New Issue
Block a user