当前位置:首页 > 电子图书 > 电子电路 > 正文内容

模拟量采集从硬件到程序,从滤波到实际值转换,多少人懂了

admin1年前 (2023-07-25)电子电路32

本原创文章基于实践经验,提供严谨可靠的设计原理及思路。

❤在单片机系统里对模拟量的处理要比数字量稍显复杂,但是只要掌握了使用技巧,使用起来也很简单,很多朋友一开始比较纠结于单片机的底层语言,非要先弄个明白才罢休,其实大可不必,重要的是我们要先学会怎么应用。

❤现以铅酸电池电压检测充电电流检测为例讲解模拟量的硬件和程序的设计。

如图1为28节铅酸电池的电压检测电路,1--14节组成电池组1,15--28节组成电池组2;第1节正极为BAT+,14与15节之间为BATM,第28节负极为BAT-。输入端的8个二极管的作用是钳位作用;电路计算如图所示。

图1:电池组电压检测电路

如图2为铅酸电池的充电电流检测电路,TA1为工频电流互感器,输入的4个二极管为整流二极管,电流流过R37(510Ω)形成压差△V。电路计算如图所示。

图2:电池组充电电流检测电路

如图3为单片机STM32F103CBT6,图1和图2的模拟信号输入至单片机的PA5、PA6、PA7。

图3:STM32F103CBT6单片机

由于代码较多,为便于浏览,我就把其中一部分以截图的形式展示,敬请谅解,需要源程序的可以私信留下邮箱。

如图4为单片机adc.c文件的底层配置,把PA5、PA6、PA7端口配置成模拟输入模式

图4:配置端口模式

如图5对以上三个模拟量进行模数转换并缓存入数组ADC_ConvertedValue[3],得到的AD值的范围是0~4096

图5:模数转换并缓存

如图6把以上两个配置函数整合在一起,定义成模拟量的初始化函数void ADC1_Init(void)。

图6:初始化

如图7在adc.h文件里声明函数void ADC1_Init(void),另外几个函数也在adc的c文件里定义的,后面附上源程序(非截图)。

图7:声明函数

如图8在main()主函数里调用ADC1_Init()初始化函数(要去掉void),初始化函数一定要放在while(1)的前面,表示在进入while(1)无限循环前只执行一次。 Analog_Processing()为模拟量处理函数,要放在while(1)无限循环里面(该函数在下面讲)。

图8,函数调用

以下为模拟量在main.c文件里的定义。

s16 Charging_Current;		 //充电电流实际值
s16 Battery1_Voltage;		 //电池组1电压实际值
s16 Battery2_Voltage;		 //电池组2电压实际值
s16 Battery_Voltage; 		 //电池组总电压值

❤下面三个函数的定义都在adc.c文件里面定义的。

以下代码为模拟量处理函数:①对数组ADC_ConvertedValue[3]缓存值进行滤波处理;②对滤波后的AD值转换为实际值。

/******************************
模拟量处理函数
******************************/
void Analog_Processing(void)
{
//对AD值进行滤波
ADC_Charging_Current=Filter(ADC_ConvertedValue[0],ADC_Charging_Current,1,10);
ADC_Battery1_Voltage=Filter(ADC_ConvertedValue[1],ADC_Battery1_Voltage,1,10);
ADC_Battery2_Voltage=Filter(ADC_ConvertedValue[2],ADC_Battery2_Voltage,1,10);
//AD值转换为实际值
Charging_Current = Adc_To_Act(ADC_Charging_Current, 10, 4096, 0, 220);//22.0A
Battery1_Voltage = Adc_To_Act(ADC_Battery1_Voltage, 10, 4096, 0, 267);//267V
Battery2_Voltage = Adc_To_Act(ADC_Battery2_Voltage, 10, 4096, 0, 267);//267V
//两组电压相加得到总电压
Battery_Voltage = Battery1_Voltage + Battery2_Voltage;
}

以下代码为滤波函数,滤波函数有很多,采用合适的才是最实用的(该函数滤波后的值是连续变化的,有些滤波函数滤波后的值是跳变的)。

/******************************
滤波函数(base/k越大,容性越大)
该函数相当于是一个电容,通常取值k=1,base=10
******************************/
u16 Filter(u16 NewData, u16 OldData, u8 k, u8 base)
{
	u16 uiResult;
	if (NewData > OldData)
	{
		uiResult = NewData - OldData;
		uiResult *= k;
		uiResult += base >> 2;
		uiResult /= base;
		uiResult = OldData + uiResult; 
	}
	else if (OldData > NewData)
	{
		uiResult = OldData - NewData;
		uiResult *= k;
		uiResult += base >> 2;
		uiResult /= base;
		uiResult = OldData - uiResult; 
	}
	else
	{
		uiResult = NewData;
	}
	
	return(uiResult);
}

使用方法如下:NewData表示最新采用的模拟量;OldData表示滤波后的模拟量。

ADC_Battery1_Voltage=Filter(ADC_ConvertedValue[1],ADC_Battery1_Voltage,1,10);

