蓄电池在电力系统中是一种必备的后备电源且数量较多, 其使用寿命和安全可靠性倍受用户关注。但由于使用不当或者不能及时维护,经常会导致蓄电池组中个别蓄电池的过放电或者早期失效。过放电或者早期失效的个别蓄电池在后备电源投入使用时,会严重影响整个电池组的放电容量,甚至会导致整个供电系统的崩溃。因此,为保证在市电被切断时用电设备能够安全可靠运行,避免蓄电池在长期使用过程中因个别电池过放电或者失效而引发事故带来经济损失,对蓄电池进行实时在线监测和及时的故障诊断成为蓄电池维护工作的一个极为重要 方面。本文介绍的基于STC89C58RD+微控制器的蓄电池在线监测系统,能实现对蓄电池无论在闲置状态还是充、放电动态过程中的状态监测;对蓄电池内 部开路、短路、过压、欠压及过度放电等异常状态及时报警并存储数据以备查询;能对2V、6V和12V多种多节电池电压在线测量;提高了对蓄电池监测的准确 性、自动化和智能化程度。本文具体介绍了系统的硬件设计和软件实现。
系统硬件设计
系统硬件结构
蓄电池在线监测系统是以STC89系列的STC89C58RD+微控制器、XILINX的XC9572-84为核心,外围电路主要由电压采集电路、 A/D转换电路、显示驱动电路及键盘电路等几部分组成的,如图1所示。A/D转换芯片采用10位ADC TLC1549。显示驱动芯片采用MC14489B,它可以驱动5位共阴极数码管,微控制器的P1口的低5位作为键盘输入口,扩展的RS485接口用于多 机通信 。下面详细介绍系统中STC89C58RD+、XC9572-84器件和电压采集电路、A/D转换电路的设计与实现。
图1 系统硬件结构框图
微控制器STC89C58RD+简介
STC89C58RD+是STC89系列的微控制器,它不但与80C51完全兼容,而且还有新的特点:片内含有Flash程序存储器32Kb, DataFlash数据存储器32Kb,RAM数据存储器1208B,同时内部还有看门狗(WDT);由于ALE信号开关状态可设置,从而降低了EMI; 具有可编程的8级中断源4种优先级,具有系统可编程(ISP)和应用可编程(IAP)等特点,片内资源丰富、集成度高、使用方便。STC89C58RD+ 对系统的工作进行实施调度,实现外部输入参数的设置、电池电压的测试和显示、电池工作状态的指示。
逻辑编程器件XC9572-84(CPLD)
由于监测的电池节数较多,所需要I/O口较多,用传统的设计方法,需要74HC273、74HC00、74HC138、CD4514等多种芯片来实 现,器件种类和数量多,使PCB的尺寸加大,也增加了系统的不稳定因素。本系统选用XILINX系列的CPLD器件XC9572-84,其共有72个宏单 元,69个I/O口,1600个门,72个寄存器,可以对上述多种芯片进行集成。该器件具有在系统可编程能力,含有先进的数据保密特性,它可以完全保护编 程数据不被非法读取和擦除,每个I/O口都有一个可编程输出摆率控制位从而可减小系统噪声,采用具有较低功耗的快速闪存技术,每个I/O口的驱动能力强, 负载电流可达24mA。XC9572-84接收单片机传来的数据和地址,控制各个固态继电器(G3VM-402C)的选通以及A/D转换的进行,达到采集 电压的功能。采用了CPLD器件后,减少了系统所需器件的数量和种类,简化了PCB的排版和布线,减小了系统体积和节约成本,方便了系统调试,有利于批量化生产。
图2 电压采集电路
电压采集电路
电压采集电路直接影响到电压测试的精确程度,因而采集电路设计得是否适当对整个系统至关重要。对每节电池电压进行测量,有两种方法:①对每节电池电 压直接采集。②采集(n+1)节电池的总电压,减去n节电池的总电压得第n+1节电池电压。第一种电压采集精确而且安全。第二种虽然电路比较简单但是当电 池节数多时采集的电压太高,不安全而且会出现较大的误差。因此选用第一种方法。电压采集电路要求要安全,采集的电压要足够的稳定。本系统的蓄电池组采用串 接方式,BAT1+接第一节电池的正极,BAT2+接第二节的正极(第一节的负极),如此依次连接,最多可达41节。经过XC9572-84模拟开关选通 G3VM-402C后,将1~n节电池电压依次释放到电压总线BUS1+、BUS1-上,电路选用运算放大器LM358作为信号放大器件,它的前级为差分 式放大器,后级为电压跟随器,使TLC1549得到一个稳定的采样电压,如图2所示。1VD0和1VD1采用FR104高速开关管来保护运算放大器的内部 电路。差分式放大倍数为A=0.2,具体推导如下:
(Ua-Up)/1R12=Up/1R14; ①
(Ub-Un)/1R11=(Un-Vo)/1R13;②
注意运放的“虚短”特点,有Up=Un;结合①、②两式得到Vo=((1R11+1R13)/1R11)·(1R14/(1R12+1R14))·Ua-1R13/1R11·Ub;选取电阻满足:1R13/1R11=1R14/1R12的关系,输出电压可简化为:Vo=1R13/1R11·(Ua-Ub),故电压放大倍数A=Vo/(Ua-Ub)=1R13/1R11=0.2。
A/D转换电路
本系统A/D转换采用片外串行总线10位高速高精度专用集成电路TLC1549,其功耗低、体积小、占用单片机的资源少,具有连接方便、编程简单的 特点。电压采集电路的输出电压与TLC1549的A/D转换通道相连接,在时钟脉冲信号作用下,TLC1549将电压转换成10位二进制数字信号,并把上 次A/D转换的结果以10位二进制数的形式依次输出,再通过光电隔离传送到单片机进行处理,如图3所示。
图3 A/D转换电路
硬件设计过程中的注意点
1 系统用多路电源,要考虑系统的功耗选择适当的电源,电源电压应比较稳定。
2 电压采集部分使用固态继电器(G3VM-402C),由于电池节数较多,电压比较高,故应注意对内部电路的保护,可以采用适当功率的电阻。对放大电路的电 阻精度要求较高,可选用精度为1%的金属膜电阻;电路设计应避免出现因多个固态继电器同时开通的直通现象,这样会使多节蓄电池短路,造成电压采集电路的损 坏。
3 A/D转换芯片的基准电源要十分稳定,基准电源与芯片工作电源应采用不同的共地电源,以保证A/D转换芯片基准电源的稳定性。为了减少干扰,时钟和片选信号与单片机、CPLD之间进行光电隔离。
4 器件的布局和PCB图的布线采用模块化,交流与直流分离,强电与弱电分离,数字地和模拟地分开,注意电源线和地线的布局。
系统软件设计
在单片机的软件编程上,以Keil C编译器的Windows集成开发环境 μvision2作为软件开发平台,采用C51高级语言编写。该语言是80C51系列单片机的专门的高性能的程序设计语言。它采用符合ANSI标准的C语 言编程,便于改进、扩充和移植,可以对硬件进行操作,能够产生极高速和极其简洁形式的目标代码,在代码的效率和执行速度上完全可以和汇编语言相媲美,并且 有十分丰富的库函数可以供用户直接调用,从而极大地提高了程序的编写效率,能提供给用户高质量的程序代码。采用硬件描述语言Verilog HDL对CPLD进行编程。
单片机软件编程注意点
1 键盘在定时中断服务程序中读取,用中断间隔时间实现键盘的去抖,不必编写另外的延时程序,提高了CPU的利用效率。键盘值存入数据缓冲区,在主程序中读数据缓冲区的内容,执行键盘功能散转子程序。
2 电池电压的采集在中断程序中执行,因固态继电器的开通与关断时间均需1ms,故通道选通时要有一定的延时,使电池采集电压建立并稳定后再启动A/D转换。
3 根据A/D转换芯片TLC1549的工作原理,当前输出的数据是上一次A/D转换的结果, 故对一节电池电压采样的首次A/D转换结果应丢弃,其余几次转换结果保留并加以处理。
图4 单片机软件编程流程图
4 根据STC89C58RD+的DataFlash 的特点,数据写入时必须启动ISP/IAP命令,CPU等待IAP动作定时后,才继续执行程序,要先关断中断(EA)。要使数据写入DataFlash存 储器,不能跨越扇区,如果要对某个扇区进行擦除,而其中有些字节的内容需要保护,则需将其先读到单片机内部的RAM中保存,再将该扇区擦除,然后再将保存 的数据写回该扇区。
CPLD的Verilog HDL编程
用硬件描述语言Verilog HDL的程序设计硬件的好处在于易于理解、易于维护、调试电路速度快、有许多易于掌握的仿真、综合和布局布线的工具,还可以用C语言配合Verilog HDL来做逻辑设计的布线前和布线后仿真,验证功能是否正确。限于篇幅,下面给出部分模块的Verilog HDL程序
module REG8 ( CLRB, D, CLK, Q ); //8位数据锁存
input CLRB, CLK;
input [7:0] D;
output [7:0] Q;
reg [7:0] Q;
always @( posedge CLK or negedge CLRB )
Q <= ( !CLRB )? 0: D;
endmodule
module DECODE4_16( E1,A,Y ); //4-16译码
input E1;
input [3:0] A;
output [15:0] Y;
reg [15:0] Y;
always @( E1 or A )
if(E1==0 )
begin
case(A)
0:Y=16'b1111111111111110;
1:Y=16'b1111111111111101;
2:Y=16'b1111111111111011;
3:Y=16'b1111111111110111;
4:Y=16'b1111111111101111;
5:Y=16'b1111111111011111;
6:Y=16'b1111111110111111;
7:Y=16'b1111111101111111;
8:Y=16'b1111111011111111;
9:Y=16'b1111110111111111;
10:Y=16'b1111101111111111;
11:Y=16'b1111011111111111;
12:Y=16'b1110111111111111;
13:Y=16'b1101111111111111;
14:Y=16'b1011111111111111;
15:Y=16'b0111111111111111;
endcase
end
else
Y=16'b1111111111111111;endmodule