INA226电压电流测量模块详细笔记(硬件连接+原理介绍+代码实现 附完整资料)

初学笔记,有错的地方感谢指出。反正我最后是实现了测量电压电流和功率,准确度还不错,可能某些地方理解有误,但最终确实是实现了测量。

硬件部分:这里展示了4种连接方法,大同小异。每个电路都可以测出U1和I1。芯片内部VIN和VOUT之间接了一个10mΩ的电阻,模块电路已给出。

9d3ad3a7469046eabfa77db949203a15.jpeg2c463a13bc814253bb15de76cdc703f5.jpegc5fbf75c07c04b1ea8752e1c99e6dd18.jpegaea996a1806d471aaf29e0c33414e3e7.jpeg

622c8c7d23ff4a7d8fce776afc97dd8e.png

软件部分:

1.学习完江科大软件IIC,开始看INA226规格书 中文版INA226规格书(注意:这是INA226芯片的规格书,不是模块的规格书,规格书里的那个Rshunt电阻就是模块里的10mR)

2.自己编写软件IIC代码,我是跟着江科大敲了几遍,江科大MyI2C.h和MyI2C.c代码如下(Delay.c代码在后面给出):注意SCL SDA的IO口设置。

MyI2C.h和MyI2C.c:

#ifndef __MYI2C_H
#define __MYI2C_H

void MyI2C_Init(void);
void MyI2C_Start(void);
void MyI2C_Stop(void);
void MyI2C_SendByte(uint8_t Byte);
uint8_t MyI2C_ReceiveByte(void);
void MyI2C_SendAck(uint8_t AckBit);
uint8_t MyI2C_ReceiveAck(void);

#endif
#include "stm32f10x.h"                  // Device header
#include "Delay.h"

/*引脚配置层*/

/**
  * 函    数:I2C写SCL引脚电平
  * 参    数:BitValue 协议层传入的当前需要写入SCL的电平,范围0~1
  * 返 回 值:无
  * 注意事项:此函数需要用户实现内容,当BitValue为0时,需要置SCL为低电平,当BitValue为1时,需要置SCL为高电平
  */
void MyI2C_W_SCL(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);		//根据BitValue,设置SCL引脚的电平
	Delay_us(10);												//延时10us,防止时序频率超过要求
}

/**
  * 函    数:I2C写SDA引脚电平
  * 参    数:BitValue 协议层传入的当前需要写入SDA的电平,范围0~0xFF
  * 返 回 值:无
  * 注意事项:此函数需要用户实现内容,当BitValue为0时,需要置SDA为低电平,当BitValue非0时,需要置SDA为高电平
  */
void MyI2C_W_SDA(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)BitValue);		//根据BitValue,设置SDA引脚的电平,BitValue要实现非0即1的特性
	Delay_us(10);												//延时10us,防止时序频率超过要求
}

/**
  * 函    数:I2C读SDA引脚电平
  * 参    数:无
  * 返 回 值:协议层需要得到的当前SDA的电平,范围0~1
  * 注意事项:此函数需要用户实现内容,当前SDA为低电平时,返回0,当前SDA为高电平时,返回1
  */
uint8_t MyI2C_R_SDA(void)
{
	uint8_t BitValue;
	BitValue = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5);		//读取SDA电平
	Delay_us(10);												//延时10us,防止时序频率超过要求
	return BitValue;											//返回SDA电平
}

/**
  * 函    数:I2C初始化
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数需要用户实现内容,实现SCL和SDA引脚的初始化
  */
void MyI2C_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOB的时钟
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					//将PB10和PB11引脚初始化为开漏输出
	
	/*设置默认电平*/
	GPIO_SetBits(GPIOA, GPIO_Pin_4 | GPIO_Pin_5);			//设置PB10和PB11引脚初始化后默认为高电平(释放总线状态)
}

/*协议层*/

/**
  * 函    数:I2C起始
  * 参    数:无
  * 返 回 值:无
  */
