【GD32】INA226电压电流功率检测模块

2.46 INA226电压电流功率检测模块

2.46.1 模块来源​

采购链接:​
INA226电压电流功率检测模块
资料下载:(基于该模块的资料,百度云链接等)​
链接:http://pan.baidu.com/s/1c0DbuXa 密码:3p2j​

​ 2.46.2 规格参数

工作电压:2.7 V -5.5 V
工作电流:典型值为 330μA
通信方式:I2C (时钟速率1k-2.94M)
引脚数量:10
(还有其他关于该模块的一些重要参数,例如温度传感器需要知道温度的检测范围,屏幕需要知道像素等等。)
1.感测的总线电压范围:
0V 至 36V (高侧或低侧感测)
2.高精度:
0.1% 增益误差(最大值)
10μV 偏移(最大值)
3.可配置的取平均值选项
4.16 个可编程地址

2.46.3 模块原理

INA226是一种高精度、低功耗的电流/电压监测芯片,它采用集成电流传感器和差分放大器电路,用于测量和监控电流和电压。INA226的工作原理如下:

  1. 电流测量:INA226内置了一个电流传感器,该传感器是基于霍尔效应或电阻的。当电流通过芯片的输入引脚时,传感器将产生一个与电流成正比的电压信号。
  2. 电压测量:INA226可以通过测量两个端口之间的电压差来实现电压测量。它采用差分放大器电路,将输入端口的电压与内部参考电压进行比较,并产生一个与输入电压差值成正比的电压信号。
  3. AD转换:INA226将电流和电压信号转换为数字信号。它包含一个内置的模数转换器(ADC),用于将模拟信号转换为数字形式。ADC将连续的模拟信号分割成离散的数字级别,并输出对应的数字值。
  4. 数据处理:转换后的数字信号被送入INA226的数字信号处理部分。在这里,它们经过放大、滤波和校准等处理,以产生准确的电流和电压测量结果。
  5. 数据输出:INA226通过接口(I2C)将测量结果输出给主控制器或其他外部设备。主控制器可以读取和解释这些测量结果,从而实现对电流和电压的监控和控制。
    总之,INA226通过集成电流传感器和差分放大器电路,以及内部的模数转换器和数字信号处理部分,实现对电流和电压的高精度测量和监控。

在这里插入图片描述

2.46.4 移植工程

讲解移植到立创梁山派的大致步骤,并基于该模块移植的代码实现什么功能。

2.46.4-1 引脚选择

如果是特殊引脚,例如使用串口时,需要讲解为什么使用该引脚,这个引脚是串口几等等。
接线按照以下模板进行编写。
在这里插入图片描述

2.46.4-2 移植步骤

将厂家提供的代码移植到立创·梁山派的步骤,图文并茂。如果没有厂家代码,请将实现功能的代码粘贴至此目录下,并进行关键代码注释。

   在本次INA226模块的测试中,使用的是贴片采样电阻R100,阻值为0.1欧姆。根据数据手册中的公式1和公式2进行计算。

在这里插入图片描述

首先,需要注意Shunt Voltage Register的值最大为0x7FFF,每个LSB对应2.5微伏,全量程范围为81.92毫伏。
由于分流电阻的阻值为0.1欧姆,因此最大电流为819.2毫安(注意避免超过此范围,以免导致错误测量结果)。
在假设Current_LSB为0.02毫安的情况下,满足最大电流不能超过819.2毫安的条件。根据公式1计算得到,Calibration Register的值为0x0A00。
因此,在配置INA226时,应将0x0A00写入Calibration Register中。
请确保在实际应用中选择适合您的应用的电流范围和分辨率,并避免超出设备的量程,以确保测量结果的准确性。

1.使用GPIO实现模拟I2C时序。
GPIO实现模拟I2C时序是一种在硬件资源有限的情况下的替代方法。虽然它具有灵活性和低硬件要求的优点,但也存在时序精度受限、速度较慢和资源占用较大等缺点。因此,在选择使用GPIO进行模拟I2C时序之前,需要权衡其优缺点,并根据具体应用的要求做出选择。
本代码封装了 I2C设备读写数据函数,方便其他I2C模块调用。

