Skip to content

IIC 控制INA226 实现电压电流功率的监测

alt text

本文有前置代码,需要先参考 SPI 0.96LCD 7735s.先编写好相关的屏幕驱动代码,再添加相关IIC 驱动INA226 的代码

alt text

INA226的大概示意图 alt text

下面是INA226的寄存器 alt text INA226初始化需要两步

  1. 初始化ADC参数(0x00),采样时间,采样次数等
  2. 初始化校准电阻(0x05)。芯片需要配置一个电流校准寄存器,匹配芯片内部的电阻和外部采样电阻。计算公式如下图。 alt text

例1:
需求:6A的测量范围,采样电阻10mR

current_lsb = (6)/32768 =0.0001831
CAL = 0.00512/( 0.0001831 * 0.01) = 2,796.286
2,796.286 约等于 2796
2796 转换成hex 0xAEC,此时 地址为0x05 的Calibration Register寄存器写入值 0xAEC即可。

例2:
需求:每个lsb 为0.2mA,采样电阻 10mR

cal = 0.00512/( 0.0002 * 0.01) = 2560
2560 转换成hex 0xA00,此时 地址为0x05 的Calibration Register寄存器写入值 0xA00即可。

1. 硬件连接

INA226 只需外部接一个电阻到测量线路上就好,IIC接口去通信。

alt text

2. CubeMX生成代码

代码复用之前7735s的代码。初始化一下IIC, alt text

3. 编写代码 INA226

INA226 读写代码

读取和写INA226的代码,就是将库中的IIC函数重新封装一下。

c
static int32_t INA226_RD_Reg(I2C_HandleTypeDef *hi2c,uint8_t deviceAddress,uint8_t addr)
{
   uint8_t temp[2];
   HAL_I2C_Mem_Read(hi2c, deviceAddress, addr, I2C_MEMADD_SIZE_8BIT, temp, 2, 0xFF);
   
    return temp[1] + temp[0] * 256;
}
 
static void INA226_WR_Reg(I2C_HandleTypeDef *hi2c,uint8_t deviceAddress,uint8_t addr, uint16_t value )
{
   uint8_t temp[2];
   temp[0] = value >> 8;
   temp[1] = value & 0xFF;
   HAL_I2C_Mem_Write(hi2c, deviceAddress, addr, I2C_MEMADD_SIZE_8BIT,  temp, 2, 0x100);
}

INA226 初始化寄存器代码

初始化INA226 ,主要就是初始化地址为0x01地址的参数,和0x05地址的校准寄存器
需要注意228和226的寄存器地址不同,所以需要控制不同的寄存器

c
 void INA226_init()
{
     //0100_010_100_100_111 //16次平均,1.1ms,1.1ms,连续测量分流电压和总线电压
    INA226_WR_Reg(&hi2c1,0x80,0x00,0x4527); //ADC_CONFIG 寄存器初始化 
    INA226_WR_Reg(&hi2c1,0x80,0x05,0xA00);//SHUNT_CAL 寄存器,初始化电流的分流电阻
    
}

main.c函数中的while函数
需要注意228和226的寄存器地址不同,所以需要控制不同的寄存器

c


    INA226_init();
    float t=0;
    int32_t input = 0;
  while (1)
  {
      
     //总线电压测量
    input = (int)INA226_RD_Reg(&hi2c1,0x80 ,0x02);
    t = input * 1.25 /1000;//V
    LCD_ShowChinese(0,40,"电压",RED,WHITE,32,0);
    LCD_ShowFloatNum1(70,45,t,5,RED,WHITE,24);
    LCD_ShowString(143,45,"V",RED,WHITE,24,0);
     
     //电流结果
     input = (int)INA226_RD_Reg(&hi2c1,0x80 ,0x04);
     t = input * 0.0002;//A
    LCD_ShowChinese(0,0,"电流",RED,WHITE,32,0);
    LCD_ShowFloatNum1(70,5,t,5,RED,WHITE,24);
    LCD_ShowString(143,5,"A",RED,WHITE,24,0);

    HAL_Delay(1000);
  }

4 编写代码INA228

INA228 是20 位ADC,所以在通信的时候会有一些位数上的差异

读取和写INA228的代码,就是将库中的IIC函数重新封装一下。

c
static int32_t INA228_RD_Reg(I2C_HandleTypeDef *hi2c,uint8_t deviceAddress,uint8_t addr)
{
   uint8_t temp[3];
   HAL_I2C_Mem_Read(hi2c, deviceAddress, addr, I2C_MEMADD_SIZE_8BIT, temp, 3, 0xFF);
   
   return temp[2]+temp[1]*256 + temp[0] * 65536;
}
 
static void INA228_WR_Reg(I2C_HandleTypeDef *hi2c,uint8_t deviceAddress,uint8_t addr, uint16_t value )
{
   uint8_t temp[2];
   temp[0] = value >> 8;
   temp[1] = value & 0xFF;
   HAL_I2C_Mem_Write(hi2c, deviceAddress, addr, I2C_MEMADD_SIZE_8BIT,  temp, 2, 0x100);
}

INA228 初始化寄存器代码

初始化INA228 ,主要就是初始化地址为0x01地址的参数,和0x05地址的校准寄存器

需要注意228和226的寄存器地址不同,所以需要控制不同的寄存器

c
 void INA228_init()
{
    INA228_WR_Reg(&hi2c1,0x80,0x01,0xFB6F); //ADC_CONFIG 寄存器初始化 
    INA228_WR_Reg(&hi2c1,0x80,0x02,0xFA0);//SHUNT_CAL 寄存器,初始化电流的分流电阻
}

main.c函数中的while函数

需要注意228和226的寄存器地址不同,所以需要控制不同的寄存器

c


  INA228_init();
  float t=0;
  int32_t input = 0;
  while (1)
  {
      
     //总线电压测量
    input = (int)INA228_RD_Reg(&hi2c1,0x80 ,0x05);
    t = input * 1.25 /1000;//V
    LCD_ShowChinese(0,40,"电压",RED,WHITE,32,0);
    LCD_ShowFloatNum1(70,45,t,5,RED,WHITE,24);
    LCD_ShowString(143,45,"V",RED,WHITE,24,0);
     
     //电流结果
     input = (int)INA228_RD_Reg(&hi2c1,0x80 ,0x07);
     t = input * 0.5057 -5;//uA
    LCD_ShowChinese(0,0,"电流",RED,WHITE,32,0);
    LCD_ShowFloatNum1(70,5,t,5,RED,WHITE,24);
    LCD_ShowString(143,5,"A",RED,WHITE,24,0);

    HAL_Delay(1000);
  }

总结

代码参考:https://blog.csdn.net/weixin_56719449/article/details/149055858