void MyI2C_Start(void)
{
	MyI2C_W_SDA(1);							//释放SDA,确保SDA为高电平
	MyI2C_W_SCL(1);							//释放SCL,确保SCL为高电平
	MyI2C_W_SDA(0);							//在SCL高电平期间,拉低SDA,产生起始信号
	MyI2C_W_SCL(0);							//起始后把SCL也拉低,即为了占用总线,也为了方便总线时序的拼接
}

/**
  * 函    数:I2C终止
  * 参    数:无
  * 返 回 值:无
  */
void MyI2C_Stop(void)
{
	MyI2C_W_SDA(0);							//拉低SDA,确保SDA为低电平
	MyI2C_W_SCL(1);							//释放SCL,使SCL呈现高电平
	MyI2C_W_SDA(1);							//在SCL高电平期间,释放SDA,产生终止信号
}

/**
  * 函    数:I2C发送一个字节
  * 参    数:Byte 要发送的一个字节数据,范围:0x00~0xFF
  * 返 回 值:无
  */
void MyI2C_SendByte(uint8_t Byte)
{
	uint8_t i;
	for (i = 0; i < 8; i ++)				//循环8次,主机依次发送数据的每一位
	{
		MyI2C_W_SDA(Byte & (0x80 >> i));	//使用掩码的方式取出Byte的指定一位数据并写入到SDA线
		MyI2C_W_SCL(1);						//释放SCL,从机在SCL高电平期间读取SDA
		MyI2C_W_SCL(0);						//拉低SCL,主机开始发送下一位数据
	}
}

/**
  * 函    数:I2C接收一个字节
  * 参    数:无
  * 返 回 值:接收到的一个字节数据,范围:0x00~0xFF
  */
uint8_t MyI2C_ReceiveByte(void)
{
	uint8_t i, Byte = 0x00;					//定义接收的数据,并赋初值0x00,此处必须赋初值0x00,后面会用到
	MyI2C_W_SDA(1);							//接收前,主机先确保释放SDA,避免干扰从机的数据发送
	for (i = 0; i < 8; i ++)				//循环8次,主机依次接收数据的每一位
	{
		MyI2C_W_SCL(1);						//释放SCL,主机机在SCL高电平期间读取SDA
		if (MyI2C_R_SDA() == 1){Byte |= (0x80 >> i);}	//读取SDA数据,并存储到Byte变量
														//当SDA为1时,置变量指定位为1,当SDA为0时,不做处理,指定位为默认的初值0
		MyI2C_W_SCL(0);						//拉低SCL,从机在SCL低电平期间写入SDA
	}
	return Byte;							//返回接收到的一个字节数据
}

/**
  * 函    数:I2C发送应答位
  * 参    数:Byte 要发送的应答位,范围:0~1,0表示应答,1表示非应答
  * 返 回 值:无
  */
void MyI2C_SendAck(uint8_t AckBit)
{
	MyI2C_W_SDA(AckBit);					//主机把应答位数据放到SDA线
	MyI2C_W_SCL(1);							//释放SCL,从机在SCL高电平期间,读取应答位
	MyI2C_W_SCL(0);							//拉低SCL,开始下一个时序模块
}

/**
  * 函    数:I2C接收应答位
  * 参    数:无
  * 返 回 值:接收到的应答位,范围:0~1,0表示应答,1表示非应答
  */
uint8_t MyI2C_ReceiveAck(void)
{
	uint8_t AckBit;							//定义应答位变量
	MyI2C_W_SDA(1);							//接收前,主机先确保释放SDA,避免干扰从机的数据发送
	MyI2C_W_SCL(1);							//释放SCL,主机机在SCL高电平期间读取SDA
	AckBit = MyI2C_R_SDA();					//将应答位存储到变量里
	MyI2C_W_SCL(0);							//拉低SCL,开始下一个时序模块
	return AckBit;							//返回定义应答位变量
}

Delay.h  Delay.c:

