本人已参加 新人创作礼 活动,一起开启掘金创作之路。
INA3221是一款三通道,高侧电流和总线电压监视器,具有一个兼容IIC和SMBUS的接口.INA3221不仅能够监视分流压降和总线电源电压,还针对这些信号提供有可编程的转换时间和平均值计算模式.INA3221提供关键报警和警告报警,用于检测每条通道上可编程的多种超范围情况。
INA3221感测总线(电压在0V至+ 26V范围内变化)上的电流。此器件由2.7V至5.5V单电源供电,电源电流消耗为350μA(典型值).IN3221的额定运行温度范围为-40°C至+ 125°C。兼容I 2 C和SMBUS的接口具有四个可编程地址。从INA3221的数据手册得知INA3221的7位通行地址为01000000.
特点:
- 可感测的总线电压范围为0V至26V
- 能报告并联和总线电压
- 高精度 偏移电压:±80μV(最大值) 增益误差:0.25%(最大值)
- 可配置取平均选项
- 拥有四个可编程地址
- 可编程报警和警告输出
- 电源运行范围:2.7V至5.5V
通过GD32单片机与INA3221芯片检测电压电流,GD32与INA3221的通行方式采用模拟IIC进行通信。
#define INA3221_ADDR (0X40<<1) //INA3221的通信地址
#define INA3221_CONFGI_REG 0X00 //配置寄存器
#define INA3221_CH1SHUNT_REG 0X01 //通道1分流电压
#define INA3221_CH1BUS_REG 0X02 //通道1总线电压
#define INA3221_CH2SHUNT_REG 0X03 //通道2分流电压
#define INA3221_CH2BUS_REG 0X04 //通道2总线电压
#define INA3221_CH3SHUNT_REG 0X05 //通道3分流电压
#define INA3221_CH3BUS_REG 0X06 //通道3总线电压
#define INA3221_CH1CAL_REG 0x07 //通道 1 严重警报限制
#define INA3221_CH1WAL_REG 0x08 //通道 1 警告警报限制
#define INA3221_CH2CAL_REG 0x09 //通道 2 严重警报限制
#define INA3221_CH2WAL_REG 0x0A //通道 2 警告警报限制
#define INA3221_CH3CAL_REG 0x0B //通道 3 严重警报限制
#define INA3221_CH3WAL_REG 0x0C //通道 3 警告警报限制
#define INA3221_SVS_REG 0x0D //分流电压和
#define INA3221_SVSLIMIT_REG 0x0E //分流电压和限制
#define INA3221_ME_REG 0x0F //屏蔽/启用 警报
#define INA3221_PVUPPER_REG 0x10 //功率有效上限
#define INA3221_PVLOW_REG 0x11 //功率有效下限
#define INA3221_MANUID_REG 0xFE //制造商标识号
#define INA3221_DIEID_REG 0xFF //模具标识号
#define INA3221_MANU_ID 0x5449 //唯一制造商标识号
#define INA3221_DIE_ID 0x3220 //唯一模具标识号
#define ImA(ShuntVoltage) ((ShuntVoltage>>3)*40/10)
typedef enum devinfo
{
MANUFACTURER_ID =1,
DIE_ID =2,
}DevInfo_Enum;
typedef enum devchs
{
Shunt_Channel_1 =1,
Bus_Channel_1 =2,
Shunt_Channel_2 =3,
Bus_Channel_2 =4,
Shunt_Channel_3 =5,
Bus_Channel_3 =6,
}DevChannel_Enum;
void INAXXXX_Init(void);
uint8_t INAXXXX_ReadOneByte(uint16_t ReadAddr);
void INAXXXX_WriteOneByte(uint16_t WriteAddr,uint8_t DataToWrite);
void INAXXXX_WriteLenByte(uint16_t WriteAddr,uint32_t DataToWrite,uint8_t Len);
uint32_t INAXXXX_ReadLenByte(uint16_t ReadAddr,uint8_t Len);
/**************************************/
void INAXXXX_SendData(uint8_t addr,uint8_t reg,uint16_t data);
uint16_t INAXXXX_ReadData(uint8_t addr);
void INAXXXX_SetRegPointer(uint8_t addr,uint8_t reg);
uint16_t INAXXXX_GetVoltage(uint8_t addr,DevChannel_Enum DevChannel);
uint16_t INAXXXX_GetShuntVoltage(uint8_t addr, DevChannel_Enum DevChannel);
void INAXXXX_DevCheck(uint8_t addr);
uint16_t INAXXXX_GetDevInfo(uint8_t addr,DevInfo_Enum DevInfo);
void INAXXXX_Init(void)
{
IIC_Init();
INAXXXX_SendData(INA3221_ADDR,INA3221_CONFGI_REG,0x8000);//软件复位
INAXXXX_SendData(INA3221_ADDR,INA3221_CONFGI_REG,0X7127);// 7127为默认配置
}
uint8_t INAXXXX_ReadOneByte(uint16_t ReadAddr)
{
uint8_t temp=0;
IIC_Start();
IIC_Send_Byte(0X80); //发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr>>8);//发送高地址
// IIC_Send_Byte(0X80+((ReadAddr/256)<<1));
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr%256); //发送低地址
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(0X81); //进入接收模式
IIC_Wait_Ack();
temp=IIC_Read_Byte(0);
IIC_Stop();//产生一个停止条件
return temp;
}
void INAXXXX_WriteOneByte(uint16_t WriteAddr,uint8_t DataToWrite)
{
IIC_Start();
IIC_Send_Byte(0X80); //发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr>>8);//发送高地址
// IIC_Send_Byte(0X80+((WriteAddr/256)<<1)); //发送器件地址0XA0,写数据
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr%256); //发送低地址
IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite); //发送字节
IIC_Wait_Ack();
IIC_Stop();//产生一个停止条件
delay_1ms(10);
}
void INAXXXX_WriteLenByte(uint16_t WriteAddr,uint32_t DataToWrite,uint8_t Len)
{
uint8_t t;
for(t=0;t<Len;t++)
{
INAXXXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
}
}
uint32_t INAXXXX_ReadLenByte(uint16_t ReadAddr,uint8_t Len)
{
uint8_t t;
uint32_t temp = 0;
for(t=0;t<Len;t++)
{
temp<<=8;
temp+=INAXXXX_ReadOneByte(ReadAddr+Len-t-1);
}
return temp;
}
void INAXXXX_SendData(uint8_t addr,uint8_t reg,uint16_t data)
{
uint8_t temp=0;
IIC_Start();
IIC_Send_Byte(addr);
IIC_Wait_Ack();
IIC_Send_Byte(reg);
IIC_Wait_Ack();
temp = (uint8_t)(data >> 8);
IIC_Send_Byte(temp);
IIC_Wait_Ack();
temp = (uint8_t)(data & 0x00FF);
IIC_Send_Byte(temp);
IIC_Wait_Ack();
IIC_Stop();
}
uint16_t INAXXXX_ReadData(uint8_t addr)
{
//读取数据
uint16_t temp = 0;
IIC_Start();
IIC_Send_Byte(addr+1);
IIC_Wait_Ack();
temp = IIC_Read_Byte(1);
temp <<= 8;
temp |= IIC_Read_Byte(0);
IIC_Stop();
return temp;
}
void INAXXXX_SetRegPointer(uint8_t addr,uint8_t reg)
{
IIC_Start();
IIC_Send_Byte(addr);
IIC_Wait_Ack();
IIC_Send_Byte(reg);
IIC_Wait_Ack();
IIC_Stop();
}
/*
**INAXXXX_GetVoltage:获取电压
**addr:7位芯片地址左移一位
**channel:通道号(1,2,3)
**temp:返回得到得到得电压
*/
uint16_t INAXXXX_GetVoltage(uint8_t addr,DevChannel_Enum DevChannel)
{
uint32_t temp=0;
switch(DevChannel)
{
case Bus_Channel_1:INAXXXX_SetRegPointer(addr,INA3221_CH1BUS_REG);
break;
case Bus_Channel_2:INAXXXX_SetRegPointer(addr,INA3221_CH2BUS_REG);
break;
case Bus_Channel_3:INAXXXX_SetRegPointer(addr,INA3221_CH3BUS_REG);
break;
}
temp = INAXXXX_ReadData(addr);
if(temp & 0X8000)
temp = ~(temp-1);
return (uint16_t)temp;
}
/*
**INAXXXX_GetShuntVoltage:获取分流电压
**addr:7位芯片地址左移一位
**channel:通道号(1,2,3)
**temp:返回得到得到得电压
*/
uint16_t INAXXXX_GetShuntVoltage(uint8_t addr, DevChannel_Enum DevChannel)
{
uint32_t temp = 0;
switch (DevChannel)
{
case Shunt_Channel_1:
INAXXXX_SetRegPointer(addr, INA3221_CH1SHUNT_REG);
break;
case Shunt_Channel_2:
INAXXXX_SetRegPointer(addr, INA3221_CH2SHUNT_REG);
break;
case Shunt_Channel_3:
INAXXXX_SetRegPointer(addr, INA3221_CH3SHUNT_REG);
break;
default:
break;
}
temp = INAXXXX_ReadData(addr);
if (temp & 0x8000)
temp = ~(temp - 1);
return (uint16_t)temp;
}
void INAXXXX_DevCheck(uint8_t addr)
{
uint32_t id = 0;
while(id != INA3221_DIE_ID)
{
// delay_ms(1);
delay_1ms(1);
//卡这说明硬件连接异常或者是地址错误
// printf("硬件连接异常或者是地址错误");
INAXXXX_SetRegPointer(addr,INA3221_DIEID_REG);
id = INAXXXX_ReadData(addr);
}
}
uint16_t INAXXXX_GetDevInfo(uint8_t addr,DevInfo_Enum DevInfo)
{
uint32_t temp = 0;
switch(DevInfo)
{
case MANUFACTURER_ID:INAXXXX_SetRegPointer(addr,INA3221_MANUID_REG);
break;
case DIE_ID:INAXXXX_SetRegPointer(addr,INA3221_DIEID_REG);
break;
}
temp = INAXXXX_ReadData(addr);
if (temp & 0x8000)
temp = ~(temp - 1);
return (uint16_t)temp;
}