2026 Make Blocks #3阶段2 - 基于 INA260 高精度电流功率监测模块实现
该项目使用了TI INA260AIPWR 作为核心芯片,实现了高精度电流功率监测模块的设计,它的主要功能为:能实时测量直流回路的电压、电流,并输出功率值,可用于电源效率分析、电池电量监测等场景。
标签
得捷电子
功率计
电流检测
IIC
INA260
lirongman
更新2026-07-07
延安大学
49
KiCad文件
全屏

2026 Make Blocks #3阶段2 - INA260 高精度电流功率监测模块实现

一、任务介绍

本次设计的任务是设计一款电流和功率监测模块,能实时测量直流回路的电压、电流,并输出功率值,可用于电源效率分析、电池电量监测等场景。

具体要求包括:使用高侧电流监测专用IC;支持0~26V总线电压测量;数字接口输出(I2C);内部集成分流电阻;提供输入和输出接线端子。选用了 TI INA260AIPWR 作为核心芯片。该芯片内部集成了高精度2mΩ分流电阻和16ADC,可直接通过I2C接口读出电压、电流、功率和电能累积值,大幅简化了硬件设计,同时保证了测量精度。

INA260DigiKey 官网链接
https://www.digikey.cn/zh/products/detail/texas-instruments/ina260aipwr/6590780




二、设计方案介绍

2.1 整体方案概述

本模块采用 INA260 + 3.3V I2C接口 + 输入/输出排针 的架构,外围仅需两颗去耦电容、两颗I2C上拉电阻和一颗LED电源指示灯。

  • 测量方式:高侧电流检测(电流从IN+流入,从IN-流出)
  • 电压测量VBUS引脚连接到IN-(负载正极),测量负载两端电压
  • 功率计算:芯片内部自动完成(电压 × 电流)
  • 数字接口I2C,地址固定为0x40A0/A1GND
  • 报警输出ALERT引脚引出,可配置为过流/过压中断

2.2 板上资源框图

2.3 工具与设备清单

工具/设备

用途

数字万用表

测量电压、通断、电阻值

直流稳压电源

提供3.3V和待测电压(0~26V

直流电机

制造电流回路

串口调试助手

接收UART输出数据

CW32F030系统板

作为I2C主机读取INA260数据

OLED 128x64屏幕

本地数据显示

烙铁、焊锡、助焊剂

焊接元器件

 



三、模块介绍(主要芯片选型与功能)

3.1 核心芯片:Texas Instruments INA260AIPWR
INA260 是德州仪器推出的一款高精度、低漂移的电流/电压/功率监测芯片,内部集成了 2mΩ 精密分流电阻16Δ-Σ ADC I2C 数字接口,可直接输出电压、电流、功率和电能累积值。

主要技术参数


参数

总线电压范围

0 ~ 36V

电流量程

±15A(持续)

精度(增益误差)

±0.15%(最大值,出厂校准)

温漂

10ppm/°C

ADC 分辨率

16

电压分辨率

1.25mV/LSB

电流分辨率

1.25mA/LSB

功率分辨率

10mW/LSB

供电电压

2.7V ~ 5.5V

接口

I2C16个可选地址)

封装

TSSOP-165×4.4mm

工作温度

-40°C ~ +125°C


3.2 其他主要元件

位号

型号

规格

功能

C1, C2

CL10B104KB8NNNC / 10μF

0603 贴片电容

电源去耦,稳定 VS 电压

R2, R4

FRC0603F1002TS

10kΩ 0603 1%

I2C 总线 SCL/SDA 上拉电阻

R1

0603WAF1001T5E

1kΩ 0603 1%

LED 限流电阻

PWR1

GL0603UB01

0603 蓝色 LED

3.3V 电源指示灯

H1, H2

PZ254V-11-02P

2.54mm 2P 排针

电源输入/输出接口

U1

DS1021-1X5SF11-B

2.54mm 5P 排针

I2C + ALERT 引出接口




四、原理图和 PCB 设计介绍

4.1 原理图设计

image.png