#ifndef __DELAY_H
#define __DELAY_H
#include "stdint.h"  //这个本来没有,但是有个保错,所以我就加上了

void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);

#endif
#include "stm32f10x.h"
#include "Delay.h"
/**
  * @brief  微秒级延时
  * @param  xus 延时时长,范围:0~233015
  * @retval 无
  */
void Delay_us(uint32_t xus)
{
	SysTick->LOAD = 72 * xus;				//设置定时器重装值
	SysTick->VAL = 0x00;					//清空当前计数值
	SysTick->CTRL = 0x00000005;				//设置时钟源为HCLK,启动定时器
	while(!(SysTick->CTRL & 0x00010000));	//等待计数到0
	SysTick->CTRL = 0x00000004;				//关闭定时器
}

/**
  * @brief  毫秒级延时
  * @param  xms 延时时长,范围:0~4294967295
  * @retval 无
  */
void Delay_ms(uint32_t xms)
{
	while(xms--)
	{
		Delay_us(1000);
	}
}
 
/**
  * @brief  秒级延时
  * @param  xs 延时时长,范围:0~4294967295
  * @retval 无
  */
void Delay_s(uint32_t xs)
{
	while(xs--)
	{
		Delay_ms(1000);
	}
} 

3.基于I2C编写INA226代码:

首先需要知道INA226的从机地址:芯片这样接线的话从机的写地址就是0x80 ,读地址就是0x81(参考规格书 表7)。

734b42c1d45c4870a7797e44d7e85d91.png

先在INA226.h里把从机地址和各个寄存器地址重定义一下(根据 规格书 表7)。之后就可以开始写INA226.c了。

INA226.h:

#ifndef __INA226_H__
#define __INA226_H__
#include "stdint.h"


#define 	CFG_REG	 		0x00		//配置寄存器地址
#define 	SV_REG 			0x01		//分流电压寄存器地址
#define 	BV_REG 			0x02		//总线电压
#define 	PWR_REG 		0x03		//电源功率
#define 	CUR_REG 		0x04		//电流
#define 	CAL_REG 		0x05		//校准
#define 	ONFF_REG 		0x06		//屏蔽 
#define 	AL_REG 			0x07		//包含与所选警报功能相比较的限定值
#define 	INA226_GET_ADDR 0XFF		//包含唯一的芯片标识号
#define   	INA226_ADDR1	0x80       //从机写地址

//初始化
void INA226_Init(void);
//发送数据到reg寄存器
void INA226_SendData(uint8_t reg,uint16_t data);
//读取寄存器reg的值
uint16_t INA226_ReadData(uint8_t reg);


//获取校准值
uint16_t  INA226_GetCAL(void);
//获取配置值
uint16_t  INA226_GetCFG(void);
//获取芯片ID
uint16_t  INA226_GetID(void);
//获取总线电压寄存器的值(只是寄存器值,不是真实电压值)
uint16_t INA226_GetBV(void);
//获取分流电压寄存器的值(只是寄存器值,不是真实电压值)
uint16_t INA226_GetSV(void);
//获取电流寄存器的值(只是寄存器值,不是真实电压值)
uint16_t INA226_GetSC(void);


#endif

编写INA226.c之前还要清楚几件事:

·MyI2C代码里的I2C一次发送的是8位数据,而INA226的地址和数据都是16位,传输的时候需要分别先后发送高8位和低8位。

·从INA226寄存器中读出来的数据不是真实的电压或电流值,是一个16位的数据,需要乘一个系数。

清楚这两件事我们可以开始写INA226的代码了,先不管具体怎么配置电压分辨率和采样规则,先把芯片寄存器的东西读出来试试再说。完整的INA226代码之后整体给出,这里先一部分一部分的讲:

发送16位数据到INA226:这个没什么好说的,逻辑就是

IIC开始 - 发送从机8位地址 - 接收应答 - 发送寄存器地址 - 接收应答 - 发送高8位 - 接收应答 - 发送低8位 - 接收应答 - IIC结束

