MCU芯片AS32A601与INA226芯片精确测量实现与应用

电子说

1.4w人已加入

描述

一、引言

为满足精准的电源管理需求,国科安芯推出的AS32X601开发板特别搭载了INA226双向电流/功率监测芯片。该芯片不仅支持高达36V的总线电压,更能通过其集成的Δ-Σ ADC对分流电阻器上的压降进行高精度采样,从而实现毫伏级电压与微安级电流的精确测量。这一特性使其非常适用于电池充放电监控、服务器/工控设备能耗分析以及太阳能系统发电效率评估等高级应用场景。

二、INA226简介

INA226

2.1****引脚功能
INA226

INA226有两个地址引脚,A0和A1。下图描述了16个可能地址中的每一个的引脚逻辑。INA226模块A0 A1****引脚被下拉至 ** GND ** ,故 ** IIC 地址则为 ** Write1000 0000 0x80 Read1000 0001 0x81

INA226

2.2****寄存器介绍

INA226

2.2.1配置寄存器 0x00

配置寄存器设置控制设备的工作模式。该寄存器控制分流和总线电压测量以及所用的平均模式的转换时间设置。

INA226

INA226

2.2.2分流电压寄存器**** 0x01

用于存储当前的分流电压读数Vshunt。负数采用二进制补码格式表示。生成一个负数的补码方法是:对其绝对值的二进制数取反,然后加1。如果最高有效位(MSB)为1,则表示这是一个负数。最小分辨率(Vshunt _LSB)为 2.5uV。

INA226

注:分流电压最大81.92mV,而该模块的采样电阻是0.1R,故最大电流为 81.92mV / 0.1R = 819.2mA

分流电压计算:Vshunt = 寄存器值 * Vshunt _LSB(2.5uV)

2.2.3.总线电压寄存器 ** 0x02**

用于存储最近一次的总线电压读数 Vbus。如果启用了平均功能,则该寄存器显示的是平均后的数值。满量程范围为 40.96V(对应 7FFF);最小分辨率(Vbus_LSB)为 1.25 mV。

INA226

总线电压计算:Vbus = 寄存器值 * Vbus_LSB(1.25 mV )

2.2.4.功率寄存器 ** 0x03**

用于存储功率读数 Power ,如果启用了平均功能,该寄存器将显示平均值。功率寄存器的最低有效位(LSB)在内部被设定为等于 Current_LSB 所设定值的 25 倍。功率寄存器通过将电流寄存器的十进制值与总线电压寄存器的十进制值相乘来记录以瓦特(Watts)为单位的功率。

INA226

功率计算: Power = 寄存器值 * Power_ LSB

由手册可知 Power_LSB(功率最小分辨率) = Current_LSB(电流最小分辨率) * 25

Current_LSB 手册给出了计算公式,如下

INA226

Current_LSB = 最大电流 / 2^15 = 819.2mA / 2^15 = 0.025mA

2.2.5.电流寄存器 ** 0x04**

用于存储电流读数 Current,如果启用了平均功能,该寄存器将显示平均值。电流寄存器的值是通过将分流电压寄存器中的十进制值与校准寄存器中的十进制值相乘来计算的

INA226

电流值 = 寄存器值 * Current_LSB(0.05mA) (Current_LSB 的计算在上文功率寄存器小节已经给出)

2.2.6.基准寄存器 ** 0x05**

该寄存器为器件提供用于产生测量差分电压的分流电阻值。它还设置电流寄存器的分辨率。编程该寄存器可设置 Current_LSB 和 Power_LSB。该寄存器也适用于整体系统校准。

该寄存器主要是设置系统基准的,将 基准值(CAL) 写入寄存器即可

INA226

Current_LSB= 0.05mA (上文功率寄存器小节已经给出) ,根据原理图可知 Rshunt = 0.1R

CAL = 0.00512 / (0.00005A * 0.1R) = 1024 = 0x0400

三、I2C时序说明

**3.1 **写时序

INA226

FlagStatus I2C_MEEPROMWriteByte(I2C_TypeDef* I2Cx, uint8_t addr, uint16_t reg, uint16_t data, uint32_t timeout)

