初学笔记,有错的地方感谢指出。反正我最后是实现了测量电压电流和功率,准确度还不错,可能某些地方理解有误,但最终确实是实现了测量。
硬件部分:这里展示了4种连接方法,大同小异。每个电路都可以测出U1和I1。芯片内部VIN和VOUT之间接了一个10mΩ的电阻,模块电路已给出。
软件部分:
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)。
先在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成试试看。
校准寄存器配置位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