/*************************************************************************************************************************************************************
Copyright (C), 2023-2024, First-micro Tech. Co., Ltd.
File name: ina3221.c
Author: Edgar Version: V1.0 Date: 20230902
Description:
Static Function List:
1.
Extern Function List:
1.
History:
1. Date: 20230902
Author: Edgar
Modification: 创建此文件
2. ...
*************************************************************************************************************************************************************/
#include "ina3221.h"
#include "iic.h"
/*************************************************************************************************************************************************************
外部变量声明区
*************************************************************************************************************************************************************/
/*************************************************************************************************************************************************************
全局变量声明区
*************************************************************************************************************************************************************/
u8 Ina3221Setp = 0; //电流采样状态机步骤标志位
stcINA3221 INA3221[4][4] = {0};
void Ina3221_Delay( void )
{
Delay_us(2);
}
void Ina3221_Iic1_Init(void)
{
stc_gpio_init_t stcGpioInit;
(void)GPIO_StructInit(&stcGpioInit);
stcGpioInit.u16PinDir = PIN_DIR_OUT;
stcGpioInit.u16PullUp = PIN_PU_OFF;
stcGpioInit.u16PinDrv = PIN_HIGH_DRV;
stcGpioInit.u16PinOutputType = PIN_OUT_TYPE_CMOS;
(void)GPIO_Init (INA3221_IIC1_SCL_PORT, INA3221_IIC1_SCL_PIN, &stcGpioInit);
(void)GPIO_Init (INA3221_IIC1_SDA_PORT, INA3221_IIC1_SDA_PIN, &stcGpioInit);
GPIO_SetFunc (INA3221_IIC1_SCL_PORT, INA3221_IIC1_SCL_PIN, INA3221_IIC1_SCL_FUNC);
GPIO_SetFunc (INA3221_IIC1_SDA_PORT, INA3221_IIC1_SDA_PIN, INA3221_IIC1_SDA_FUNC);
GPIO_SetPins (INA3221_IIC1_SCL_PORT, INA3221_IIC1_SCL_PIN);
GPIO_SetPins (INA3221_IIC1_SDA_PORT, INA3221_IIC1_SDA_PIN);
}
void Ina3221_Iic1_SclOutCfg(void)
{
stc_gpio_init_t stcGpioInit;
(void)GPIO_StructInit(&stcGpioInit);
stcGpioInit.u16PinDir = PIN_DIR_OUT;
stcGpioInit.u16PullUp = PIN_PU_OFF;
stcGpioInit.u16PinDrv = PIN_HIGH_DRV;
stcGpioInit.u16PinOutputType = PIN_OUT_TYPE_CMOS;
(void)GPIO_Init(INA3221_IIC1_SCL_PORT, INA3221_IIC1_SCL_PIN, &stcGpioInit);
}
void Ina3221_Iic1_SdaOutCfg(void)
{
stc_gpio_init_t stcGpioInit;
(void)GPIO_StructInit(&stcGpioInit);
stcGpioInit.u16PinDir = PIN_DIR_OUT;
stcGpioInit.u16PullUp = PIN_PU_OFF;
stcGpioInit.u16PinDrv = PIN_HIGH_DRV;
stcGpioInit.u16PinOutputType = PIN_OUT_TYPE_CMOS;
(void)GPIO_Init(INA3221_IIC1_SDA_PORT, INA3221_IIC1_SDA_PIN, &stcGpioInit);
}
void Ina3221_Iic1_SdaInCfg(void)
{
stc_gpio_init_t stcGpioInit;
(void)GPIO_StructInit(&stcGpioInit);
stcGpioInit.u16PinDir = PIN_DIR_IN;
(void)GPIO_Init(INA3221_IIC1_SDA_PORT, INA3221_IIC1_SDA_PIN, &stcGpioInit);
}
void Ina3221_Iic1_SdaWR(u8 Level)
{
(Level) ? GPIO_SetPins(INA3221_IIC1_SDA_PORT,INA3221_IIC1_SDA_PIN) : GPIO_ResetPins(INA3221_IIC1_SDA_PORT,INA3221_IIC1_SDA_PIN);
}
void Ina3221_Iic1_SclWR(u8 Level)
{
(Level) ? GPIO_SetPins(INA3221_IIC1_SDA_PORT,INA3221_IIC1_SDA_PIN) : GPIO_ResetPins(INA3221_IIC1_SDA_PORT,INA3221_IIC1_SDA_PIN);
}
u8 Ina3221_Iic1_SclRD(void)
{
return GPIO_ReadInputPins(INA3221_IIC1_SDA_PORT,INA3221_IIC1_SDA_PIN);
}
//注册函数
IIC_TypeDef IIC1_INA3221 = {
.index = 0,
.I2C_addr = 0,
.Delay = Ina3221_Delay,
.Init_Cfg = Ina3221_Iic1_Init,
.SCL_Out_Cfg = Ina3221_Iic1_SclOutCfg,
.SDA_Out_Cfg = Ina3221_Iic1_SdaOutCfg,
.SDA_In_Cfg = Ina3221_Iic1_SdaInCfg,
.SCL_WR = Ina3221_Iic1_SclWR,
.SDA_WR = Ina3221_Iic1_SdaWR,
.SDA_RD = Ina3221_Iic1_SclRD
};
IIC_TypeDef IIC2_INA3221 = {
.index = 1,
.I2C_addr = 0,
.Delay = Ina3221_Delay,
.Init_Cfg = Ina3221_Iic1_Init,
.SCL_Out_Cfg = Ina3221_Iic1_SclOutCfg,
.SDA_Out_Cfg = Ina3221_Iic1_SdaOutCfg,
.SDA_In_Cfg = Ina3221_Iic1_SdaInCfg,
.SCL_WR = Ina3221_Iic1_SclWR,
.SDA_WR = Ina3221_Iic1_SdaWR,
.SDA_RD = Ina3221_Iic1_SclRD
};
IIC_TypeDef IIC3_INA3221 = {
.index = 2,
.I2C_addr = 0,
.Delay = Ina3221_Delay,
.Init_Cfg = Ina3221_Iic1_Init,
.SCL_Out_Cfg = Ina3221_Iic1_SclOutCfg,
.SDA_Out_Cfg = Ina3221_Iic1_SdaOutCfg,
.SDA_In_Cfg = Ina3221_Iic1_SdaInCfg,
.SCL_WR = Ina3221_Iic1_SclWR,
.SDA_WR = Ina3221_Iic1_SdaWR,
.SDA_RD = Ina3221_Iic1_SclRD
};
IIC_TypeDef IIC4_INA3221 = {
.index = 3,
.I2C_addr = 0,
.Delay = Ina3221_Delay,
.Init_Cfg = Ina3221_Iic1_Init,
.SCL_Out_Cfg = Ina3221_Iic1_SclOutCfg,
.SDA_Out_Cfg = Ina3221_Iic1_SdaOutCfg,
.SDA_In_Cfg = Ina3221_Iic1_SdaInCfg,
.SCL_WR = Ina3221_Iic1_SclWR,
.SDA_WR = Ina3221_Iic1_SdaWR,
.SDA_RD = Ina3221_Iic1_SclRD
};
u8 Ina3221SendData(IIC_TypeDef I2C ,u8 reg,u8 *data,u8 Size)
{
I2cStart(I2C);
I2cSendByte(I2C, I2C.I2C_addr);
I2cWaitAck(I2C);
I2cSendByte(I2C, reg);
I2cWaitAck(I2C);
for(uint8_t i = 0; i<Size; i++)
{
I2cSendByte(I2C, *(data+i));
I2cWaitAck(I2C);
}
I2cStop(I2C);
return 0;
}
void Ina3221ReadData(IIC_TypeDef I2C ,u8 reg,u8 *data,u8 Size)
{
//设置3221的读取寄存器
I2cStart(I2C);
I2cSendByte(I2C, I2C.I2C_addr);
I2cWaitAck(I2C);
I2cSendByte(I2C, reg);
I2cWaitAck(I2C);
I2cStop(I2C);
I2cStart(I2C);
//读操作需要在地址值发送完后的一个位置1,写操作需要在地址值发送完后的一个位置0
I2cSendByte(I2C, I2C.I2C_addr+1);
I2cWaitAck(I2C);
uint8_t i;
for(i = 0; i<Size; i++)
{
*(data + i) = I2cReadByte(I2C, 1);
}
I2cStop(I2C);
}
u16 Ina3221GetReg(IIC_TypeDef I2C ,stcINA3221 INA3221,u8 Reg)
{
u16 temp=0;
I2C.I2C_addr = INA3221.DevAddr;
Ina3221ReadData(I2C,Reg,(u8 *)&temp,2);
return temp;
}
void Ina3221WriteReg(IIC_TypeDef I2C ,stcINA3221 INA3221,u8 Reg,u16 Data)
{
I2C.I2C_addr = INA3221.DevAddr;
Ina3221SendData(I2C ,Reg,(u8 *)&Data,2);
}
u16 Ina3221GetId(IIC_TypeDef I2C ,stcINA3221 INA3221)
{
u16 temp=0;
I2C.I2C_addr = INA3221.DevAddr;
Ina3221ReadData(I2C,INA3221_DIE_ID,(u8 *)&temp,2);
return temp;
}
void Ina3221Reset(IIC_TypeDef I2C ,stcINA3221 INA3221)
{
u16 temp=0x8000;
I2C.I2C_addr = INA3221.DevAddr;
Ina3221SendData(I2C ,CFG_REG,(u8 *)&temp,2);
}
void Ina3221_Init(IIC_TypeDef I2C)
{
u16 Ina3221_Id[4] = {0};
//初始化IO
I2C.Init_Cfg();
INA3221[I2C.index][0].DevAddr = INA3221_ADDR_40;
INA3221[I2C.index][1].DevAddr = INA3221_ADDR_41;
INA3221[I2C.index][2].DevAddr = INA3221_ADDR_42;
INA3221[I2C.index][3].DevAddr = INA3221_ADDR_43;
for(u8 i=0;i<4;i++)
{
Ina3221Reset(I2C ,INA3221[I2C.index][i]);
}
//读取ID信息测试IIC读写是否正常
printf("\r\n IIC%d读取的ID信息:",I2C.index);
for(u8 i=0;i<4;i++)
{
Ina3221_Id[i] = Ina3221GetId(I2C ,INA3221[I2C.index][i]);
printf("DevAddr:0x%02X Id:0x%04X",INA3221[I2C.index][i].DevAddr,Ina3221_Id[i]);
}
//软件复位
for(u8 i=0;i<4;i++)
{
INA3221[I2C.index][i].U_CFGREG.INA3221CfgReg = 0x00;
INA3221[I2C.index][i].U_CFGREG.Member.RST = 1;
I2C.I2C_addr = INA3221[I2C.index][i].DevAddr;
Ina3221WriteReg(I2C ,INA3221[I2C.index][i],CFG_REG,INA3221[I2C.index][i].U_CFGREG.INA3221CfgReg);
}
Delay_ms(10);
//初始化设置
for(u8 i=0;i<4;i++)
{
INA3221[I2C.index][i].U_CFGREG.INA3221CfgReg = 0x00;
/*
Channel enable mode.这些位允许每个独立通道使能或失能
0 = Channel disable1 = Channel enable (default)
*/
INA3221[I2C.index][0].U_CFGREG.Member.CH1_EN = 1;
INA3221[I2C.index][0].U_CFGREG.Member.CH2_EN = 1;
INA3221[I2C.index][0].U_CFGREG.Member.CH3_EN = 1;
/*
AVG[2:0] 设定采集的样本数量并一起取平均值。
000b=1 001b=4 010b=16 011b=64 100b=128 101b=256 110b=512 111b=1024
*/
INA3221[I2C.index][0].U_CFGREG.Member.AVG2 = 0;
INA3221[I2C.index][0].U_CFGREG.Member.AVG1 = 1;
INA3221[I2C.index][0].U_CFGREG.Member.AVG0 = 0;
/*
VbusCT 为总线电压测量设定转换时间。
000b=140us 001b=204us 010b=332us 011b=588us 100b=1.1ms 101b=2.116ms 110b=4.156ms 111b=8.244ms
*/
INA3221[I2C.index][0].U_CFGREG.Member.VBUS_CT2 = 0;
INA3221[I2C.index][0].U_CFGREG.Member.VBUS_CT1 = 1;
INA3221[I2C.index][0].U_CFGREG.Member.VBUS_CT0 = 1;
/*
cfg_VshCT 为总线电压测量设定转换时间。
000b=140us 001b=204us 010b=332us 011b=588us 100b=1.1ms 101b=2.116ms 110b=4.156ms 111b=8.244ms
*/
INA3221[I2C.index][0].U_CFGREG.Member.VSH_CT2 = 0;
INA3221[I2C.index][0].U_CFGREG.Member.VSH_CT1 = 1;
INA3221[I2C.index][0].U_CFGREG.Member.VSH_CT0 = 1;
/*
cfg_Mode value 选择连续的、 触发的、 或者省电运行模式。
0=省电 1=分流电压、触发模式 2=总线电压、触发模式 3=分流和总线电压、触发模式
4=省电 5=分流电压、持续模式 6=总线电压、持续模式 7=分流和总线电压、持续模式
*/
INA3221[I2C.index][0].U_CFGREG.Member.MODE3 = 1;
INA3221[I2C.index][0].U_CFGREG.Member.MODE2 = 1;
INA3221[I2C.index][0].U_CFGREG.Member.MODE1 = 1;
Ina3221WriteReg(I2C ,INA3221[I2C.index][i],CFG_REG,INA3221[I2C.index][i].U_CFGREG.INA3221CfgReg);
}
}
void Ina3221GetBusVal(IIC_TypeDef I2C,stcINA3221 INA3221)
{
INA3221.BusValue[0] = Ina3221GetReg(I2C ,INA3221,BV_REG_CHANNEL_1);
INA3221.BusValue[1] = Ina3221GetReg(I2C ,INA3221,BV_REG_CHANNEL_2);
INA3221.BusValue[2] = Ina3221GetReg(I2C ,INA3221,BV_REG_CHANNEL_3);
}
void Ina3221GetShuntVal(IIC_TypeDef I2C,stcINA3221 INA3221)
{
INA3221.shuntValue[0] = Ina3221GetReg(I2C ,INA3221,SV_REG_CHANNEL_1);
INA3221.shuntValue[1] = Ina3221GetReg(I2C ,INA3221,SV_REG_CHANNEL_2);
INA3221.shuntValue[2] = Ina3221GetReg(I2C ,INA3221,SV_REG_CHANNEL_3);
}
//转换算法
float Ina3221ShuntConversion( signed short dat )
{
u16 Temp;
float Temp1;
if( dat & 0x8000 )//负电压处理
{
dat = ~dat;//取反
dat += 1;//+1
}
Temp = dat;
Temp = Temp>>3;
Temp1 = Temp*40.0f;//得到uV电压(lsb=40uV)
Temp1 = (Temp1/0.3F);//0.3欧采样电阻得到uA电流
return ( (float)Temp1 );
}
u16 Ina3221BusConversion( signed short dat )
{
unsigned long tmp;
if( dat & 0x8000 )//负电压处理
{
dat = ~dat;//取反
dat += 1;//+1
}
tmp = dat;
tmp >>= 3;
tmp *= 8;//得到mV电压
return ( (u16)tmp );
}分析代码
最新发布