//发送16位数据到INA226:reg是寄存器地址,data是要发送的16位数据
void INA226_SendData(uint8_t reg,uint16_t data)
{
	uint8_t temp=0;
	MyI2C_Start();//IIC开始
	MyI2C_SendByte(INA226_ADDR1); //这里我就直接把从机的写地址写入函数了(也就是0x80),没作为传参参数
	MyI2C_ReceiveAck(); //接收应答
	
	MyI2C_SendByte(reg);//发送寄存器地址,表明我们对INA226的这个寄存器进行写入
	MyI2C_ReceiveAck();//接收应答
	
	temp = (uint8_t)(data>>8); 
	MyI2C_SendByte(temp);//写入高8位
	MyI2C_ReceiveAck();//接收应答
	
	temp = (uint8_t)(data&0x00FF);
	MyI2C_SendByte(temp); //写入低8位
	MyI2C_ReceiveAck();//接收应答
	
	MyI2C_Stop();//IIC结束
}

读取INA226某个寄存器的数据:这里有点说法(更清楚的讲解在江科大软件IIC实现读写MPU6050那一节讲MPU6050.C的时候)。具体来说,要指定读INA226的某个寄存器,需要先把当前地址设置到该寄存器起始,然后才能读。即通过  ‘发送从机地址 - 发送寄存器地址 - IIC停止’  这样的方式将当前地址设置为某寄存器所在地址,然后重新开始IIC的‘当前地址读’程序。代码如下:

//接收来自INA226的16位数据,reg表示寄存器地址
uint16_t INA226_ReadData(uint8_t reg)
{
	uint16_t temp=0;
	
	MyI2C_Start();//IIC开始
	MyI2C_SendByte(INA226_ADDR1); //发送从机写地址
	MyI2C_ReceiveAck();//接收从机应答
	
	MyI2C_SendByte(reg);//发送寄存器地址
	MyI2C_ReceiveAck();//接收从机应答
	
	MyI2C_Stop();//IIC停止
	
	MyI2C_Start();//IIC开始
	
	MyI2C_SendByte(INA226_ADDR1+1);//从机写地址+1 = 从机读地址
	MyI2C_ReceiveAck();//接收从机应答
	
	
	temp = MyI2C_ReceiveByte();//接收高8位数据到temp
	MyI2C_SendAck(0);//0表示发送应答给从机,让从机不要再发数据了,我先把这16位接收完
	temp = temp <<8;//左移8位,让出低位
	temp = temp | MyI2C_ReceiveByte();//接收低8位数据到temp
	MyI2C_SendAck(1);//1表示发送应答

	MyI2C_Stop();//IIC停止
	return temp; 
}

有了发送和读取函数之后,就可以对INA226进行初始化了:

这里的CFG_REG和CAL_REG在INA226.h里定义,分别表示配置寄存器地址和校验寄存器地址。

配置寄存器设置为0x4527:也就是将芯片设置为:转换时间1.1ms,求平均值次数16,分流和总线连续模式 。具体配置成什么根据自己需要,具体请参考规格书“寄存器详细信息”一节。这个如果你想先试试,不要求太高准确度,你可以先像我这样配置0x4527成试试看。

55f9b844b00641809adc8fc37c8a3cb6.png

校准寄存器配置位0x2800:首先你先知道你要测的电流最大估计是多大,我这里最大1A。

根据规格书公式2:Current_LSB = 1A/2^15 = 3.05*10^-5 A 取一个比它大的近似值 我这里取5*10^-5 A (这个数据虽然比计数值大很多,但其实已经设置了一个很高的分辨率)。

根据公式1:CAL = 0.00512/(Current_LSB*Rshunt) = 0.00512/(5*10^-5 * 10 * 10^-3) = 10240

Rshunt:就是原理图中那个10mΩ的电阻值

换成16进制为:0x2800