代码1  GPIO实现模拟I2C时序代码
/********************************************************************************
  * 测试硬件:立创·梁山派开发板GD32F470ZGT6    使用主频200Mhz    晶振25Mhz
  * 版 本 号: V1.0
  * 修改作者: LC
  * 修改日期: 2023年06月12日
  * 功能介绍:
  ******************************************************************************
  
*********************************************************************************/
#include <stdio.h>
#include "main.h"
#include "driver_i2c.h"
#include "systick.h"
// I2C引脚定义
#define SCL_PIN GPIO_SCL  // SCL引脚
#define SDA_PIN GPIO_SDA  // SDA引脚
#define I2C_PORT PORT_SDA
/******************************************************************
 * 函 数 名 称:I2C_GPIO_Init
 * 函 数 说 明:I2C的引脚初始化
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void i2c_gpio_init(void)
{
  /* 使能时钟 */
  rcu_periph_clock_enable(RCU_SCL);
  rcu_periph_clock_enable(RCU_SDA);

  /* 配置SCL为输出模式 */
  gpio_mode_set(PORT_SCL, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_SCL);
  /* 配置为推挽输出 50MHZ */
  gpio_output_options_set(PORT_SCL, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_SCL);

  /* 配置SDA为输出模式 */
  gpio_mode_set(PORT_SDA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_SDA);
  /* 配置为推挽输出 50MHZ */
  gpio_output_options_set(PORT_SDA, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_SDA);

  gpio_bit_set(I2C_PORT, SDA_PIN);
  gpio_bit_set(I2C_PORT, SCL_PIN);

}



/*********************************************************
* 函数名称:i2c_delay
 * 函 数 说 明:I2C总线延时函数
* 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
*********************************************************/
void i2c_delay()
{
  uint32_t delay = 200;

  while (delay--)
  {
    __NOP();
  }
}
/*********************************************************

 * 函 数 名 称:i2c_start
 * 函 数 说 明:产生I2C起始信号
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
*********************************************************/
static void i2c_start()
{
  gpio_bit_set(I2C_PORT, SDA_PIN); // 确保数据线为高电平
  gpio_bit_set(I2C_PORT, SCL_PIN); // 确保时钟线为高电平
  i2c_delay();
  gpio_bit_reset(I2C_PORT, SDA_PIN); // 拉低数据线,产生起始信号
  i2c_delay();
  gpio_bit_reset(I2C_PORT, SCL_PIN); // 拉低时钟线,准备发送数据
  i2c_delay();
}
/*********************************************************
 * 函 数 名 称:i2c_stop
 * 函 数 说 明:产生I2C停止信号
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
*********************************************************/
static void i2c_stop()
{
  gpio_bit_reset(I2C_PORT, SDA_PIN); // 确保数据线为低电平
  gpio_bit_set(I2C_PORT, SCL_PIN); // 确保时钟线为高电平
  i2c_delay();
  gpio_bit_set(I2C_PORT, SDA_PIN); // 拉高数据线,产生停止信号
  i2c_delay();
}
/*********************************************************
 * 函 数 名 称:i2c_write_byte
 * 函 数 说 明:向I2C总线写入一个字节,并读取ACK信号
 * 函 数 形 参:data - 要写入的数据字节
 * 函 数 返 回:uint8_t - ACK信号,0表示收到ACK,1表示收到NACK
 * 作       者:LC
 * 备       注:无
*********************************************************/
static uint8_t i2c_write_byte(uint8_t data)
{
  uint8_t i, ack;

  for (i = 0; i < 8; i++)
  {
    if (data & 0x80) // 检查数据的最高位
    {
      gpio_bit_set(I2C_PORT, SDA_PIN); // 将数据线拉高,写入1
    }
    else
    {
      gpio_bit_reset(I2C_PORT, SDA_PIN); // 将数据线拉低,写入0
    }

    gpio_bit_set(I2C_PORT, SCL_PIN);  // 拉高时钟线,发送数据位
    i2c_delay();
    gpio_bit_reset(I2C_PORT, SCL_PIN);  // 拉低时钟线,准备发送下一位数据
    i2c_delay();
    data <<= 1;  // 左移一位,准备发送下一位数据
  }

  gpio_bit_set(I2C_PORT, SDA_PIN); // 拉高数据线,准备接收ACK信号
  gpio_bit_set(I2C_PORT, SCL_PIN); // 拉高时钟线
  i2c_delay();
  ack = gpio_input_bit_get(I2C_PORT, SDA_PIN); // 读取ACK信号
  gpio_bit_reset(I2C_PORT, SCL_PIN); // 拉低时钟线
  i2c_delay();
  return ack;
}