为便于逻辑计算、控制及显示,以下代码是把AD值转换为实际值,

/******************************
AD值转换实际值函数
******************************/
s16 Adc_To_Act(s16 Adc_Value, s16 Pre_Adc_Min, s16 Pre_Adc_Max, s16 Pre_Act_Min, s16 Pre_Act_Max)
{
s32 _temp;
s32 _range;
_temp = (s32)((Adc_Value - Pre_Adc_Min) * (Pre_Act_Max - Pre_Act_Min) / (Pre_Adc_Max-Pre_Adc_Min)) + Pre_Act_Min;
_temp = Adc_Value - Pre_Adc_Min;
_range = Pre_Act_Max - Pre_Act_Min;
_temp = _temp * _range;
_range = Pre_Adc_Max - Pre_Adc_Min;
_temp = _temp + _range / 2;
_temp = _temp / _range;
_temp = _temp + Pre_Act_Min;
return(_temp);
}

使用方法如下:Adc_Value表示要转换的模拟量;Pre_Adc_Min表示模拟量AD值的最小值;Pre_Adc_Max表示模拟量AD值的最大值;Pre_Act_Min表示转换后实际值的最小值;Pre_Act_Max表示转换后实际值的最大值;(以下最大实际值220表示22.0A,是因为数码管显示需要小数表示)。

Charging_Current = Adc_To_Act(ADC_Charging_Current, 10, 4096, 0, 220);//22.0A

❤要点:

①模拟量的采样电路,我多采用运放的差分放大电路,原因是被测电压可以和运放不用共地,且可有效抑制共模噪声,可达到较高的精确线性测量,比如以上电池组的被测电压的误差与实际相差在0.3V左右;

②电池组输入至运放的8个1M的电阻是两个为一组的,且功率至少1/4W以上,因为在高压下的电阻容易老化,为保险起见,通常一个电阻的最大压差在100V以下为宜;

③电池组分为两组检测,一是为了降低元件所承受的电压,二是为了监视两组电池电压之间是否平衡,达到保护电池目的。

③函数应功能模块化,且具备通用性质,便于移植和调用,对于很多朋友应先学会如何使用,底层代码只要会配置就完全足够了。

当然,以上提供的设计是我通常的做法,能满足大多数的常规应用。


扫描二维码推送至手机访问。

版权声明:本文由梦魁网络资源站发布,如需转载请注明出处。

本文链接:https://family.monkui.com:39/?id=1162

标签: 电子电路
分享给朋友:

相关文章

看爽了!50张电工接线图,够你琢磨一天了

看爽了!50张电工接线图,够你琢磨一天了

   众所周知,所谓电工也就是成天跟“电”打交道的存在,那么下面这么多电工接线图,各位老师傅熟悉哪些呢?一起来看看吧!1、启、停延时不断循环2、桥式全波整流滤波电路3、起保停控制4、电源线的接电方式5、时间继电器延时控制...

非常全的地线基础知识整理

非常全的地线基础知识整理

线的作用地线的主要作用就是当电器出现故障时,电源可能击穿(或:破坏)某些元件,使电器的外壳带电。将电器的外壳接地,可以使漏电保护装置1. 信号“地”;信号“地”又称参考“地”,就是零电位的参考点,也是构成电路信号回路的公共段,图形符号“⊥”...

电工最实用的8大经验公式,快快收藏~

电工最实用的8大经验公式,快快收藏~

一、照明电路电流计算及熔丝刀闸的选择口诀:白炽灯算电流,可用功率除压求;日光灯算电流,功率除压及功率因数求(节能日光灯除外);刀闸保险也好求,一点五倍额定流。说明:照明电路中的白炽灯为电阻性负荷,功率因数cosΦ=1,用功率P单位瓦除以电压...

200个电气知识,值得收藏

01电荷的性质答:电荷之间存在着相互作用力,同性电荷相互排斥,异性电荷相互吸引。02电场答:在带电体周围的空间存在着一种特殊物质,它对放在其中的任何电荷表现为力的作用,这一特殊物质叫做电场。03电阻,影响电阻的因素答:电流在导体内流动过程中...

一分钟学会电机正反转电路电机顺序启动,逆序停止!

一分钟学会电机正反转电路电机顺序启动,逆序停止!

电机正反转作为最基本的电路,学习电工是一定要了解的。要学习电机电机正反转电路一定要了解电机正反转工作原理,就是当我们按下正转启动按钮的时候,电机会正转,这时候按下反转启动按钮是不起作用的,只有按下停止按钮,电动机停止以后才能启动电机反转。电...

电工接线口诀,记住你就是电工老师傅了

电工接线口诀,记住你就是电工老师傅了

电工接线口诀一 安全注意事项火线L零线N,金属外壳接地E。零线接地火有电,氖气发光是火线,氖管电阻一百万。手按笔卡尖接线,注意手指不碰尖。触电事故先断电,绝缘棒来挑起线。火线零线并排走,插座电器并联接。三孔插座上接地,两孔插座右接...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。