//配置INA226
void INA226_Init(void)
{	
	MyI2C_Init();
	Delay_ms(10);
	//0100 010 100 100 111设置转换时间1.1ms,求平均值次数16,分流和总线连续模式
	INA226_SendData(CFG_REG,0x4527);
	INA226_SendData(CAL_REG,0x2800);//设置分流电压转电流转换参数 以最大测1A来设置分辨率
}

下面就是读取一系列INA226寄存器内存储的值了:

//获取 id
uint16_t  INA226_GetID(void)
{
	uint16_t temp=0;
	temp = INA226_ReadData(INA226_GET_ADDR);
	return temp;
}

//获取校准值
uint16_t  INA226_GetCAL(void)
{
	uint16_t temp=0;
	temp = INA226_ReadData(CAL_REG);
	return temp;	
}
//获取配置值
uint16_t  INA226_GetCFG(void)
{
	uint16_t temp=0;
	temp = INA226_ReadData(CFG_REG);
	return temp;	
}


//获取总线电压BV
uint16_t INA226_GetBV(void)
{
	uint16_t temp=0;
	temp = INA226_ReadData(BV_REG);
	return temp;	
}

//获取分流电压寄存器的值(只是寄存器值,不是真实电压值)
uint16_t INA226_GetSV(void)
{
	uint16_t temp=0;
	temp = INA226_ReadData(SV_REG);
	return temp;
}

//获取电流寄存器的值(只是寄存器值,不是真实电压值)
uint16_t INA226_GetSC(void)
{
	uint16_t temp=0;
	temp = INA226_ReadData(CUR_REG);
	return temp;
}

完整的INA226.C  INA226.H文件:

#ifndef __INA226_H__
#define __INA226_H__
#include "stdint.h"


#define 	CFG_REG	 		0x00		//
#define 	SV_REG 			0x01		//分流电压, 此处分流电阻为 0.1欧
#define 	BV_REG 			0x02		//总线电压
#define 	PWR_REG 		0x03		//电源功率
#define 	CUR_REG 		0x04		//电流
#define 	CAL_REG 		0x05		//校准,设定满量程范围以及电流和功率测数的 
#define 	ONFF_REG 		0x06		//屏蔽 使能 警报配置和转换准备就绪
#define 	AL_REG 			0x07		//包含与所选警报功能相比较的限定值
#define 	INA226_GET_ADDR 0XFF		//包含唯一的芯片标识号
#define   	INA226_ADDR1	0x80 

//初始化
void INA226_Init(void);
//发送数据到reg寄存器
void INA226_SendData(uint8_t reg,uint16_t data);
//读取寄存器reg的值
uint16_t INA226_ReadData(uint8_t reg);


//获取校准值
uint16_t  INA226_GetCAL(void);
//获取配置值
uint16_t  INA226_GetCFG(void);
//获取芯片ID
uint16_t  INA226_GetID(void);
//获取总线电压寄存器的值(只是寄存器值,不是真实电压值)
uint16_t INA226_GetBV(void);
//获取分流电压寄存器的值(只是寄存器值,不是真实电压值)
uint16_t INA226_GetSV(void);
//获取电流寄存器的值(只是寄存器值,不是真实电压值)
uint16_t INA226_GetSC(void);


#endif
#include "INA226.h"
#include "Delay.h"
#include "MyI2C.h"


//配置INA226
void INA226_Init(void)
{	
	MyI2C_Init();
	Delay_ms(10);
	//0100 010 100 100 111设置转换时间1.1ms,求平均值次数16,分流和总线连续模式
	INA226_SendData(CFG_REG,0x4527);
	INA226_SendData(CAL_REG,0x2800);//设置分流电压转电流转换参数 以最大测1A来设置分辨率
}