/*********************************************************
 * 函 数 名 称:i2c_read_byte
 * 函 数 说 明:从I2C总线读取一个字节,并发送ACK或NACK信号
 * 函 数 形 参:ack - ACK信号,0表示发送ACK,1表示发送NACK
 * 函 数 返 回:uint8_t - 读取到的数据字节
 * 作       者:LC
 * 备       注:无
*********************************************************/
static uint8_t i2c_read_byte(uint8_t ack)
{
  uint8_t i, data = 0;
  gpio_bit_set(I2C_PORT, SDA_PIN); // 确保数据线为高电平

  for (i = 0; i < 8; i++)
  {
    data <<= 1; // 左移一位,准备接收数据位
    gpio_bit_set(I2C_PORT, SCL_PIN); // 拉高时钟线,准备接收数据
    i2c_delay();


    if (gpio_input_bit_get(I2C_PORT, SDA_PIN))  // 检查数据线的状态
    {
      data |= 0x01;  // 如果数据线为高电平,将最低位设置为1
    }

    gpio_bit_reset(I2C_PORT, SCL_PIN);  // 拉低时钟线,准备接收下一位数据
    i2c_delay();
  }

  if (ack)
  {
    gpio_bit_reset(I2C_PORT, SDA_PIN); // 拉低数据线,发送NACK信号
  }
  else
  {
    gpio_bit_set(I2C_PORT, SDA_PIN); // 拉高数据线,发送ACK信号
  }

  gpio_bit_set(I2C_PORT, SCL_PIN); // 拉高时钟线,准备发送ACK或NACK信号
  i2c_delay();
  gpio_bit_reset(I2C_PORT, SCL_PIN); // 拉低时钟线
  i2c_delay();
  return data; // 返回读取到的数据字节
}


/*********************************************************
 * 函 数 名 称:i2c_write_data
 * 函 数 说 明:向I2C设备写入数据
 * 函 数 形 参:dev_addr - 设备地址
  reg_addr - 寄存器地址
  data - 要写入的数据数组指针
  len - 数据长度
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
*********************************************************/
void i2c_write_data(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len)
{
  i2c_start();
  i2c_write_byte((dev_addr << 1) & 0xFE);  // 写入设备地址
  i2c_write_byte(reg_addr);                // 写入寄存器地址

  for (uint8_t i = 0; i < len; i++)
  {
    i2c_write_byte(data[i]);              // 写入数据
  }

  i2c_stop();
}

/*********************************************************
 * 函 数 名 称:i2c_read_data
 * 函 数 说 明:从I2C设备读取数据
 * 函 数 形 参:dev_addr - 设备地址
  reg_addr - 寄存器地址
  data - 存储读取数据的数组指针
  len - 数据长度
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
*********************************************************/
void i2c_read_data(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len)
{
  i2c_start();
  i2c_write_byte((dev_addr << 1) & 0xFE);  // 写入设备地址
  i2c_write_byte(reg_addr);                // 写入寄存器地址
  i2c_start();
  i2c_write_byte((dev_addr << 1) | 0x01);  // 写入设备地址,读模式

  for (uint8_t i = 0; i < len; i++)
  {
    if (i == len - 1)
    {
      data[i] = i2c_read_byte(0);       // 读取最后一个字节,发送NACK
    }
    else
    {
      data[i] = i2c_read_byte(1);       // 读取字节,发送ACK
    }
  }

  i2c_stop();
}

2.INA226驱动主要包括以下功能
1.配置INA226:使用I2C接口发送配置命令和参数给INA226芯片。这些参数包括采样时间、测量范围等。
2.读取电压电流等数据:使用I2C接口从INA226芯片读取电流、电压和功率等数据。可以根据需要设置不同的读取频率和精度。
3.处理数据:根据实际的电路和采样电阻,需要选择合适的计算公式对从INA226读取的数据进行处理。可以使用公式和系数将原始数据转换为实际物理量。

代码2 INA226初始化、获取电压、电流、功率代码


