GD32同INA3221监测电压电流

525 阅读3分钟

本人已参加 新人创作礼 活动,一起开启掘金创作之路。

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.

特点:

  1. 可感测的总线电压范围为0V至26V
  2. 能报告并联和总线电压
  3. 高精度 偏移电压:±80μV(最大值) 增益误差:0.25%(最大值)
  4. 可配置取平均选项
  5. 拥有四个可编程地址
  6. 可编程报警和警告输出
  7. 电源运行范围: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;    
}