//发送16位数据到INA226:reg是寄存器地址,data是要发送的16位数据
void INA226_SendData(uint8_t reg,uint16_t data)
{
	uint8_t temp=0;
	MyI2C_Start();//IIC开始
	MyI2C_SendByte(INA226_ADDR1); //这里我就直接把从机的写地址写入函数了(也就是0x80),没作为传参参数
	MyI2C_ReceiveAck(); //接收应答
	
	MyI2C_SendByte(reg);//发送寄存器地址,表明我们对INA226的这个寄存器进行写入
	MyI2C_ReceiveAck();//接收应答
	
	temp = (uint8_t)(data>>8); 
	MyI2C_SendByte(temp);//写入高8位
	MyI2C_ReceiveAck();//接收应答
	
	temp = (uint8_t)(data&0x00FF);
	MyI2C_SendByte(temp); //写入低8位
	MyI2C_ReceiveAck();//接收应答
	
	MyI2C_Stop();//IIC结束
}

//接收来自INA226的16位数据,reg表示寄存器地址
uint16_t INA226_ReadData(uint8_t reg)
{
	uint16_t temp=0;
	
	MyI2C_Start();//IIC开始
	MyI2C_SendByte(INA226_ADDR1); //发送从机写地址
	MyI2C_ReceiveAck();//接收从机应答
	
	MyI2C_SendByte(reg);//发送寄存器地址
	MyI2C_ReceiveAck();//接收从机应答
	
	MyI2C_Stop();//IIC停止
	
	MyI2C_Start();//IIC开始
	
	MyI2C_SendByte(INA226_ADDR1+1);//从机写地址+1 = 从机读地址
	MyI2C_ReceiveAck();//接收从机应答
	
	
	temp = MyI2C_ReceiveByte();//接收高8位数据到temp
	MyI2C_SendAck(0);//0表示发送应答给从机,让从机不要再发数据了,我先把这16位接收完
	temp = temp <<8;//左移8位,让出低位
	temp = temp | MyI2C_ReceiveByte();//接收低8位数据到temp
	MyI2C_SendAck(1);//1表示发送应答

	MyI2C_Stop();//IIC停止
	return temp; 
}

//获取 id
uint16_t  INA226_GetID(void)
{
	uint16_t temp=0;
	temp = INA226_ReadData(INA226_GET_ADDR);
	return temp;
}

//获取校准值
uint16_t  INA226_GetCAL(void)
{
	uint16_t temp=0;
	temp = INA226_ReadData(CAL_REG);
	return temp;	
}
//获取配置值
uint16_t  INA226_GetCFG(void)
{
	uint16_t temp=0;
	temp = INA226_ReadData(CFG_REG);
	return temp;	
}


//获取总线电压BV
uint16_t INA226_GetBV(void)
{
	uint16_t temp=0;
	temp = INA226_ReadData(BV_REG);
	return temp;	
}

//获取分流电压寄存器的值(只是寄存器值,不是真实电压值)
uint16_t INA226_GetSV(void)
{
	uint16_t temp=0;
	temp = INA226_ReadData(SV_REG);
	return temp;
}

//获取电流寄存器的值(只是寄存器值,不是真实电压值)
uint16_t INA226_GetSC(void)
{
	uint16_t temp=0;
	temp = INA226_ReadData(CUR_REG);
	return temp;
}

到这里,基本代码就写完了。开始写main.c

我用的是江科大套件里的那个4引脚的小屏幕来观察输出的。

        BVF = BV*0.00116f; //计算实际总线电压
        SCF = SC*0.0000592857f;//计算实际电流

按照规格书中的说法,总线电压BV要乘0.00125的,但是我实测,0.00125的时候不准,和我万用表读数相差较大,可能是这个模块中Rshunt不稳定导致的,所以我基于我的万用表测量,把这个值设置为0.00116

另外,计算实际电流的时候,规格书里的式3给的是芯片内部的电流寄存器里的值的计算方式。

我们要把寄存器里的值转换成十进制的读数。

另外,这个芯片是比较精确的,但是模块上的采样电阻并不是特别精确,所以造成了按照理论设置的校准值并不准确,这时可以用万用表测一下实际电流电压,然后自己计算一下校准系数。

比如说,这时候万用表的读数是16.6mA   电流寄存器的十进制值是280,直接