{

/ 等待总线释放 /

while (!I2C_CheckStatus(I2Cx, I2C_BUS_IDLE))

{

I2C_StartClear(I2Cx);

I2C_GenerateStop(I2Cx);

I2C_ClearITPendingBit(I2Cx);

if ((timeout--) == 0)

{

return RESET;

}

delay_ms(1);

}

I2C_GenerateStart(I2Cx);

/ 等待启动信号完成 /

while (!I2C_CheckStatus(I2Cx, MASTER_START_READY))

{

if ((timeout--) == 0)

{

return RESET;

}

delay_ms(1);

}

I2C_Send7bitAddress(I2Cx, addr, I2C_WRITE);

I2C_StartClear(I2Cx);

I2C_ClearITPendingBit(I2Cx);

/ 等待从机接收完成地址并发送ack /

while (!I2C_CheckStatus(I2Cx, MSEND_WADDR_ACK))

{

if ((timeout--) == RESET)

{

I2C_GenerateStop(I2Cx);

I2C_ClearITPendingBit(I2Cx);

return RESET;

}

delay_ms(1);

}

I2C_SendData(I2Cx, (uint8_t)(reg >> 0));

I2C_ClearITPendingBit(I2Cx);

/ 等待从机接收完成数据并发送ack /

while (!I2C_CheckStatus(I2Cx, MSEND_DATA_ACK))

{

if ((timeout--) == 0)

{

I2C_GenerateStop(I2Cx);

I2C_ClearITPendingBit(I2Cx);

return RESET;

}

delay_ms(1);

}

I2C_SendData(I2Cx, (data&0xff00)>>8);

I2C_ClearITPendingBit(I2Cx);

/ 等待从机接收完成数据并发送ack /

while (!I2C_CheckStatus(I2Cx, MSEND_DATA_ACK))

{

if ((timeout--) == 0)

{

I2C_GenerateStop(I2Cx);

I2C_ClearITPendingBit(I2Cx);

return RESET;

}

delay_ms(1);

}

I2C_SendData(I2Cx, data&0x00ff);

I2C_ClearITPendingBit(I2Cx);

/ 等待从机接收完成数据并发送ack /

while (!I2C_CheckStatus(I2Cx, MSEND_DATA_ACK))

{

if ((timeout--) == 0)

{

I2C_GenerateStop(I2Cx);

I2C_ClearITPendingBit(I2Cx);

return RESET;

}

delay_ms(1);

}

I2C_GenerateStop(I2Cx);

I2C_ClearITPendingBit(I2Cx);

return 1;

}

3.2 读时序

INA226

FlagStatus I2C_MEEPROMRead(I2C_TypeDef* I2Cx, uint8_t addr, uint16_t reg, uint8_t* pData, uint32_t Size, uint32_t timeout)

{

uint32_t num = 0x00;

/ 等待总线释放 /

while (!I2C_CheckStatus(I2Cx, I2C_BUS_IDLE))

{

I2C_StartClear(I2Cx);

I2C_GenerateStop(I2Cx);

I2C_ClearITPendingBit(I2Cx);

if ((timeout--) == 0)

{

return RESET;

}

delay_ms(1);

}

I2C_AcknowledgeConfig(I2Cx, I2C_IICAA_ACK);

I2C_GenerateStart(I2Cx);

/ 等待启动信号完成 /

while (!I2C_CheckStatus(I2Cx, MASTER_START_READY))

{

if ((timeout--) == 0)

{

I2C_StartClear(I2Cx);

I2C_GenerateStop(I2Cx);

I2C_ClearITPendingBit(I2Cx);

return RESET;

}

delay_ms(1);

}

I2C_Send7bitAddress(I2Cx, addr, I2C_WRITE);

I2C_StartClear(I2Cx);

I2C_ClearITPendingBit(I2Cx);

/ 等待从机接收完成地址并发送ack /

while (!I2C_CheckStatus(I2Cx, MSEND_WADDR_ACK))

{

if ((timeout--) == 0)

{

I2C_GenerateStop(I2Cx);

I2C_ClearITPendingBit(I2Cx);

return RESET;

}

delay_ms(1);

}

// I2C_SendData(I2Cx, (uint8_t)(reg >> 8));

// I2C_ClearITPendingBit(I2Cx);

// / 等待从机接收完成数据并发送ack /

// while (!I2C_CheckStatus(I2Cx, MSEND_DATA_ACK))

// {

// if ((timeout--) == 0)

// {

// I2C_GenerateStop(I2Cx);

// I2C_ClearITPendingBit(I2Cx);

// return 0;

// }

// delay_ms(1);

// }

I2C_SendData(I2Cx, (uint8_t)(reg >> 0));

I2C_ClearITPendingBit(I2Cx);

/ 等待从机接收完成数据并发送ack /

while (!I2C_CheckStatus(I2Cx, MSEND_DATA_ACK))

{

if ((timeout--) == 0)

{

I2C_GenerateStop(I2Cx);

I2C_ClearITPendingBit(I2Cx);

return RESET;

}

delay_ms(1);

}

I2C_GenerateStart(I2Cx);

I2C_ClearITPendingBit(I2Cx);

/ 等待从机接收完成数据并发送ack /

while (!I2C_CheckStatus(I2Cx, MASTER_START_REPEAT))

{

if ((timeout--) == 0)

{

I2C_GenerateStop(I2Cx);

I2C_ClearITPendingBit(I2Cx);

return RESET;

}

delay_ms(1);

}

I2C_Send7bitAddress(I2Cx, addr, I2C_READ);

I2C_ClearITPendingBit(I2Cx);

/ 等待从机接收完成地址并发送ack /

while (!I2C_CheckStatus(I2Cx, MSEND_RADDR_ACK))

{

if ((timeout--) == 0)

{

I2C_StartClear(I2Cx);

I2C_GenerateStop(I2Cx);

I2C_ClearITPendingBit(I2Cx);

return RESET;

}

delay_ms(1);

}

for (num = 0; num < Size; num++)

{

if (num == (Size - 1))

{

/* IIC sends NACK */

I2C_AcknowledgeConfig(I2Cx, I2C_IICAA_NACK);

}

else

{

I2C_AcknowledgeConfig(I2Cx, I2C_IICAA_ACK);

}

I2C_StartClear(I2Cx);

I2C_ClearITPendingBit(I2Cx);

/* Wait for the slave to send the completed data, and the host will send an ack */

while (!(I2C_CheckStatus(I2Cx, MREAD_DATA_ACK) || I2C_CheckStatus(I2Cx, MREAD_DATA_NACK)))

{

if ((Timeout--) == 0)

{

I2C_StartClear(I2Cx);

I2C_GenerateStop(I2Cx);

I2C_ClearITPendingBit(I2Cx);

return RESET;

}

delay_ms(1);

}

*pData++ = I2C_ReceiveData(I2Cx);

}

I2C_StartClear(I2Cx);

I2C_GenerateStop(I2Cx);

I2C_ClearITPendingBit(I2Cx);

return SET;

}

