前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一颗=3颗(nPM1300电源芯片)

一颗=3颗(nPM1300电源芯片)

作者头像
云深无际
发布2024-08-21 13:40:53
1100
发布2024-08-21 13:40:53
举报
文章被收录于专栏:云深之无迹

nPM1300是NRF最新的电源IC,文章比较长,请耐心观看:

对比以前的芯片来看,这次是补全了前面芯片的空缺,而且DCDC+LDO+充电这样的设置可以让嵌入式设备的体积再变小一些:

就像一个项目的电源系统,里面有数字的MCU,也有模拟的AEF,以及为了便携的充电芯片,现在一颗芯片就可以全搞定了,而且还多了很多高级功能,比如可调的LDO和BUCK,以及高端产品才能拥有的运输模式。

下面的一个框图就说明了在设计上面的优势,可以直接通过USB接口充电,还拥有最新的Type-C标准,为了充电的上面的安全还加入了NTC功能配合恒流恒压等可以让设备更加的安全,其实配套软件还有更多的功能,可以预测什么的,看别人评测吧。

可以通过外置电阻的设置,在芯片没有被主机控制的情况下就可以供电。最后我觉得是官方给的BUCK做LDO给MCU供电还挺好,剩下的两个LDO做模拟和数字电源。

其实还有一路主机供电的电源,也可以作为扩展电源出现。

1.可以有两个LDO,一个模拟域,一个数字域(但是我没有找到纹波)

2.两个BUCK,有两个模式

1PWM 和滞后模式可根据负载自动切换

1滞后模式可在较低负载电流下提供效率,并且通常以最大 PWM 电流的一半运行。

1BUCK 默认在自动模式下运行。在自动模式下,BUCK 针对低负载电流选择滞后模式,针对高负载电流选择 PWM 模式。

1在 PWM 模式下,BUCK 由于恒定的开关频率和较低的电压纹波而提供清洁的电源,从而与 RF 电路实现最佳共存。

1VSET1和VSET2引脚仅在通电时启用。如果存在 电阻 R (VSETn ,则 BUCK 启用,输出电压由电阻值)定义。如果引脚接地,则 BUCK 禁用。

有两个电阻是控制BUCK输出的

BUCK 的输出电压范围可通过 TWI (IIC) 进行编程。默认输出电压选择位于引脚VSET1VSET2上,这些引脚使用外部电阻器配置为GND

BUCK 1和2 的设置电阻

输出电压范围为 1.0 V 至 3.3 V,步长为 100 mV,并在电压配置寄存器BUCK1NORMVOUT和BUCK2NORMVOUT中设置。一旦选择了电压,必须写入寄存器BUCKSWCTRLSEL才能使值生效。

寄存器BUCK1VOUTSTATUS和BUCK2VOUTSTATUS 指示状态或当前电压设置。

这个是编程时候的要点

BUCK组件需要电感和电容

官方的板子推荐的是这颗,但是jlc没有现货,需要在贸泽上面定欧

这个有个重要的参数是要启用BUCK输出的最小VSYS电压,是2.7V,最大的降压电流是0.2A。然后两个电源纹波

强制BUCK1 进入PWM模式

正常模式的输出电压

状态寄存器,BUCK有些寄存器我看不懂是做什么的

可以精确的按照0.1V的步进来调整

充电的电流是可以限制的,USB上面的

VBUS上面的电压信息是可以输出的,所以这里也可以做USB接口信息检测

涓流就是以低速率且恒定方式对电池提供很小的充电电流。

恒流,就是充电电流保持不变,不管输出电压如何变化,锂电池的主要充电方式,电流大于500mA。

电池维护功能

充电电流限值以 2 mA 为步长设置在 32 mA 至 800 mA 之间。充电电流 I (CHG)由 TWI 配置,默认值为 32 mA。

支持NTC测温

可以通过NTC+电流的配合来适应温度智能充电

电池的充电终止电压也是可以设置的,常温下

涓流充电设置,默认是2.9V

充电状态,这些都是可以通过查询来读出的

官方的板子真的很漂亮,hhhh,原理图也是赏心悦目

LED-DRV 由三个相同的低侧 LED 驱动器组成,位于引脚 LED0LED1LED2上。引脚配置彼此独立。

可以在寄存器中配置引脚以实现以下目的:

1充电指示

1充电错误指示

1RGB LED(需要全部三个引脚)

1通用开漏输出