/********************************************************************************
 * 测试硬件:立创·梁山派开发板GD32F470ZGT6    使用主频200Mhz    晶振25Mhz
 * 版 本 号: V1.0
 * 修改作者: LC
 * 修改日期: 2023年06月12日
 * 功能介绍:
 ******************************************************************************

*********************************************************************************/

#include "bsp_ina226.h"
#include "driver_i2c.h"

/************************************************
 * 函 数 名 称:ina226_init
 * 函 数 说 明:INA226初始化配置
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
*************************************************/
void ina226_init()
{
  uint8_t config_data[2] = {0x80, 0x00}; 

  i2c_write_data(INA226Addr, 0x00, config_data, 2);  // 
  config_data[0] = 0x45;
  config_data[1] = 0x27;
  i2c_write_data(INA226Addr, 0x00, config_data, 2);  // 
  config_data[0] = 0x0A;
  config_data[1] = 0x00;
  i2c_write_data(INA226Addr, 0x05, config_data, 2);  // 
}

/************************************************
 * 函 数 名 称:ina226_get_voltage
 * 函 数 说 明:获取电压值
 * 函 数 形 参:无
 * 函 数 返 回:电压值(浮点数)
 * 作       者:LC
 * 备       注:无
*************************************************/
float ina226_get_voltage()
{
  uint8_t voltage_data[2];
  i2c_read_data(INA226Addr, 0x02, voltage_data, 2);  // 

  uint16_t data = (voltage_data[0] << 8) | voltage_data[1];
  float voltage = (float)data * 1.25 ; 
  return voltage;
}

/************************************************
 * 函 数 名 称:ina226_get_current
 * 函 数 说 明:获取电流值
 * 函 数 形 参:无
 * 函 数 返 回:电流值(浮点数)
 * 作       者:LC
 * 备       注:无
*************************************************/
float ina226_get_current()
{
  uint8_t current_data[2];
  i2c_read_data(INA226Addr, 0x04, current_data, 2);  // 
  int16_t data = (current_data[0] << 8) | current_data[1];
  float current = data * 0.02; 
  return current;
}

/************************************************
 * 函 数 名 称:ina226_get_power
 * 函 数 说 明:获取功率值
 * 函 数 形 参:无
 * 函 数 返 回:功率值(浮点数)
 * 作       者:LC
 * 备       注:无
*************************************************/
float ina226_get_power()
{
  uint8_t power_data[2];
  i2c_read_data(INA226Addr, 0x03, power_data, 2);  // 
  uint16_t data = (power_data[0] << 8) | power_data[1];
  float power = (float)data *  0.02 * 25; 
  return power;
}

2.46.5 移植验证

讲解代码移植成功后的现象,贴上完成该模块相关功能的图片或者视频。将代码上传飞书分享。
示例:
案例现象:
使用了120欧姆水泥电阻作为负载,并使用了万用表和INA226来分别测量电压数据。在正确连接电路之后,打开串口助手连接到立创·梁山派的串口,获取了电压、电流和功率数据。整个过程的现象如图所示。
正确连接电路后连接成功之后,立创·梁山派的串口向串口助手发送电压电流功率数据,现象如图所示。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

成功示例文件

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-15 05:16:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-15 05:16:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-15 05:16:03       82 阅读
  4. Python语言-面向对象

    2024-04-15 05:16:03       91 阅读

热门阅读

  1. 方法引用(详)

    2024-04-15 05:16:03       32 阅读
  2. 【华为OD机试C++】图片整理

    2024-04-15 05:16:03       44 阅读
  3. 4-安装并配置Grafana并导入特定的仪表板模板

    2024-04-15 05:16:03       44 阅读
  4. 未来的前端框架技术发展趋势

    2024-04-15 05:16:03       45 阅读
  5. 获取主页数据并显示流程笔记

    2024-04-15 05:16:03       142 阅读
  6. 基于单片机的智能照明控制系统设计与实现

    2024-04-15 05:16:03       33 阅读
  7. 如何在CentOS中开放指定端口

    2024-04-15 05:16:03       44 阅读
  8. Unity Android Release-Notes

    2024-04-15 05:16:03       107 阅读
  9. 课时94:脚本自动化_脚本信号_信号基础

    2024-04-15 05:16:03       39 阅读
  10. C#`DataGridView`控件显示多余的空行

    2024-04-15 05:16:03       37 阅读
  11. Python程序设计 上下文管理器

    2024-04-15 05:16:03       36 阅读