四、程序

指令

#define I2C I2C0

// INA226 I2C地址(根据A0和A1引脚配置决定)

#define INA226_ADDRESS 0x40

// INA226寄存器定义

#define INA226_REG_CONFIG 0x00

#define INA226_REG_SHUNT_VOLT 0x01

#define INA226_REG_BUS_VOLT 0x02

#define INA226_REG_POWER 0x03

#define INA226_REG_CURRENT 0x04

#define INA226_REG_CALIB 0x05

#define INA226_REG_MASK_ENABLE 0x06

#define INA226_REG_ALERT_LIMIT 0x07

#define INA226_REG_MANUFACTURER 0xFE

#define INA226_REG_DIE_ID 0xFF

#define Byte_NUMBER 2

main.c

void main()

{

Systemclock_Init();

uint8_t rdata[2] = {0};

delay_init(SMU_ClocksStruct.AXIBus0_Frequency/1000000);

#ifdef DEBUG

IIC0_RESET();

delay_ms(100);

IIC0_SET();

#endif

/* Initialize print usart */

User_Print_Init(115200);

Printf( "INNA226 test begin! n");

User_I2C_Init();

/* Configuration Register */

I2C_MEEPROMWriteByte(I2C, INA226_ADDRESS, INA226_REG_CONFIG, 0x4527, 1000);

delay_ms(1);

/* Calibration Register */

I2C_MEEPROMWriteByte(I2C, INA226_ADDRESS, INA226_REG_CALIB, 0x0A00, 1000);

delay_ms(1);

/* Printf INNA226 ID */

I2C_MEEPROMRead(I2C, INA226_ADDRESS, INA226_REG_MANUFACTURER, rdata, Byte_NUMBER, 2000);

Printf("INNA226 ID:%x%x rn",rdata[0], rdata[1]);

for (int i = 0; i<10; i++)

{

/* Printf INA226_REG_SHUNT_VOLT */

uint16_t shuntVolt=0;

I2C_MEEPROMRead(I2C, INA226_ADDRESS, INA226_REG_SHUNT_VOLT, rdata, Byte_NUMBER, 2000);

shuntVolt = rdata[0]<<8&0xff00 | rdata[1];

Printf("SHUNT VOLT: %f mVrn", shuntVolt2.50.001);

delay_ms(10);

uint16_t busVolt=0;

I2C_MEEPROMRead(I2C, INA226_ADDRESS, INA226_REG_BUS_VOLT, rdata, Byte_NUMBER, 2000);

busVolt = rdata[0]<<8&0xff00 | rdata[1];

Printf("busVolt: %f mVrn", shuntVolt*1.25);

delay_ms(10);

/* Printf INA226_REG_POWER */

uint16_t Power=0;

I2C_MEEPROMRead(I2C, INA226_ADDRESS, INA226_REG_POWER, rdata, Byte_NUMBER, 2000);

Power = rdata[0]<<8&0xff00 | rdata[1];

Printf("Power: %f mWrn", Power*1.25);

/* Printf INA226_REG_SHUNT_VOLT */

uint16_t current=0;

I2C_MEEPROMRead(I2C, INA226_ADDRESS, INA226_REG_CURRENT, rdata, Byte_NUMBER, 2000);

current = rdata[0]<<8&0xff00 | rdata[1];

Printf("CUURET :%f mArn", current*0.02);

delay_ms(100);

Printf("--------------------------rn");

}

while (1);

}

五、实验结果

INA226

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分