草庐IT

基于STM32电压检测和电流检测

IT_阿水 2023-07-12 原文

基于STM32电压检测和电流检测

1.硬件平台

  • CPU:STM32F103C8
  • 屏幕:0.96寸OLED屏幕(SPI接口)
  • 电压测量模块: INA226(IIC接口)
  • 点流测量模块:ACS712(ADC采集)

2.功能实现

1.可测量直流电压0~36V,适用于低电压电子电路中。
2.可测量直流电0~5A范围内,目前采用的ACS712测量量程为5A,该模块有多个量程,可测量到20A
3.实时功率监测
4.电池电量监测(采用电压压降方式计算)

3.硬件介绍

3.1 INA226模块

  INA226是具有I2C™或SMBUS兼容接口的电流分流器和功率监控器。该设备同时监视并联电压降和总线电源电压。可编程的校准值,转换时间和平均值与内部乘法器结合使用,可以直接读取以安培为单位的电流和以瓦特为单位的功率。INA226感应共模总线电压上的电流,该电压可在0 V至36 V之间变化,与电源电压无关。该器件采用2.7V至5.5V单电源供电,典型功耗为330 µA。该器件的额定工作温度范围为–40°C至125 \ xC2°C,并且在I 2 C兼容接口上具有多达16个可编程地址。


  根据实物和原理图可看出IN和OUT 之间进接了一个0.002R电阻。在官方提供说明文档介绍改模块是可以测量直流电压0~36V,可测量总线共模电流,测量电流范围为-20A ~ 20A之间。测量精度为±1%。但在实际使用过程中发现仅能测量测量到电压值。测量电压时接线方式为:
  INPUT接电源正极,GND接电源负极。
  按照模块使用说明提示在将模块串联接入电路(即OUPUT接入到负载),实际测量发现无法获取到正常电流值,因此采用ACS712模块通过ADC方式完成电流测量。

3.2 INA226模块相关寄存器和设备地址

   1.INA226一共有6个寄存器(0x0~0x5),关于各个寄存器详细介绍这里则不展开介绍,可自行下载相关资料。

   2.INA226模块采用IIC通讯,根据原理图可知地址A1 A0 ==00,再参考官方技术文档可知模块设备地址为:0x40

从时序可以看出,第8位为读写使能位,则地址和读写为组合则为:读0x81,写0x80

3.3 INA226模块时序图

   在时钟下降沿沿时发送数据,上升沿读取数据。
  3.3 INA226模块驱动

#include "sys.h"
#include "myiic.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		/
//初始化INA226
void INA226_Init(void)
{	

	IIC_Init();
	INA226_SendData(INA226_ADDR1,CFG_REG,0x8000);	//重新启动
	
	INA226_SendData(INA226_ADDR1,CFG_REG,0x484f);	//设置转换时间204us,求平均值次数128,采样时间为204*128,设置模式为分流和总线连续模式
	INA226_SendData(INA226_ADDR1,CAL_REG,CAL);	//设置分辨率
	//INA226_SendData(INA226_ADDR1,CAL_REG,0x0012);//设置分流电压转电流转换参数	
	INA226_Get_ID(INA226_ADDR1);					//获取ina226的id
}
//设置寄存器指针
void INA226_SetRegPointer(u8 addr,u8 reg)
{
	IIC_Start();

	IIC_Send_Byte(addr);
	IIC_Wait_Ack();

	IIC_Send_Byte(reg);
	IIC_Wait_Ack();

	IIC_Stop();
}

//发送,写入数据
void INA226_SendData(u8 addr,u8 reg,u16 data)
{
	u8 temp=0;
	IIC_Start();

	IIC_Send_Byte(addr);
	IIC_Wait_Ack();

	IIC_Send_Byte(reg);
	IIC_Wait_Ack();
	
	temp = (u8)(data>>8);
	IIC_Send_Byte(temp);
	IIC_Wait_Ack();

	temp = (u8)(data&0x00FF);
	IIC_Send_Byte(temp);
	IIC_Wait_Ack();
	
	IIC_Stop();
}

//读取数据
u16 INA226_ReadData(u8 addr)
{
	u16 temp=0;
	IIC_Start();

	IIC_Send_Byte(addr+1);
	IIC_Wait_Ack();
	
	temp = IIC_Read_Byte(1);
	temp<<=8;	
	temp |= IIC_Read_Byte(0);
	
	IIC_Stop();
	return temp;
}
//1mA/bit
u16 INA226_GetShunt_Current(u8 addr)
{
	u16 temp=0;	
	INA226_SetRegPointer(addr,CUR_REG);
	temp = INA226_ReadData(addr);
	if(temp&0x8000)	temp = ~(temp - 1);	
	return temp;
}