开漏模式一般应用在I2C、SMBUS通讯等需要“线与”功能的总线电路中,除此之外,还用在电平不匹配的场合,如需要输出5伏的高电平,就可以在外部接一个上拉电阻,上拉电源为5伏,并且把GPIO设置为开漏模式,当输出高阻态时,由上拉电阻和电源向外输出5伏的电平。

所以:在开漏模式下运行的每个 LED 引脚都需要一个外部上拉电阻。

GPIO 由VDDIO引脚供电。

GPIO作为输入的时候,一定有去抖动,这里直接内置了,20ms,实在是贴心,给出了一个寄存器来控制

给了一个定时器,但是是一带而过。

但是我研究后,不知道这个东西咋用:

当设备处于休眠模式时,唤醒定时器会以可编程间隔唤醒系统。当系统处于运输或休眠模式时,请勿使用看门狗定时器或通用定时器。

运输和休眠模式将电池与系统隔离,并最大限度地减少静态电流。

休眠模式与运输模式相同,不同之处在于,在休眠模式下,计时器正在运行并作为额外的唤醒源。

这个运输模式,现在在产品上面还挺普遍的,比如无人机,电脑,电动牙刷什么的。

Ship功能是在产品出厂之后的长期保管中,尽可能减少电池余量的功能。Ship功能也称为运输模式等其它名称。

没有搭载Ship功能的电子设备,出厂后仍处于电池发生消耗电流的状态。在这种状态下,电子设备在长期保存中电池余量逐渐减少,导致的电池因深度过放电导致的损坏。

可以设想当产品到达最终客户时,可能会出现电池电量太低以至产品不能立即启动,或者目标电池驱动时间不足的情况。

为了抑制出厂后长期保存状态下电池发生的电流消耗,电子设备需要具备Ship功能。

就是一种

有三种方式退出这个模式,按键,当你摁对应的按钮够了时间就退出,还有VSYS电压唤醒,以及定时器自动唤醒

真不好翻译,应该就是测量一个按键上面的时间。

SHPHLD引脚除了用于退出航行和休眠模式外,还是一个复位控制

芯片操作其实简单的,就是IIC:

TWI 由 VDDIO 供电。建议将VDDIO连接到 BUCK 输出、VOUT1VOUT2。除运输和休眠模式外,芯片的所有操作模式下都必须有 VDDIO。

也就是推荐连接到BUCK上面

设计的时候,这个VDDIO

夸夸大厂的文档,IIC协议写的简洁明了,开始信号+地址+读写+回应+寄存器地址+8位数据+回复+不要啦

对应的读取

看一个官方给的demo,里面要点众多,幸亏我用了一次。这里分析一下:Type-C的CC感应线,还有USB+-上面的保护二极管:

注意这里的USB需要差分走线,电池输入部分使用了NTC测温,重启的引脚被引出,LED也是被引出,BUCK的输出电压被外置的电阻指定,运输引脚被引出,IIC控制引出,还有中断和重启,就是软件自动控制,不需要手动,VDDIO是1.8V,记住我上面写的东西,这个地方是芯片的供电,推荐是BUCK1上面,LDO的输出有两个滤波电容。

这里就有个有趣的事情,我们都知道MCU需要一个LDO,但是我用了PMIC,PMIC是数字器件,必须主机启动后使用IIC控制,这里就有一些鸡生蛋蛋生鸡的问题,所以需要PMIC在MCU启动前就给MCU供电。

SO:BUCK1 自动启动并为 nRF5x 主机 SoC 提供 1.8 V 电压。

BUCK1 是系统的 I/O 电压。

BUCK2 自动启动,提供 3 V 输出电压,用于其他应用功能。

这里也学了新东西,BUCK可以直接给MCU供电,PMIC是可以的。

在以上VBUS是USB的电压:

PMIC上面还天然的设计了一个VBUSOUT的引脚,时候应用USB外设的器件

我在PCB设计之前,喜欢研究芯片的引脚,因为布过线的都知道,一个良好的布局多重要,芯片的左边是BUCK,下面是IIC,左面是LDO,上面是USB部分,大概就是这样的。

官方给了三个配置

注意的地方就是电源这些,IIC的上拉:

我这里给出自己的设计图,LDO的输出我留了俩路,可以给模拟和数字器件分别供电,中间给出了BUCK的设置电压用的电阻表。

这里学习官方,上拉和设置使用了最小的封装

在简单的配置里面,最小封装是用在了滤波和上下拉。

最简单同理

布局要求是:

为了获得最佳性能,建议使用至少两层的 PCB,其中包括接地层。(这里都是4层的,因为性能是一部分,布线我实在是器件多了2层布不出来,一个完整层被打的七零八落的,哭死)