设计要点

  1. 电流测量路径
    H1-1 (VIN+) → U3-IN+ (P1-3) → [内部2mΩ电阻] → U3-IN- (P14-16) → H2-1 (VOUT+)
  2. 电压测量
    U3-VBUS (P12) 短接至 IN-H2-1),测量负载正极对 GND 的电压
  3. 电源与去耦
    U3-VS (P10) 3.3VC1(0.1μF) C2(10μF) 并联在 VS GND 之间,靠近芯片引脚
  4. I2C 接口
    SCL (P9) SDA (P8) 通过 R2R4(10kΩ) 上拉至 3.3V,引出至 5 针排针 U1
  5. 地址配置
    A0 (P5) A1 (P4) 直接接 GNDI2C 地址固定为 0x40
  6. 电源指示灯
    R1(1kΩ) + 蓝色 LED 串联在 3.3V GND 之间,上电即亮
  7. 报警输出
    ALERT (P7) 引出至 U1-5,供外部 MCU 作为中断输入(开漏输出,需外部上拉)

4.2 PCB 设计要点

设计项

要求

电流路径线宽

局部铺铜(IN+&IN-

去耦电容位置

C1C2 尽可能靠近 U3 VS GND 引脚

芯片摆放

INA260 尽量靠近输入排针 H1,缩短电流路径

底层 GND 铜皮

整板铺地,降低回路阻抗

排针布局

H1H2 位于板子两侧,U1 位于边缘便于插拔

外形尺寸

1.60mm × 1.60mm 双层板


精度高、体积小巧

仅16.0mmx16.0mm



五、模块主要性能指标和引脚定义

5.1 电气性能

参数

最小值

典型值

最大值

单位

供电电压

2.7

3.3

5.5

V

静态电流

0.42

0.7

mA

总线电压

0

36

V

可测电流

-15

+15

A

电压分辨率

1.25

mV/LSB

电流分辨率

1.25

mA/LSB

精度(增益误差)

±0.15

%

5.2 接口定义

电源输入/输出(H1, H22.54mm 2P 排针)

端子

引脚

功能

H1

1

VIN+(接电源正极)


2

GND(接电源负极)

H2

1

VOUT+(接负载正极)


2

GND(接负载负极)

I2C + 报警接口(U12.54mm 5P 排针)

引脚

信号

说明

1

3.3V

模块供电输出(可给外部 MCU 供电)

2

GND

3

SCL

I2C 时钟线

4

SDA

I2C 数据线

5

ALERT

报警输出(开漏,低有效)

5.3 I2C 通信

  • 从机地址0x407位,A0=A1=GND
  • 支持时钟速度100kHz / 400kHz / 1MHz / 2.5MHz

主要寄存器

寄存器名称

地址

说明

Configuration

0x00

配置 ADC 模式、转换时间等

Current

0x01

电流值,LSB = 1.25mA

Bus Voltage

0x02

总线电压,LSB = 1.25mV

Power

0x03

功率值,LSB = 10mW

Energy

0x04

电能累积值

Charge

0x05

电荷累积值

 



六、功能验证与数据测试

6.1 调试验证

12V电池作为电源,经过DC-DC降压为5V供负载-直流电机.

12V-1A

       IN+12V电池正极 IN-dc-dc输入端

5V-2A:

IN+dc-dc输出端 IN-接负载电机

6.2 测试数据记录

测试场景15V供电,负载2A

参数

万用表实测

INA260读值

误差

电压

4.46V

4.455V

-0.11%

电流

1.94A

1.942A

+0.1%

功率

8.65W

8.651W

+0.012%

 

测试场景212V供电,负载1A

参数

万用表实测

INA260读值

误差

电压

11.95V

11.958V

-0.067%

电流

1.02A

1.018A

-0.20%

功率

12.18W

12.17W

-0.08%

6.3 功能展示

显示界面(OLED 128x64):

串口输出(115200bps):




七、关键代码

所用调试软件KEIL5,串口调试助手。

驱动部分:

/**
* @brief I2C 写寄存器
*/
static uint8_t INA260_I2C_WriteBytes(uint8_t reg, uint8_t *data, uint8_t len)
{
uint8_t state, idx = 0, reg_sent = 0;
uint32_t timeout;

I2C_GenerateSTART(INA260_I2C, ENABLE);

while (1) {
timeout = 0xFFFFF;
while (I2C_GetIrq(INA260_I2C) == 0) {
if (--timeout == 0) {
I2C_GenerateSTOP(INA260_I2C, ENABLE);
I2C_ClearIrq(INA260_I2C);
return 1;
}
}

state = I2C_GetState(INA260_I2C);

switch (state) {
case 0x08: /* START 已发送 */
I2C_GenerateSTART(INA260_I2C, DISABLE);
I2C_Send7bitAddress(INA260_I2C, 0x80, I2C_Direction_Transmitter);
break;

case 0x18: /* SLA+W ACK */
if (reg_sent == 0) {
I2C_SendData(INA260_I2C, reg);
reg_sent = 1;
} else {
I2C_SendData(INA260_I2C, data[idx++]);
}
break;

case 0x28: /* 数据发送完成 */
if (idx < len) {
I2C_SendData(INA260_I2C, data[idx++]);
} else {
I2C_GenerateSTOP(INA260_I2C, ENABLE);
I2C_ClearIrq(INA260_I2C);
return 0;
}
break;

case 0x20: case 0x30: case 0x38: /* NACK/仲裁丢失 */
default:
I2C_GenerateSTOP(INA260_I2C, ENABLE);
I2C_ClearIrq(INA260_I2C);
return 1;
}
I2C_ClearIrq(INA260_I2C);
}
}

/**
* @brief I2C 读寄存器
*/
static uint8_t INA260_I2C_ReadBytes(uint8_t reg, uint8_t *data, uint8_t len)
{
uint8_t state, idx = 0, phase = 0;
uint32_t timeout;

I2C_GenerateSTART(INA260_I2C, ENABLE);

while (1) {
timeout = 0xFFFFF;
while (I2C_GetIrq(INA260_I2C) == 0) {
if (--timeout == 0) {
I2C_GenerateSTOP(INA260_I2C, ENABLE);
I2C_ClearIrq(INA260_I2C);
return 1;
}
}

state = I2C_GetState(INA260_I2C);

switch (state) {
case 0x08: /* START, 发送 SLA+W */
I2C_GenerateSTART(INA260_I2C, DISABLE);
I2C_Send7bitAddress(INA260_I2C, 0x80, I2C_Direction_Transmitter);
phase = 0;
break;

case 0x10: /* 重复 START, 发送 SLA+R */
I2C_GenerateSTART(INA260_I2C, DISABLE);
I2C_Send7bitAddress(INA260_I2C, 0x80, I2C_Direction_Receiver);
phase = 1;
break;

case 0x18: /* SLA+W ACK, 发寄存器地址 */
I2C_SendData(INA260_I2C, reg);
break;

case 0x28: /* 寄存器地址发完, 发重复 START */
INA260_I2C->CR_f.STA = 1; /* 直接写 STA,不用库函数 */
break;

case 0x40: /* SLA+R ACK, 准备收数据 */
I2C_AcknowledgeConfig(INA260_I2C, len > 1 ? ENABLE : DISABLE);
break;

case 0x50: /* 收到数据 + ACK */
data[idx++] = I2C_ReceiveData(INA260_I2C);
if (idx == len - 1) {
I2C_AcknowledgeConfig(INA260_I2C, DISABLE); /* 最后一个回 NACK */
}
break;

case 0x58: /* 收到最后字节 + NACK, 结束 */
data[idx++] = I2C_ReceiveData(INA260_I2C);
I2C_GenerateSTOP(INA260_I2C, ENABLE);
I2C_ClearIrq(INA260_I2C);
return 0;

case 0x48: /* SLA+R NACK */
default:
I2C_GenerateSTOP(INA260_I2C, ENABLE);
I2C_ClearIrq(INA260_I2C);
return 1;
}
I2C_ClearIrq(INA260_I2C);
}
}

/**
* @brief 读 16 位寄存器
*/
uint8_t INA260_ReadRegister(uint8_t reg, uint16_t *val)
{
uint8_t buf[2];
if (INA260_I2C_ReadBytes(reg, buf, 2)) return 1;
*val = (buf[0] << 8) | buf[1];
return 0;
}

/**
* @brief 写 16 位寄存器
*/
uint8_t INA260_WriteRegister(uint8_t reg, uint16_t val)
{
uint8_t buf[2] = {val >> 8, val & 0xFF};
return INA260_I2C_WriteBytes(reg, buf, 2);
}

/**
* @brief 读电压 (V)
*/
uint8_t INA260_ReadBusVoltage(float *v)
{
uint16_t raw;
if (INA260_ReadRegister(0x02, &raw)) return 1;
*v = (float)(raw & 0x7FFF) * 0.00125f; /* 1.25mV/bit */
return 0;
}

/**
* @brief 读电流 (A)
*/
uint8_t INA260_ReadCurrent(float *i)
{
uint16_t raw;
if (INA260_ReadRegister(0x01, &raw)) return 1;
*i = (float)((int16_t)raw) * 0.00125f; /* 1.25mA/bit */
return 0;
}

/**
* @brief 读功率 (W)
*/
uint8_t INA260_ReadPower(float *p)
{
uint16_t raw;
if (INA260_ReadRegister(0x03, &raw)) return 1;
*p = (float)raw * 0.01f; /* 10mW/bit */
return 0;
}

主函数:

int32_t main(void)
{
uint8_t u8InaReady = 0;
INA260_ReadingsTypeDef tReadings;
uint32_t u32LastPrint = 0;
uint32_t u32LedPeriod = 500;

/* 1. SysTick 1ms 中断 */
SysTick_Config(SystemCoreClock / 1000);

/* 2. LED 初始化 (PC13) */
__RCC_GPIOC_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pins = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_Init(CW_GPIOC, &GPIO_InitStruct);
GPIO_WritePin(CW_GPIOC, GPIO_PIN_13, GPIO_Pin_RESET); /* 亮 */

/* 3. 串口初始化 */
UART1_Init_ForPrintf();
printf("\r\nINA260 Monitor\r\n");

/* 4. OLED 初始化 */
OLED_Init();
OLED_Clear();
OLED_ShowString(1, 3, "INA260 Monitor");

/* 5. INA260 初始化 */
if (INA260_Init() == 0) {
u8InaReady = 1;
printf("INA260 OK!\r\n");
OLED_ShowString(4, 1, "INA260: OK");
} else {
printf("INA260 FAILED!\r\n");
OLED_ShowString(4, 1, "INA260: OFF");
}

/* 主循环 */
while (1) {
if (u8InaReady) {
/* 读取数据 */
if (INA260_ReadAll(&tReadings) == 0) {
/* LED 周期 = 功率越大闪越快 */
if (tReadings.fPower > 0.1f) {
u32LedPeriod = 50 + (uint32_t)(950.0f / (tReadings.fPower * 10.0f + 1.0f));
if (u32LedPeriod > 1000) u32LedPeriod = 1000;
} else {
u32LedPeriod = 1000;
}

/* 每秒打印 + 刷新 OLED */
if ((GetTick() - u32LastPrint) >= 1000) {
u32LastPrint = GetTick();
printf("V=%.3fV I=%.4fA P=%.4fW\r\n",
tReadings.fBusVoltage, tReadings.fCurrent, tReadings.fPower);
OLED_DisplayPowerInfo(tReadings.fBusVoltage,
tReadings.fCurrent,
tReadings.fPower);
}
}
} else {
/* 不在线则每 2 秒重试 */
if ((GetTick() - u32LastPrint) >= 2000) {
u32LastPrint = GetTick();
if (INA260_Init() == 0) {
u8InaReady = 1;
printf("INA260 OK!\r\n");
OLED_ShowString(4, 1, "INA260: OK");
}
}
}

/* LED 闪烁 */
if ((GetTick() % u32LedPeriod) < (u32LedPeriod / 2)) {
GPIO_WritePin(CW_GPIOC, GPIO_PIN_13, GPIO_Pin_RESET); /* 亮 */
} else {
GPIO_WritePin(CW_GPIOC, GPIO_PIN_13, GPIO_Pin_SET); /* 灭 */
}
}
}


八、心得体会

通过本次设计,我深刻体会到了选对芯片比画好电路更重要的含义。

第一,焊接质量决定调试效率。 本次调试中80%的问题(LED不亮、I2C无响应)都源于焊接不良。TSSOP-16封装虽然不算小,但拖焊时仍然容易连锡或虚焊。建议焊接后用万用表逐个引脚测量对地电压,比用放大镜目检更可靠。

第二,上电前检查是保命符。 有两次差点把3.3V直接怼到GND——多亏了先测通断的习惯。建议把"目检测电阻上电"三步曲刻在肌肉记忆里。

第三,INA260真的省心。 内部集成2mΩ电阻和校准数据,焊完就能用,不需要外接采样电阻,也不需要做温漂补偿。对比之前用INA219外加2512电阻的方案,设计周期至少缩短了一周。

 

软硬件
附件下载
cw32f030.zip
INA260验证测试工程文件
INA219.zip
INA219.kicad_sch
INA219.kicad_pcb
团队介绍
lirongman
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号