//获取id
void INA226_Get_ID(u8 addr)
{
	u32 temp=0;
	INA226_SetRegPointer(addr,INA226_GET_ADDR);
	temp = INA226_ReadData(addr);
	ina226_data.ina226_id = temp;
}

//获取校准值
u16 INA226_GET_CAL_REG(u8 addr)
{	
	u32 temp=0;
	INA226_SetRegPointer(addr,CAL_REG);
	temp = INA226_ReadData(addr);
	return (u16)temp;
}

//1.25mV/bit
u16 INA226_GetVoltage(u8 addr)
{
	u32 temp = 0;
	INA226_SetRegPointer(addr,BV_REG);
	temp = INA226_ReadData(addr);
	return (u16)temp;	
}

//2.5uV/bit
u16 INA226_GetShuntVoltage(u8 addr)
{
	int16_t temp = 0;
	INA226_SetRegPointer(addr,SV_REG);
	temp = INA226_ReadData(addr);
	if(temp&0x8000)	temp = ~(temp - 1);	
	return (u16)temp;	
}

//获取电压
void GetVoltage(float *Voltage)//mV
{
	*Voltage = INA226_GetVoltage(INA226_ADDR1)*Voltage_LSB;
}

3.4 ACS712模块

  ACS712基于霍尔感应的原理设计,由一个精确的低偏移线性霍尔传感器电路与位于接近IC表面的铜箔组成(如下图所示),电流流过铜箔时,产生一个磁场, 霍尔元件根据磁场感应出一个线性的电压信号,经过内部的放大、滤波、斩波与修正电路,输出一个电压信号,该信号从芯片的第七脚输出,直接反应出流经铜箔电流的大小。ACS712根据尾缀的不一样,量程分为三个规格:±5A、±20A、±30A 。输入与输出在量程范围内为良好的线性关系,其系数Sensitivity分别为,185 mV/A、100 mV/A、66mV/A。因为斩波电路的原因,其输出将加载于0.5Vcc上。ACS712的Vcc电源 一般建议采用5V。输出与输入的关系为Vout=0.5Vcc+IpSensitivity。一般输出的电压信号介于0.5V~4.5V之间。
  典型的应用:电机领域,载荷检测和管理,开关电源领域,和各种电子产品过电流故障保护。
   器件特点

  • 80KHZ带宽
  • 总输出误差为1.5%
  • 采用小型贴片SOIC8封装
  • 1.2mΩ内部电阻
  • 左侧大电流引脚(PIN1-4)与右侧低电压引脚(PIN5-8)最小绝缘电压为2100V
  • 5V单电压工作
  • 该器件不可应用于汽车领域


  ACS712模块为霍尔传感器,通过ADC采集电压值,载根据电压与电流的线性关系时序电流转换,输入电流与输出电压对应曲线及计算公式:
  ACS712ELCTR-05B电流电压对应关系如下图,Ip=0A即没有输入电流的时候,对应输出电压为2.5V.精确度为185mV/A即为图中斜线的斜率。取VCC=5V,计算公式为:
Vout = 2.5 + 0.185*Ip

3.5 ACS712驱动

#include "adc.h"
/***************ADC规则通道初始化*************
**硬件接口:PB0 -- ADC1_CH8(模拟)
**
*注:ADC的工作频频率不能超过14MHZ
********************************************/
void ADC1_RegularChannel_Init(void)
{
	//1.开时钟
	RCC->APB2ENR|=1<<9;//ADC1时钟
	RCC->APB2ENR|=1<<3;//PB0时钟
	RCC->APB2RSTR|=1<<9;//ADC复位时钟
	RCC->APB2RSTR&=~(1<<9);//关复位
	/*2.GPIO配置*/
	GPIOB->CRL&=0xFFFFFFF0;//模式输入方式
	/*3.ADC时钟频率配置*/
	RCC->CFGR&=~(0x3<<14);//清除原来配置
	RCC->CFGR|=0x2<<14;//ADC工作频率72MHZ/6=12MZH
	/*4.配置ADC核心寄存器*/
//	ADC1->CR1&=~(0xF<<16);//独立模式
	ADC1->CR2|=1<<23;//启动温度传感器(测量CPU温度)
	ADC1->CR2|=1<<20;//规则通道外部触发转换模式
	ADC1->CR2|=0x7<<17;//外部事件通过开关事件触发
//	ADC1->CR2&=~(1<<11);//右对齐(地位对齐,高位补0)
	ADC1->SMPR1|=0x7<<18;//温度传感器采样时间通道16
	ADC1->SMPR2|=0x7<<24;//通道8采用时间
	ADC1->SQR1&=~(0xF<<20);//规则通道转换的通道数目为1个转换
//	ADC1->CR2&=~(1<<1);//单次转换模式
	ADC1->CR2|=1<<0;//开启ADC
	ADC1->CR2|=1<<3;//初始化校准
	while(ADC1->CR2&1<<3);//等待初始化校准完成
	ADC1->CR2|=1<<2;//开始校准
	while(ADC1->CR2&1<<2){}//等待校准完成
}
/****************ADC1规则通道获取数值***************/
u16 ADC1_GetRegularCHx(u8 chx)
{
	ADC1->SQR3&=~(0x1F<<0);//清除原来寄存器中的值
	ADC1->SQR3|=chx;//要转的通道号
	ADC1->CR2|=1<<22;//开启转换规则通过
	while(!(ADC1->SR&1<<1)){}//等待转换完成
	return ADC1->DR;
}