BUCK 电源电压应使用尽可能靠近电源引脚的高性能电容器进行去耦。

应避免在 PCB 上采用较长的电源线。所有设备接地、VDD 连接和 VDD 旁路电容都必须尽可能靠近设备连接。

官方的PCB里面给的布局,其实就是真实PCB的一个改版,主要是去耦电容更加的紧凑,主要是左边BUCK的电容和电感。

就是布这里的时候要求足够的近,一个小环路

这里是可以从电容中间之间穿线出去

在PCB里面更加的清晰,对称布局

看我画住的地方

这个布局就很好,真实布局

我自己的布局就不好,过多的孔打散了地,以及追求对称失去了性能,需要整改

比如LDO的偏置电容,一般是要求直接压在上面的

现在在看一次这个布局,就很清晰了

在软件开发上面,也是齐全的配置,首先使用官方最大支持力度的zephyr,demo的代码也是基于此:

可以GitHub上面搜索这个库

这次设计给到了:提供了一个 shell 接口来支持 nPM1300 PMIC 的功能,我更改为串口控制版:

官方指令

实现的独有函数,还有一个回调,但是耦合很强,就没有分析了,就看单函数

分析一个吧,是读取多个寄存器的函数,说实话套的很深:

因为寄存器是基地址+偏移,前者是高八位,后是第八位,其实这个是说明了要读取的寄存器位置

这个内联函数封装了I2C通信,通过 i2c_write_read 函数执行具体的读写操作。参数包括I2C设备规范、写缓冲区、写字节数、读缓冲区和读字节数。

然后内联函数才又执行了一个函数

函数通过I2C接口执行写和读操作。它构建了两个I2C消息,一个用于写操作,另一个用于读操作。然后调用 i2c_transfer 函数执行这两个消息。

1msg[0]: 写操作,包含要写入的数据。

1msg[1]: 读操作,包含要读取的数据。

1I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP 标志表示在读操作之前发送重启信号,读操作之后发送停止信号。

mfd_npm1300_reg_read_burst 函数被调用时,会构建一个包含寄存器基地址和偏移地址的缓冲区 buff。

然后调用 i2c_write_read_dt 函数,该函数进一步调用 i2c_write_read 函数。

i2c_write_read 函数创建两个I2C消息,一个用于写入寄存器地址,另一个用于读取数据。

最终,i2c_transfer 函数执行I2C传输,写入地址后读取数据,并将数据存储在 data 缓冲区中。

我这里给出使用串口控制PMIC的代码:

C++ #include#include#include#include#include#include#include#include #define UART_DEVICE_NODE DT_LABEL(DT_CHOSEN(zephyr_console)) #define BUFFER_SIZE 64 static const struct device *uart_dev = DEVICE_DT_GET(UART_DEVICE_NODE); static const struct device *regulators = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_regulators)); static const struct device *charger = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_charger)); static char rx_buf[BUFFER_SIZE]; static volatile int rx_buf_pos; void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data) { switch (evt->type) { case UART_RX_RDY: for (int i = 0; i < evt->data.rx.len; i++) { rx_buf[rx_buf_pos++] = evt->data.rx.buf[i]; if (rx_buf_pos >= BUFFER_SIZE) { rx_buf_pos = 0; } } break; case UART_RX_DISABLED: uart_rx_enable(dev, rx_buf, sizeof(rx_buf), 50); break; default: break; } } void configure_uart(void) { uart_callback_set(uart_dev, uart_cb, NULL); uart_rx_enable(uart_dev, rx_buf, sizeof(rx_buf), 50); } void process_command(const char *cmd) { if (strncmp(cmd, "GET_STATUS", 10) == 0) { struct sensor_value volt, current, temp, status, error; sensor_sample_fetch(charger); sensor_channel_get(charger, SENSOR_CHAN_GAUGE_VOLTAGE, &volt); sensor_channel_get(charger, SENSOR_CHAN_GAUGE_AVG_CURRENT, ¤t); sensor_channel_get(charger, SENSOR_CHAN_GAUGE_TEMP, &temp); sensor_channel_get(charger, SENSOR_CHAN_NPM1300_CHARGER_STATUS, &status); sensor_channel_get(charger, SENSOR_CHAN_NPM1300_CHARGER_ERROR, &error); printk("V: %d.%03d I: %d.%03d T: %d.%03d Status: %d Error: %d\n", volt.val1, volt.val2, current.val1, current.val2, temp.val1, temp.val2, status.val1, error.val1); } else if (strncmp(cmd, "SET_DVS ", 8) == 0) { int state = cmd[8] - '0'; if (state >= 0 && state <= 3) { regulator_parent_dvs_state_set(regulators, state); printk("Set DVS state to %d\n", state); } else { printk("Invalid DVS state\n"); } } else { printk("Unknown command\n"); } } void main(void) { if (!device_is_ready(uart_dev)) { printk("UART device not ready\n"); return; } if (!device_is_ready(regulators)) { printk("Regulator device not ready\n"); return; } if (!device_is_ready(charger)) { printk("Charger device not ready\n"); return; } configure_uart(); printk("UART initialized\n"); while (1) { if (rx_buf_pos > 0) { rx_buf[rx_buf_pos] = '\0'; process_command(rx_buf); rx_buf_pos = 0; } k_sleep(K_MSEC(100)); } }

