详细跳转借鉴链接INA219例程此处进行总结
简单介绍一下 INA219:
1、 输入脚电压可以从 0V~26V,INA219 采用 3.3V/5V 供电.
2、 能够检测电流,电压和功率,INA219 内置基准器和乘法器使之能够直接以 A 为单位
读出电流值。
3、 16 位可编程地址,有五个寄存器,有多种采样位数和采样方式供选择。
4、 INA219 能够感应电阻两端的最大电压范围为 VSHUNT= ±320mv.
5、 INA219 有两个地址引脚 A1A0 可以确定器件 I2C 地址(有 16 种)。
几个功能简单介绍
1、启动:可以上电启动或者通过 I2C 启动。
2、ADC 功能:
①可以对分流电阻两端的电压进行 ADC;
②可以对 Vin-进行 ADC;
③可以对采样位数,采样时间,采样方式进行设置。
3、PGA 功能:
①可以设置感应分流电压的范围(±40mv, ±80mv, ±160mv, ± 320mv);
②可以设置感应 bus 电压范围(16V 和 32V);
4、入滤波电路:在输入信号两端接 10R 电阻,两信号间接 0.1uF~1.0uF 这样可以滤除噪声,也有防静电功能(没有验证^),0R 电阻对ADC 精度没有影响。
5、简单电流检测 (不需要对配置寄存器设置): 上电默认 12 位 ADC,320mv 程32Vbus
电压,连续采样。这种检测电流是通过读电压来获取电流值。
计算部分
下图中的方程是功率寄存器的一般方程。数字设计师选择了5000倍,以获得INA219的良好范围。该因素反映了内部寄存器的数学计算
下面的公式显示了如何将总线电压寄存器转换为一个实际的模拟电压。它被代数地重新排列以供以后使用
下面的公式显示了如何将电流电压寄存器转换为一个实际的模拟电压。它被代数地重新排列以供以后使用。
下面的公式显示了如何将电流电压寄存器转换为一个实际的模拟电压。它被代数地重新排列以供以后使用。
将等式2、3、4替换为等式1。
简化
替换P = V*I
双方可取消的分母
代码部分
STM32标准库
#include "ina219.h"
void INA_REG_Write(unsigned char reg,unsigned int data);
#ifdef INA_INSIDE_IIC
void INA_IIC_Delay()
{unsigned char x;
for(x=1;x>0;x--)
{
__NOP();__NOP();__NOP();__NOP();__NOP();
}
}
void INA_IIC_INIT(void) //IIC初始化
{
GPIO_InitTypeDef GPIO_INIT;
RCC_APB2PeriphClockCmd(IIC_RCC,ENABLE);
GPIO_INIT.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_INIT.GPIO_Pin=IIC_SDA | IIC_SCL;
GPIO_INIT.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(IIC_PORT,&GPIO_INIT);
IIC_SDA_H;
IIC_SCL_H;
}
void INA_IIC_SDA_OUT(void) //SDA配置为输出
{
GPIO_InitTypeDef GPIO_INIT;
GPIO_INIT.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_INIT.GPIO_Pin=IIC_SDA ;
GPIO_INIT.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(IIC_PORT,&GPIO_INIT);
}
void INA_IIC_SDA_IN(void) //SDA配置为输入
{
GPIO_InitTypeDef GPIO_INIT;
GPIO_INIT.GPIO_Mode=GPIO_Mode_IPU;
GPIO_INIT.GPIO_Pin=IIC_SDA ;
GPIO_INIT.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(IIC_PORT,&GPIO_INIT);
}
void INA_IIC_Start(void) //开始信号
{
IIC_SDA_H;
IIC_SCL_H;
INA_IIC_Delay();
IIC_SDA_L;
INA_IIC_Delay();
IIC_SDA_L;
}
void INA_IIC_Stop(void ) //结束信号
{
IIC_SDA_L;
IIC_SCL_H;
INA_IIC_Delay();
IIC_SDA_H;
INA_IIC_Delay();
IIC_SCL_L;
IIC_SCL_H;
IIC_SDA_H;
}
bool INA_IIC_ACK_Read(void) //读取应答信号
{
bool ack;
IIC_SDA_H;
INA_IIC_SDA_IN();
IIC_SCL_H;
INA_IIC_Delay();
if(IIC_SDA_READ() == SET) ack=false;
else ack=true;
IIC_SCL_L;
INA_IIC_SDA_OUT();
return ack;
}
void INA_IIC_ACK_Send(bool ack) //发送应答信号
{
IIC_SCL_L;
if(ack == true)
IIC_SDA_L;
else IIC_SDA_H;
IIC_SCL_H;
INA_IIC_Delay();
IIC_SCL_L;
}
void INA_IIC_Send_Byte(unsigned char byte) //IIC发送一位数据
{
unsigned char i;
IIC_SCL_L;
for(i=0;i<8;i++)
{
if(byte & 0x80 ) IIC_SDA_H;
else IIC_SDA_L;
IIC_SCL_H;
INA_IIC_Delay();
IIC_SCL_L;
INA_IIC_Delay();
byte<<=1;
}
INA_IIC_ACK_Read();
}
unsigned char INA_IIC_Read_Byte(void) //IIC读取一位数据
{
unsigned char i,byte=0;
INA_IIC_SDA_IN();
for(i=0;i<8;i++)
{
IIC_SCL_H;
byte<<=1;
if(IIC_SDA_READ() == SET) byte |= 0x01;
else byte &= 0xFE;
IIC_SCL_L;
INA_IIC_Delay();
}
INA_IIC_SDA_OUT();
return byte;
}
#endif
void INA_Read_Byte_s(unsigned char reg,unsigned char *data) //读两位数据
{
INA_IIC_Start();
INA_IIC_Send_Byte(INA219_ADDRESS); //发送INA219地址s
INA_IIC_Send_Byte(reg);
INA_IIC_Start();
INA_IIC_Send_Byte(INA219_ADDRESS+0x01); //设置iic为读模式
*data=INA_IIC_Read_Byte();
data++;
INA_IIC_ACK_Send(1);
*data=INA_IIC_Read_Byte();
INA_IIC_ACK_Send(0);
INA_IIC_Stop();
}
void INA_REG_Write(unsigned char reg,unsigned int data) //写寄存器 测试成功
{
unsigned char data_temp[2];
data_temp[0]=(unsigned char )(data>>8);
data_temp[1]=(unsigned char )(data & 0xFF);
INA_IIC_Start();
INA_IIC_Send_Byte(INA219_ADDRESS); //发送INA219地址
INA_IIC_Send_Byte(reg); //发送寄存器地址
INA_IIC_Send_Byte(data_temp[0]); //发送高8位数据
data++;
INA_IIC_Send_Byte(data_temp[1]) ; //发送低8位数据
INA_IIC_Stop();
}
void INA_Init(void )
{
INA_IIC_INIT();
INA_REG_Write(INA219_REG_CONFIG,INA219_CONFIG_value);
INA_REG_Write(INA219_REG_CALIBRATION,INA_CAL);
}
unsigned int INA_GET_Voltage_MV(void) //获取电压(单位:mv)
{
unsigned char data_temp[2];
INA_Read_Byte_s(0x02,data_temp);
return (int)((((data_temp[0]<<8)+data_temp[1]) >> 3)*4); //右移3为去掉:bit2,CNVR,OVF三位,再乘以 4MV (官方文档规定),得到当前总线的电压值
}
unsigned int INA_GET_Current_MA(void) //获取电流(单位:mA)
{
unsigned char data_temp[2];
INA_REG_Write(INA219_REG_CONFIG,INA219_CONFIG_value);
INA_Read_Byte_s(INA219_REG_CURRENT,data_temp);
return (int)((((data_temp[0]<<8)+data_temp[1]))*IAN_I_LSB); //得到寄存器的值在乘以每位对应的值(IAN_I_LSB)得到实际的电流
}
unsigned int INA_GET_Power_MW(void) //获取当前功率(单位:mw)
{
unsigned char data_temp[2];
INA_Read_Byte_s(INA219_REG_POWER,data_temp);
return (int)(((data_temp[0]<<8)+data_temp[1])*INA_Power_LSB); //得到寄存器的值在乘以每位对应的值(INA_Power_LSB)得到实际的功率
}
主函数部分
#include "sys.h"
#include "lcd.h"
#include "usart.h"
#include "usmart.h"
#include "24cxx.h"
#include "ina219.h"
#include "stdio.h"
#define SIZE sizeof(TEXT_Buffer)
//要写入到24c02的字符串数组
const u8 TEXT_Buffer[]={"Elite STM32 IIC TEST"};
unsigned int voltage_mv,Current_ma,Power_mw,R_mv;
float voltage_mv_float,
Current_ma_float,
Power_mw_float,
R_mv_float;
int main(void)
{
u8 key;
u16 i=0,mv=0;
u8 datatemp[SIZE];
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LED_Init(); //初始化与LED连接的硬件接口
INA_Init();
while(1)
{
delay_ms(100);
voltage_mv=INA_GET_Voltage_MV(); //得到电压(mV)
voltage_mv_float=(float)voltage_mv/1000; //转换为浮点型电压(V)
Current_ma=INA_GET_Current_MA(); //得到电流(mA)
Current_ma_float=(float)Current_ma; 得到浮点型电流(V)
Power_mw=INA_GET_Power_MW();//得到功率(mW)
Power_mw_float=(float)Power_mw;//得到浮点型功率(mW)
printf("电压:%f\n",0.9963*(voltage_mv_float)+0.3047);
printf("电流:%f\n",Current_ma_float);
printf("功率:%f\n",Power_mw_float);
i++;
delay_ms(10);
if(i==10)
{
LED2=!LED2;//提示系统正在运行
i=0;
}
}
}