16.6mA/280 = 0.0000592857

那么对于电压BV  实测0.493V  寄存器显示是425  直接 0.493/425 = 0.00116

这个模块在不接测量负载时,电流的输出值经常跳变到65535,但是其它时候测量是准的,我的解决办法是把这个值过滤掉if(SC>0xEFFF){SC = 0;}

这里的电压和电流,都是指定的U1 I1, 万用表就测这两个值。

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "MyI2C.h"
#include "Delay.h"
#include "INA226.h"
#include "ALLDATA.h"


int main(void)
{

	OLED_Init();
	MyI2C_Init();
	INA226_Init();
	uint16_t BV, SC, POWER;
	float BVF, SCF, POWERF;
	while (1)
	{

		BV = INA226_GetBV();  //读取电压 U1
		SC = INA226_GetSC(); //读取电流  I1
		POWER = BV*SC; 

		BVF = BV*0.00116f; //计算实际总线电压
		SCF = SC*0.0000592857f;//计算实际电流
		POWERF = BVF*SCF;
		
		
        OLED_ShowString(1, 1, "F:");
		OLED_ShowHexNum(1, 3, INA226_GetCFG(), 4); //获取配置值
		OLED_ShowString(1, 8, "A:");
		OLED_ShowHexNum(1, 10, INA226_GetCAL(), 4); //获取校准值
		
		OLED_ShowString(2, 1, "BV:");
		OLED_ShowString(2, 10, ".");
		OLED_ShowNum(2, 4, BV, 4); //获取总线电压
		OLED_ShowNum(2, 9, BVF, 1);//显示真实值
		OLED_ShowNum(2, 11, ((uint8_t)((BVF)*10))%10, 1);
		OLED_ShowNum(2, 12, ((uint8_t)((BVF)*100))%100, 1);
		OLED_ShowNum(2, 13, ((uint8_t)((BVF)*1000))%1000, 1);
		OLED_ShowNum(2, 14, ((uint8_t)((BVF)*10000))%10000, 1);
		OLED_ShowString(2, 15, "V");
	

		OLED_ShowString(3, 1, "SC:");
		OLED_ShowString(3, 10, ".");
		OLED_ShowNum(3, 4, SC, 4); //获取分流电阻电流
		OLED_ShowNum(3, 9, SCF, 1);//显示真实值
		OLED_ShowNum(3, 11, ((uint8_t)((SCF)*10))%10, 1);
		OLED_ShowNum(3, 12, ((uint8_t)((SCF)*100))%100, 1);
		OLED_ShowNum(3, 13, ((uint8_t)((SCF)*1000))%1000, 1);
		OLED_ShowNum(3, 14, ((uint8_t)((SCF)*10000))%10000, 1);
		OLED_ShowString(3, 15, "A");
		
		
		OLED_ShowString(4, 1, "PW:");
		OLED_ShowString(4, 10, ".");
		OLED_ShowNum(4, 4, POWER, 4); //获取功率
		OLED_ShowNum(4, 9, POWERF, 1);//显示真实值
		OLED_ShowNum(4, 11, ((uint8_t)((POWER)*10))%10, 1);
		OLED_ShowNum(4, 12, ((uint8_t)(POWER*100))%100, 1);
		OLED_ShowNum(4, 13, ((uint8_t)(POWER*1000))%1000, 1);
		OLED_ShowNum(4, 14, ((uint8_t)(POWER*10000))%10000, 1);
		OLED_ShowString(4, 15, "W");
		
		Delay_ms(100); //也可以不delay delay是便于观察屏幕
	}
}




 完整代码文件:https://pan.baidu.com/s/1HjCHBz-AFjS0GGpQmEiigA?pwd=1234

实拍图片:分别测得 SC和BV 功率的话可以用功率寄存器里的值,也可以直接SC*BV

c63e1735427c4f7a9559f98ee3d37750.jpegbf50fc7c92114f1dbe5bf720f9fd4d9c.jpeg

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值