逻辑是:

UART初始化: configure_uart 函数设置UART回调函数,并启用接收。

接收指令: uart_cb 回调函数将接收到的数据存储在缓冲区 rx_buf 中。

处理指令: process_command 函数根据接收到的指令执行相应的操作,例如获取PMIC状态

主循环: 在 main 函数的主循环中,检查缓冲区中是否有新的指令,并调用 process_command 进行处理。

这个测量设备之后会开源

RTOS的方法可能不是所有人都用的,也贴心的给出了耦合不强的纯C:

还单独的给出了zephyr的一个库,方便开发

我最后分析一个C库LDO的操作,为了后面给移植的朋友看:

这个驱动是对芯片的功能的封装

ADK里面是寄存器最底层的封装

里面都是这种封装:

MAIN_TASKSWRESET 宏定义

1TASKSWRESET: 控制寄存器中的位,用于触发系统的完全重启。

1TASKSWRESET_NOEFFECT: 表示该位为 0 时不产生任何效果。

1TASKSWRESET_TRIGGER: 当写入该位为 1 时,会触发任务,执行完全重启操作。

(0UL)

1这个表达式表示一个无符号长整型常量,其值为 0。

(0x1UL << MAIN_TASKSWRESET_TASKSWRESET_Pos)

10x1UL 是一个无符号长整型常量,其十六进制表示为 0x1,即二进制 0001。

1<< 是左移位操作符,用于将 0x1 左移 MAIN_TASKSWRESET_TASKSWRESET_Pos 位。

1MAIN_TASKSWRESET_TASKSWRESET_Pos 是宏定义中的位偏移量,它指示了在寄存器中要操作的位的位置。

例如,假设 MAIN_TASKSWRESET_TASKSWRESET_Pos 的值为 0,那么这个表达式将会计算为 0x1 << 0,结果为 0x1,即二进制 0001。这意味着这个宏定义生成了一个掩码,可以用来设置或清除特定寄存器中的位。

移植的时候,只要满足:

这两个函数就可以了。

代码语言:javascript
复制
https://github.com/NordicSemiconductor/npmx-zephyr
代码语言:javascript
复制
https://github.com/zephyrproject-rtos/zephyr/blob/main//samples/shields/npm1300_ek/doc/index.rst#id2
代码语言:javascript
复制
https://nordicsemiconductor.github.io/npmx/drivers/adc/index.html
代码语言:javascript
复制
https://docs.nordicsemi.com/bundle/ps_npm1300/page/chapters/ordering_info/doc/ordering_info.html
代码语言:javascript
复制
https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.7.pdf
代码语言:javascript
复制
https://www.nordicsemi.com/Products/nRF52840
代码语言:javascript
复制
https://product.torex.com.cn/cn/technical-support/techfaq/doc_4262
代码语言:javascript
复制
https://www.ti.com.cn/product/cn/MSPM0L1106?bm-verify=AAQAAAAJ_____94NfixNSc5gIZiom7vfqTlren0d_BxDX5T7ru2uqX2Oe9fynoDdF_Gax9xpW2SCpUSZaN3tCvlg_GkMLX8G3B7aJm1aHjLopBBDd7bsXOGAaOEyIJ7s3D3YVoSVmq8_uxM7X1AL0DCyqgSlw-HQJ40bcWiubEAvU1viLNvd_C4nrZa03jX8N6NDeOUh8NpF-RDu7uydQDSW70OCbGKWbKw5fU92YYJkPSYIL2tr59YJyGWasdyg-couassLwjI4UUxiIvjc45nj-Zw8dp28zfYAvYFELRji_M767hum8b35dVq1ICjoKst_ZAFM_d6vcK-8i6bG1xuEaUjUXZo
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云深之无迹 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据保险箱
数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档