4.实物测量效果


示例地址:https://download.csdn.net/download/weixin_44453694/85520132

有关基于STM32电压检测和电流检测的更多相关文章

  1. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  2. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  3. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  4. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  5. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  6. ruby - 检测由 RSpec、Ruby 运行的代码 - 2

    我想知道我的代码是否在rspec下运行。这可能吗?原因是我正在加载一些错误记录器,这些记录器在测试期间会被故意错误(expect{x}.toraise_error)弄得乱七八糟。我查看了我的ENV变量,没有(明显的)测试环境变量的迹象。 最佳答案 在spec_helper.rb的开头添加:ENV['RACK_ENV']='test'现在您可以在代码中检查RACK_ENV是否经过测试。 关于ruby-检测由RSpec、Ruby运行的代码,我们在StackOverflow上找到一个类似的问题

  7. ruby - 使用 Ruby Daemons gem 检测停止 - 2

    我正在使用rubydaemongem。想知道如何向停止操作添加一些额外的步骤?希望我能检测到停止被调用,并向其添加一些额外的代码。任何人都知道我如何才能做到这一点? 最佳答案 查看守护程序gem代码,它似乎没有用于此目的的明显扩展点。但是,我想知道(在守护进程中)您是否可以捕获守护进程在发生“停止”时发送的KILL/TERM信号...?trap("TERM")do#executeyourextracodehereend或者你可以安装一个at_exit钩子(Hook):-at_exitdo#executeyourextracodehe

  8. ruby-on-rails - (Ruby,Rails) 基于角色的身份验证和用户管理...? - 2

    我正在寻找用于Rails的优质管理插件。似乎大多数现有的插件/gem(例如“restful_authentication”、“acts_as_authenticated”)都围绕着self注册等展开。但是,我正在寻找一种功能齐全的基于管理/管理角色的解决方案——但不是简单地附加到另一个非基于角色的解决方案。如果我找不到,我想我会自己动手......只是不想重新发明轮子。 最佳答案 RyanBates最近做了两个关于授权的railscast(注意身份验证和授权之间的区别;身份验证检查用户是否如她所说的那样,授权检查用户是否有权访问资源

  9. ruby - 在 Rakefile 中动态生成 Rake 测试任务(基于现有的测试文件) - 2

    我正在根据Rakefile中的现有测试文件动态生成测试任务。假设您有各种以模式命名的单元测试文件test_.rb.所以我正在做的是创建一个以“测试”命名空间内的文件名命名的任务。使用下面的代码,我可以用raketest:调用所有测试require'rake/testtask'task:default=>'test:all'namespace:testdodesc"Runalltests"Rake::TestTask.new(:all)do|t|t.test_files=FileList['test_*.rb']endFileList['test_*.rb'].eachdo|task|n

  10. ruby - Ruby 脚本如何检测到它正在 irb 中运行? - 2

    我有一个定义类的Ruby脚本。我希望脚本执行语句BoolParser.generate:file_base=>'bool_parser'仅当脚本作为可执行文件被调用时,而不是当它被irbrequire(或通过-r在命令行上传递)时。我可以用什么来包装上面的语句,以防止它在我的Ruby文件加载时执行? 最佳答案 条件$0==__FILE__...!/usr/bin/ruby1.8classBoolParserdefself.generate(args)p['BoolParser.generate',args]endendif$0==_

随机推荐