智能电池充电器的设计-毕业设计 - 图文

更新时间:2023-03-08 18:51:00 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

编号

2014020342B

研究类型

应用研究

分类号

TN7

学士学位论文(设计)

Bachelor’s Thesis

论文题目

智能电池充电器的设计

作者姓名 学

陈绪词 2010112020342 物理与电子科学学院 电子信息科学与技术 潘言全 副教授 2014年5月11日

所在院系 学科专业名称 导师及职称 论文答辩时间

学士学位论文(设计)诚信承诺书

中文题目:智能电池充电器的设计 外文题目:The Design of Intelligent Battery Charger 学生姓名 院系专业 陈绪词 物理与电子科学学院 电子信息科学与技术 学 生 承 诺 我承诺在学士学位论文(设计)活动中遵守学校有关规定,恪守学术规范,本人学士学位论文(设计)内容除特别注明和引用外,均为本人观点,不存在剽窃、抄袭他人学术成果,伪造、篡改实验数据的情况。如有违规行为,我愿承担一切责任,接受学校的处理。 学生(签名): 2014年5月8日 指导教师承诺 我承诺在指导学生学士学位论文(设计)活动中遵守学校有关规定,恪守学术道德规范,经过本人核查,该生学士学位论文(设计)内容除特别注明和引用外,均为该生本人观点,不存在剽窃、抄袭他人学术成果,伪造、篡改实验数据的现象。 指导教师(签名): 2014年5月8日 学生学号 学生班级 2010112020342 1003

目 录

1. 前言 ....................................................................................................................................... 1 2. 系统设计概述 ........................................................... 2

2.1设计内容和要求 ..................................................... 2 2.2总体设计方案 ....................................................... 2 3. 硬件电路设计 ........................................................... 6

3.1总体电路设计 ....................................................... 6 3.2硬件功能模块分析 ................................................... 6 4. 系统软件设计 .......................................................... 10

4.1主程序流程图 ...................................................... 10 4.2数码管显示模块 .................................................... 11 4.3定时器模块 ........................................................ 12 4.4按键处理器模块 .................................................... 12 4.5ADC采样和PWM模块 ................................................. 13 4.6充电过程处理模块 .................................................. 13 5. 系统实物调试和效果 .................................................... 14 6. 总结与展望 ............................................................ 16 7. 参考文献 .............................................................. 17 致谢

学士学位论文(设计)评审表

智能电池充电器的设计

陈绪词(指导老师,潘言全 副教授)

(湖北师范学院物理与电子科学学院,湖北 黄石 435002)

摘 要:本文所述的智能电池充电器,利用运放和场效应管构成的闭环控制组成恒流恒

压源,根据锂电池的特性,通过恒流恒压源对电池进行充电。单片机产生PWM波,通过滤波电路去调节恒流恒压源,单片机自带的ADC功能,对恒流恒压源的电流和电压进行检测,并且与之前设置最大电流和最大电压进行比较,从而进行调节。按键设置充电器的最大电流和最大电压,设置完成之后,充电器处于工作状态,数码管显示电池两端的电压和电流。整个过程实现智能调控。 关键词:单片机;充电器;恒流恒压源;智能 中图分类号: TN7

The Design Of Intelligent Battery Charger

Chen Xuci(Tutor:Pan Yanquan) (College of Physics and Electronic Science, Hubei Normal University, Huangshi, 435002, China)

Abstract: A intelligent battery charger described in this paper is a constant current and

constant voltage source realized by closed-loop controls composed of operational amplifiers and FETs. According to the characteristics of lithium battery, a battery is charged by the charger. With the use of PWM wave by MCU, the charger is adjusted through the filter circuit. ADCs on MCU are able to detect the current and voltage and compare the maximum current and maximum voltage set before, so as to adjust. The maximum current and maximum voltage of the charger is set up by keys. After a one-time setup, the charger is in working state, and digital pipes display battery voltage and current. The whole process is intelligently controlled.

Key words:MCU;Charger;Constant current and constant voltage source;Intelligence

湖北师范学院物理与电子科学学院2014届学士学位论文

智能电池充电器的设计

陈绪词(指导老师,潘言全 副教授)

(湖北师范学院物理与电子科学学院,湖北 黄石 435002)

1. 前言

社会信息化进程的加快对电力、信息系统的安全稳定运行提出了更高的要求。在人们的生产、生活中,各种电气、电子设备的应用也越来越广泛,与人们的工作、生活的关系日益密切,越来越多的工业生产、控制、信息等重要数据都要由电子信息系统来处理和存储。而各种用电设备都离不开可靠的电源,如果在工作中间电源中断,人们的生产和生活都将受到不可估量的经济损失[1]。

对于由交流供电的用电设备,为了避免出现上述不利情况,必须设计一种电源系统,它能不间断地为人们的生产和生活提供以安全和操作为目的可靠的备用电源。为此,以安全和操作为目的的备用电源设备上都使用充电电池[2]。这样,即使电力网停电,也可利用由充电电池构成的安全和操作备用电源,从容地采用其他应急手段,避免重大损失的发生。而对于采用充电电池供电的用电设备,从生产、信息、供电安全角度来说,充电电池在系统中处于及其重要的地位。

同时,具体到生活方面,随着社会的快速发展,电子产品小型化、便携化也使得充电电池越来越重要,锂离子电池有较高的比能量,放电曲线平稳,自放电率低,循环寿命长,具有良好的充放电性能,可随充随放、快充深放,无记忆效应,不含镉、铅、汞等有害物质,对环境无污染,被称为绿色电池。基于这些特性,所以锂电池得到了迅速的发展和广泛的应用。锂电池充电器是为锂离子充电电池补充能源的静止变流装置,其性能的优劣直接关系到整个用电系统的安全性和可靠性指标[3]。

本文对设计硬件电路的过程进行了详细的描述,包括对方案的选择和元器件的选择。软件控制流程也进行了详细的叙述。充电器的技术已经很成熟了,正好通过这次毕业设计,对大学四年所学的的知识进行整合,回顾。

1

湖北师范学院物理与电子科学学院2014届学士学位论文

2. 系统设计概述

2.1设计内容和要求

一般市场上的万能充电器只能对4.2V的锂电池进行充电[4],我们这次设计的可编程智能充电器,是在普通的万能充基础上进行升级,可以对充电的最大电压和最大电流进行设定,这样就可以使充电器的适用范围更广。要求:

①充电电压的范围为1V~13V,最大充电电流为0.5A-2.5A;

②能实现电池的充电与显示,显示的结果够精确,并且具备很好的稳定性; ③电路简单、成本要求低;

④操作简单、方便、易懂、数码管显示;

2.2总体设计方案 2.2.1设计思路

本设计的关键就是要知道电池充电过程的三个阶段,涓流充电,恒流充电,恒压充电,然后需要设计一个电路,具有恒流恒压功能。然后把这三个阶段的电压电流情况在数码管上显示出来。

2.2.2方案论证与比较

从设计思路出发,可以提出以下三个方案: 方案一:

电路原理图如图2-1所示。这种方案主要用到了一个基准源TL431,它是一种三端可调分流基准源[5]。DA的输出电压通过一个电阻R4接至TL431的参考极。当调节DA的输出电压使参考极电压高于2.5V时,三极管中有一个很大的电流通过。那么经过三极管输出的电流将会减小,电压也会随之下降。当调节DA的输出电压使参考极电压低于2.5V时,三极管相当于截止状态,通过R1经TL431到地的电流就很小,接近于0。那么三极管输出的电流将会增大,输出电压也会增加。当AD检测到输出电压超过4.2V时,又会自动调整增加DA的输出电压,使TL431导通,从而使三极管的输出电压减小。整个充电过程中,单片机会通过AD检测电池两端的输出电压和充电电流,过大或者过小都会通过控制DA的输出电压对电路进行调整,使得输出的电压和电流保持在一个相

2

湖北师范学院物理与电子科学学院2014届学士学位论文

对稳定的状态。DA的输出电压取决于电路中电阻R4的大小。

3Q2211R11000R21.75kB23V锂电池B19V3U11R4MCU-DAC 调电压5kTL431R35kB38VR50.52 图2-1 方案一电路图

方案二:

电路原理图如图2-2所示,此方案用运放构成比较器对电池两端的电压进行控制。

图2-2 方案二原理图

电路运行分析:单片机的DA输出接运放的同相端5,与运放的反相端6进行比较,当电池两端的电压过高时,6脚的电压比5脚高,比较器输出将三极管的拉低,使电池两端电压降低;当电池两端电压偏低时,6脚的电压比5脚低,比较器输出将复合管抬

3

湖北师范学院物理与电子科学学院2014届学士学位论文

高,使电池两端的电压升高。这样闭环控制使电池两端的电压维持不变,通过电压和电流检测的软件反馈可以调整DA输出。

方案三:

恒流源方案,采用硬件闭环控制方案。硬件闭环稳流的典型电路如图2-3所示,根据集成运算放大器的特性,可计算得:式中为负载电流,R1为取样电阻,为运算放大器同相端输入信号。若固定R1,则完全由决定,此时无论VCC或是RL发生变化,利用反馈环路的自动调节作用,都能使保持稳定。这样就可保证恒流源具有良好的线性关系。

图2-3 恒流源产生电路

对比三个方案可知,方案三更为合理,并且控制更为简单,方案三直接通过硬件闭环控制,使电池两端的电流恒定。方案二虽然能控制电流平衡,但是对AD的精度要求比较高,这样就没有硬件闭环控制实现恒流的方案好。方案一的TL431相对方案二中的运放来说,最大电压的范围就受限制了,所以此方案不是很好。最终选择方案三。

2.2.3系统设计总体框图

系统设计框图如图2-4所示。智能充电器采用单片机作为主控芯片,主要包括电源电路、恒流恒压电路[6]、键盘响应电路以及状态显示电路。

4

湖北师范学院物理与电子科学学院2014届学士学位论文

外接电源直流12V恒流恒压电路PWM键盘电路电压检测电池MCU显示电路I/O接口图2-4 系统框图

ADC电流检测采样电阻

5

3.1总体电路设计

3. 硬件电路设计

3.2.1单片机最小系统

3.2硬件功能模块分析

按键模块、LED显示模块和数码管显示模块。

图3-1 硬件电路图

湖北师范学院物理与电子科学学院2014届学士学位论文

根据图3-1,设计出如图所示的硬件电路,完整硬件电路包括以下几个模块:系统

电源模块[7]、以单片机STC12C5A60S2为控制核心的单片机最小系统、恒流恒压源模块、

图3-2单片机最小系统

6

片机相媲美。

3.2.2系统电源模块

3.2.3恒流恒压源模块

图3-3系统电源模块

ICL7660[10]。LM7805是三端稳压芯片,可以给运放提供负电压。

湖北师范学院物理与电子科学学院2014届学士学位论文

PWM功能,有足够的I/O口及内部定时器,都可以拿来实现这个方案,我采用的是

单片机最小系统不仅仅包括核心芯片STC12C5A60S2,还包括复位电路、晶振时

10位A/D转换(250K/S,即25万次每秒)等,资源丰富、性价比高,可以和AVR单

钟电路,单片机最小系统如图3-2所示。对于单片机的选择,只要它具备ADC功能和

STC12C5A60S2单片机,该单片机单时钟/机器周期(1T),有2路PWM[8],8路高速

如图3-3所示。系统电源模块包括给单片机供电模块,用到芯片LM7805[9]和

图3-4恒流恒压源模块

7

湖北师范学院物理与电子科学学院2014届学士学位论文

如图3-4所示。该电路是经典的串联型稳压电路,以稳压管稳压电路为基础,利用晶体管的电流放大作用,增大负载电流;在电路中引入深度负反馈使输出电压稳定;并且通过一路PWM对输出电压值进行设定,使输出电压可调,通过另一路PWM对输出电流值进行设定,使输出电流可调。如图3-4所示,电压值设定和电流值设定为两路PWM信号,在PWM信号频率不变的情况下,通过调节PWM脉冲占空比,便可改变设定值。对于电池两端电压检测,电池电压值为电池正极电压减去负极电压;对于电流值检测,由于本方案的采样电阻为0.1?,即使经过500mA大电流时,采样电阻两端电压也才50mV,没有充分利用ADC的转换精度,不利于电流检测的准确性,所以必须对采样电阻两端的电压值进行线性放大。

3.2.4按键模块

图3-5 按键模块

按键模块如图3-5所示,通过按键对最大电压最大电流进行设置,控制电池的最大充电电流和最大充电电压。

3.2.5数码管显示模块

8

用完全,减少成本。

湖北师范学院物理与电子科学学院2014届学士学位论文

图3-6数码管显示电路

电池的电压和工作电流。数码管驱动直接用IO口驱动,这样单片机多余的IO口可以利

数码管显示模块如图3-6所示。数码管显示充电器的最大充电电压、最大充电电流、

9

湖北师范学院物理与电子科学学院2014届学士学位论文

4. 系统软件设计

4.1主程序流程图

主程序流程图如图4-1所示,包含两个部分,一部分为初始化段,另一部分为循环主体段。在主程序循环体中,并不是直接执行程序,而是去调用一个个任务模块。每个任务都是一个子函数,这些任务的调度机制为轮询机制。即:这些子函数功能的执行与否取决于其条件标志是否满足。比如:当某个子函数被主程序调用时,会先判断其执行条件是否成立(标志位是否有效),如果有效则执行实际功能语句,否则不执行任何动作直接返回。为了避免各个任务为了抢占系统CPU资源,造成时间冲突,我采取以下一些措施:根据任务的轻重缓急分别给予以不同的时间调度。比如LCD显示2ms扫描一个,8个数码管扫描频率为62Hz,经调试扫描频率太慢了会数码管会闪,这个频率刚好[10]。PWMD/A调节和A/D采样速度不宜太快,我用的是200ms调用一次,因为它会影响到数码管刷屏,调节和采样太快,数码管上的数值会跳变的厉害。按键处理则为10ms调用一次,当按键处理中,当首次检测到按键闭合时,本来需要20ms左右的延时时间来进行消除抖动,这里如果用延时程序delay(20ms)来实现,则会影响其他任务的执行。应该把这个等待时间让给其他任务程序去执行。具体方法是可以先设置个标志后退出,待下次到了20ms再次进入按键处理程序,再做一个闭合检测。一个任务执行过程中,不能影响其它任务的执行,一旦一个任务执行完成,就立刻释放对CPU的控制权。

上电初始化程序主程序2mS定时处理程序10mS定时处理程序20mS定时处理程序主程序流程图

10

湖北师范学院物理与电子科学学院2014届学士学位论文 2mS定时处理程序10mS定时处理程序200mS定时处理程序N2mS溢出标志=1?Y2mS溢出标志=0N10mS溢出标志=1?Y10mS溢出标志=0N200mS溢出标志=1?Y200mS溢出标志=0LCD显示RET2mS定时处理程序流程图LCD显示RET10mS定时处理程序流程图LCD显示RET200mS定时处理程序流程图

图4-1 主程序流程图

4.2数码管显示模块

将数码管各显示状态化分13种状态,给每个状态编号: //工作模式 WK_MODE

//WK_MODE=0 充电时,电压值电流值显示 //WK_MODE=1 设定时,电压值闪烁,电流值不闪烁 //WK_MODE=2 设定时,电流值闪烁,电压值不闪烁 //WK_MODE=3 设定时,电压值第一位闪烁 //WK_MODE=4 设定时,电压值第二位闪烁 //WK_MODE=5 设定时,电压值第三位闪烁 //WK_MODE=6 设定时,电压值第四位闪烁 //WK_MODE=7 设定时,电流值第一位闪烁 //WK_MODE=8 设定时,电流值第二位闪烁 //WK_MODE=9 设定时,电流值第三位闪烁 //WK_MODE=10 设定时,电流值第四位闪烁 //WK_MODE=11 设定时,电压值电流值显示 //WK_MODE=12 设定时,电压值电流值显示

11

湖北师范学院物理与电子科学学院2014届学士学位论文

4.3定时器模块

//计数寄存器

unsigned char JSQ_2MS;//2ms计数器 unsigned char JSQ_10MS;//10ms计数器 unsigned char JSQ_200MS;//200ms计数器 unsigned char JSQ_500MS;//500ms计数器 //标志位

bit JS2MS_F;//计时5ms标志位 bit JS10MS_F;//计时10ms标志位 bit JS500MS_F;//计时50ms标志位 bit JS200MS_F;//计时200ms标志位

设定系统时钟任务时基1ms。比如:1ms 到,在中断服务函数 JSQ_2MS++;//计数器计数 If(JSQ_2MS>1) //2ms到 {

JSQ_2MS=0;//计数器清零 JS2MS_F=1;//计时2ms标志位置1 }

任务模块通过查询相应标志位执行相应任务,没到2ms退出释放CPU控制权;到了2ms进入,获得CPU使用权;一旦任务执行完,立即释放CPU控制权。这样CPU工作效率很高。

4.4按键处理器模块

常见按键处理是应该掌握的一项基本功。单击;短击+长击;短击+连击。主要目的是通过按键对最大电压值和最大电流值进行设定。相应按键按下,执行相应功能或者迁移到新的状态。

sbit Key_Dec=P3^2;//减键,支持短击+连击 sbit Key_Left=P3^3;//左移键,支持单击

12

湖北师范学院物理与电子科学学院2014届学士学位论文

sbit Key_Set=P3^4;//设定键,支持短击+长击 sbit Key_Right=P3^5;//右移键,支持单击 sbit Key_Add=P3^6;//加键,支持短击+连击

4.5 ADC采样和PWM模块

直接调用STC12C5A60S2系列单片机手册里的现成函数。 4.6充电过程处理模块

充电过程处理模块如图4-2所示,空闲状态,不进行电池充电的功作,主要任务是对电池接入识别,绿灯闪烁。预充状态,电池以最大设置电流的五分之一充电,充电三分钟,自动跳转快充状态,红灯亮。快充状态用PWM方式控制充电电流和电压,也就是根据A/D口采样到的电压和电流反馈,通过调节占空比来调节充电电流和电压,红灯亮。恒压状态快充状态下,充电电压大于4.2V时,跳转到恒压状态。此时给电池4.2V充电,红灯亮。停充状态恒压状态下,I<1/5最大电流时,停止充电,绿灯亮。故障状态空闲状态下,当电池两端电压大于4.2V时,停止充电,红灯闪烁。预充状态三分钟后,当电池两端电压大于4.2V时,停止充电,红灯闪烁。

上电初始化空闲状态电池接入V<4.2VV>4.2V预充状态预充3分钟电池取下故障状态快充状态V>4.2V恒压状态V>4.0VI<1.0C停充状态

图4-2 充电过程处理模块

13

湖北师范学院物理与电子科学学院2014届学士学位论文

5. 系统实物调试和效果

5.1实物调试和效果

焊接好的实物如图5-1所示。板子打烊回来之后,就开始检测板子打烊的时候有没有问题,电源和地有没有短路,这些都检查好没问题之后就开始焊接板子了。开始焊的是最小系统,焊好之后,接上下载线,程序能够下载进去。

图5-1 焊接完成的实物图

充电之前电池电压为3.836V,如图5-2所示。

图5-2 充电之前的电池电压

系统上电如图5-3所示。

图5-3 系统上电图

14

湖北师范学院物理与电子科学学院2014届学士学位论文

充满电之后电池电压为4.217V,如图5-4所示。

图5-4 充满电之后电池电压

5.2改善措施

调试成功,不过还是有不足的地方,就是场效应管的散热问题,场效应管用的是贴片,贴在PCB板子的背面,当场效应管一直工作在恒流充电的时候就会发热,工作一段时间久发热很厉害,上面的焊锡在高温下也就起不了什么作用了,第一块板子因为发热的原因,场效应管移动了,漏极和数码管的的一个接单片机P01口的脚碰了一下,此时的漏极电压为11V左右,P01口烧坏了,用示波器看,使P01=0,此时的波形电压为3.5V,P01口不能输出低电平,数码管的b段时刻亮着的。最后就重新焊了一块,没有换单片机了,第一次焊的时候调试把板子搞得也不像个样子。电池没充几分钟这个场效管就掉下来了,所以要想成为一个真正的产品,硬件上必须解决的就是散热问题。

可以用开关电源的原理来解决这个散热问题。

15

湖北师范学院物理与电子科学学院2014届学士学位论文

6. 总结与展望

本论文描述了锂离子电池快速充电过程的基本原理,设计了对单节4.2V锂离子电池充电的充电器,它能够快速完成锂离子电池的充电过程。根据对锂离子电池的充放电特性和充电控制方法的分析得出:锂离子电池充电器常采用三段充电法,即预处理、恒流充电(快充)和恒压充电(充满)。开始以设定的恒流充电,锂离子电池的电压以较高的斜率增长,在充电过程中斜率逐步降低,充到接近4.2V时,恒流充电阶段结束,接着以4.2V恒压充电。在恒压阶段充电时,电压几乎不变(或稍有增加),充电电流不断下降。当充电速率下降到0.1C时,表示电池已充满,应终止充电。没有及时终止的话,此后最明显的特征是电池温度升高,发热,在整个快充电过程中都应当注意电池的温度,尤其是过充电时,锂离子电池温度过高,会造成过热而损坏电池或发生爆炸。在锂离子电池进入恒压充电状态前,必须适时停止快速充电。为此,设计了此种锂离子电池快速充电器, 利用快速充电的方法,并在此基础之上进行电压、温度的检测和控制来保证该充电器能对锂离子电池进行安全可靠而又快速的充电。本电路具有温度保护功能,当电池温度过高时, 即刻停止快速充电,这样就能避免过充电对锂离子电池造成的损害.

根据锂离子电池的充电特性可知,锂电池或充电器在电池充满后应当停止充电,并不存在镍电充电器所谓的持续10几小时的“涓流”充电。也就是说,如果你的锂电池在充满后,放在充电器上也是白充,反而会造成内压升高、电池发热等现象,而我们谁都无法保证电池的充放电保护电路的特性永不变化和质量的万无一失,所以电池将长期处在危险的边缘徘徊。这也是本次设计中当充满电后自动断开充电的一个理由。

此外,不可忽视的另外一个方面就是锂电池同样也不适合过放电,过放电对锂电池同样也很不利。

目前一些大的厂家生产的手机充电器都具有以下特点:宽范围AC输入或多个电压可选;具备限流保护,电流短路与反充保护线路设计;体积小、重量轻;自动、快速充电,充满电后自动关断等等。另外,有的充电器还有自动识别锂离子、镍氢、镍镉电池组;自动计算电池的已充电量和剩余的充电时间,也可以改变参数来适应各种不同电池的充电;具有放电功能;LED 或LCD充电状态显示;低噪声;模拟微电脑控制系统等特点。

因此,设计一款真正由微电脑控制单片机控制,且价格低廉的智能控制充电器,成为各厂家努力的方向。

16

湖北师范学院物理与电子科学学院2014届学士学位论文

7. 参考文献

[1] 周志敏,周纪海,纪爱华.充电器电路设计与应用(第1版)[M].北京:人民邮电出版

社,2005,10: 54~62.

[2] 康华光.电子技术基础数字部分(第五版)[M].北京:高等教育出版社,2005: 103~125. [3] 杨欣,王玉凤.电路设计与仿真[M].北京:清华大学出版社,2005: 77~84. [4] 李建忠.单片机原理及运用[J].西安:西安电子科技大学出版社,2003: 22~25.

[5] 何立民.MCS-51系列单片机应用系统设计系统配置与接口技术[M].北京:北京航空航

天大学出版社,1990.3: 46~70.

[6] 谭浩强.C语言程序设计第三版[M].北京:清华大学出版社,2005: 55~68.

[7] 张家怡.图像识别的技术现状和发展趋势[J].电脑知识与技术,2010,16(21): 6045-6046. [8] Gary Bradski Adrian Kaehler,于仕琪,刘瑞被.学习OpenCV(中文版)[M].北京:清华大学

出版社,2009: 1-14.

[9] 靳艳红.一种基于Canny算子改进的边缘检测算法[J].重庆文理学院学报(自然科学

版),2011,30(2): 27-30.

[10] 杨碧石,陈兵飞.ICL7660/7662变极性DC-DC变换器的原理与应用[J].国外电子元器

件,2003.2: 51-52.

17

致谢

论文在选题及研究过程中得到潘言全老师的悉心指导。感谢潘老师给我提供了宝贵的学习机会和良好的科研环境。感谢潘老师在我做实验期间及撰写论文期间给我提供宝贵建议,并为我指点迷津,帮助我开拓思路。潘老师治学严谨、实事求是、兢兢业业,这种做事的态度让我终生受益无穷。也感谢给予我帮助的其他老师和好友。

我会带着这份求学精神,带着老师和同学们寄予我的厚望,好好地把握机会,在以后的生活、工作岗位上发挥自己最大的优势,实现自己的人生价值。

最后,感谢在百忙之中抽出时间为我评阅论文的诸位前辈和专家!

附录:

//--------------------------------------------------------------------- //项目:智能电池充电器的设计

//说明:1.该项目使用的CPU是STC12C5A60S2,晶振22.1184MHz // 2.可通过按键设置充电最大电压,充电最大电流

// 3.对于充电过程智能化,无须人为操作,充满后自动停止充电

// 4.充电器处于空闲状态时绿灯闪烁,充电状态时红灯亮,充电停止时绿灯亮

// 用户可通过灯的显示状态,识别充电的过程

//--------------------------------------------------------------------- #include\

#include\#include\#include\#include\#include\#include\

extern bit JS2MS_F;//计时1ms标志位 extern bit JS10MS_F;//计时10ms标志位 extern bit JS200MS_F;//计时200ms标志位 extern unsigned char ch;//A/D通道选择

extern unsigned char Charge_Mode;//充电状态

extern unsigned char WK_MODE;//设定系统工作模式

extern unsigned char PWM0_TEMP = 179,PWM1_TEMP = 127;//PWM脉冲占空比设定

//2ms处理程序

void DS2MS_CNT(void) {

if( JS2MS_F )//2ms到 {

JS2MS_F = 0; //标志位清零 New_Display();//待显示字符串 Display_Lcd();//LCD显示 } }

//10ms处理程序

void DS10MS_CNT(void) {

if( JS10MS_F ) //10ms到 {

JS10MS_F = 0;//标志位清零 KEYSCAN(); //按键处理 }

}

//200ms处理程序

void DS200MS_CNT(void) {

if( JS200MS_F )//200ms到 {

JS200MS_F = 0;//标志位清零

ADC_CONTR = ADC_POWER|ADC_SPEEDLL|ADC_START|ch; //启动A/D采样 Charge_Pro(); //充电过程处理

PWM_DAC( PWM0_TEMP,PWM1_TEMP ); //PWMD/A调节 } }

//主程序

void main(void) {

Timer0_Init();//定时器初始化 PWM_Init();//PWMD/A初始化 Adc_Init();//A/D采样初始化

IE |= 0XA0;//开总中断和开ADC中断 Charge_Mode = 0;//充电状态初始化 WK_MODE = 0;//设定系统工作模式 while(1) {

DS2MS_CNT();//2ms定时处理 DS10MS_CNT();//10ms定时处理 DS200MS_CNT();//200ms定时处理 } }

//定时器模块(晶振22.1184MHz,12分频) #include\#include\//计数寄存器

unsigned char JSQ_2MS;//2ms计数器 unsigned char JSQ_10MS;//10ms计数器 unsigned char JSQ_500MS;//500ms计数器 unsigned char JSQ_200MS;//200ms计数器 unsigned int JSQ_3MINUTE;//3分钟计数器 //标志位

bit JS2MS_F;//计时5ms标志位 bit JS10MS_F;//计时10ms标志位 bit JS500MS_F;//计时50ms标志位 bit JS200MS_F;//计时200ms标志位 bit JS3MINUTE_F;//计时3分钟标志位 bit Flag_S;//闪烁标志位,闪烁频率2HZ

bit LED_Flag_S;//LED闪烁标志位,闪烁频率2HZ extern bit Key_Scan_F;//计时10ms标志位 //定时器0初始化,设定时基1ms;

//定时器1初始化,设定时基20ms(专供预充电定时3分钟,便于控制) void Timer0_Init(void) {

TMOD = 0X11;//定时器0和定时器1工作在模式1,16Bit定时器模式 TH0 = 255-CLOCK/TIMER0_PER_SEC/12/256;//时基频率1000HZ TL0 = 255-CLOCK/TIMER0_PER_SEC/12%6; TR0 = 1;//启动 ET0 = 1;//允许中断

TH1 = 255-CLOCK/TIMER1_PER_SEC/12/256;//时基频率50HZ TL1 = 255-CLOCK/TIMER1_PER_SEC/12%6; TR1 = 0;//不启动 ET1 = 1;//允许中断 }

//定时器0溢出中断服务函数 void Timer0(void)interrupt 1 {

TH0 = 255-CLOCK/TIMER0_PER_SEC/12/256;//重装 TL0 = 255-CLOCK/TIMER0_PER_SEC/12%6; JSQ_2MS++; JSQ_10MS++;

if( JSQ_2MS>1 )//2ms到 { JSQ_2MS = 0; JS2MS_F = 1; }

if(JSQ_10MS>9)//10ms到 { JSQ_10MS=0; JS10MS_F = 1; Key_Scan_F = 1; JSQ_500MS++; JSQ_200MS++;

if( JSQ_200MS>19 )//200ms到 {

JSQ_200MS = 0; JS200MS_F = 1; }

if( JSQ_500MS>49 )//500ms到 { JSQ_500MS = 0; JS500MS_F = 1;

Flag_S =~ Flag_S;//数码管闪烁标志位取反

LED_Flag_S =~ LED_Flag_S;//LED闪烁标志位取反 } } }

//定时器1溢出中断服务函数 void Timer1(void)interrupt 3 {

TH1=255-CLOCK/TIMER1_PER_SEC/12/256;//重装 TL1=255-CLOCK/TIMER1_PER_SEC/12%6; JSQ_3MINUTE++;

if(JSQ_3MINUTE>8999)//3分钟到 { JSQ_3MINUTE=0; JS3MINUTE_F=1; } }

//数码管显示模块 //工作模式 WK_MODE

//WK_MODE=0 充电时,电压值电流值显示

//WK_MODE=1 设定时,电压值闪烁,电流值不闪烁 //WK_MODE=2 设定时,电流值闪烁,电压值不闪烁 //WK_MODE=3 设定时,电压值第一位闪烁 //WK_MODE=4 设定时,电压值第二位闪烁 //WK_MODE=5 设定时,电压值第三位闪烁 //WK_MODE=6 设定时,电压值第四位闪烁 //WK_MODE=7 设定时,电流值第一位闪烁 //WK_MODE=8 设定时,电流值第二位闪烁 //WK_MODE=9 设定时,电流值第三位闪烁 //WK_MODE=10 设定时,电流值第四位闪烁 //WK_MODE=11 设定时,电压值电流值显示 //WK_MODE=12 设定时,电压值电流值显示 #include\

#include%unsigned char table_d[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff};//段码值

unsigned char table_w[] = {0xf7,0xfb,0xfd,0xfe,0x7f,0xbf,0xdf,0xef};//位选值 //显缓区

unsigned char Disp_Queue[8];//待显示字符队列

extern unsigned int MCU_ADC0,MCU_ADC1;//通道0电压值,通道1电压值 unsigned int Voltage_Val,Current_Val;//电压值,电流值

extern unsigned int Voltage_Max,Current_Max;//设定最大电压值,最大电流值 char voltage_q,voltage_b,voltage_s,voltage_g;//最大电压值第一位,第二位,第三位,第四位

char current_q,current_b,current_s,current_g;//最大电流值第一位,第二位,第三位,第四位

unsigned char WK_MODE;//设定系统工作模式

extern bit Flag_S;//闪烁标志位,闪烁频率500HZ extern unsigned char PWM0_TEMP,PWM1_TEMP; //反馈数据处理

void BackData_Pro( unsigned int Voltage_V,unsigned int Current_V ) {

Voltage_Val=

(long)(Voltage_V)*5*1000/256-(long)Current_V*5*1000/256/21-70; Current_Val = (float)(Current_V)*5*1000/256.0/2.1; }

//设定数据处理

void SetData_Pro( unsigned int voltage_set,unsigned int current_set ) {

voltage_q = voltage_set/1000; voltage_b = voltage_set00/100; voltage_s = voltage_set0/10; voltage_g = voltage_set; current_q = current_set/1000; current_b = current_set00/100; current_s = current_set0/10; current_g = current_set; }

//刷新待显示字符串 void New_Display(void) {

BackData_Pro( MCU_ADC0,MCU_ADC1 );

SetData_Pro( Voltage_Max,Current_Max ); switch( WK_MODE ) {

case 0://充电时,电压值电流值显示

Disp_Queue[0] = Voltage_Val/1000+10 ; Disp_Queue[1] = Voltage_Val00/100 ; Disp_Queue[2] = Voltage_Val0/10; Disp_Queue[3] = Voltage_Val; Disp_Queue[4] = Current_Val/1000+10; Disp_Queue[5] = Current_Val00/100 ; Disp_Queue[6] = Current_Val0/10;; Disp_Queue[7] = Current_Val; break;

case 1://设定时,电压值闪烁,电流值不闪烁 if( Flag_S )//灭 {

Disp_Queue[0] = 20; Disp_Queue[1] = 20; Disp_Queue[2] = 20; Disp_Queue[3] = 20; }

else //亮 {

Disp_Queue[0] = voltage_q+10; Disp_Queue[1] = voltage_b; Disp_Queue[2] = voltage_s; Disp_Queue[3] = voltage_g; }

Disp_Queue[4] = current_q+10; Disp_Queue[5] = current_b; Disp_Queue[6] = current_s; Disp_Queue[7] = current_g; break;

case 2: //设定时,电流值闪烁,电压值不闪烁 if( Flag_S ) {

Disp_Queue[4] = 20; Disp_Queue[5] = 20; Disp_Queue[6] = 20; Disp_Queue[7] = 20; } else {

Disp_Queue[4] = current_q+10; Disp_Queue[5] = current_b; Disp_Queue[6] = current_s; Disp_Queue[7] = current_g; }

Disp_Queue[0] = voltage_q+10; Disp_Queue[1] = voltage_b; Disp_Queue[2] = voltage_s; Disp_Queue[3] = voltage_g; break;

case 3://设定时,电压值第一位闪烁 if( Flag_S ) {

Disp_Queue[0] = 20; } else {

Disp_Queue[0] = voltage_q+10; }

Disp_Queue[1] = voltage_b; Disp_Queue[2] = voltage_s; Disp_Queue[3] = voltage_g;

Disp_Queue[4] = current_q+10; Disp_Queue[5] = current_b; Disp_Queue[6] = current_s; Disp_Queue[7] = current_g; break;

case 4://设定时,电压值第二位闪烁 if( Flag_S ) {

Disp_Queue[1] = 20; } else {

Disp_Queue[1] = voltage_b; }

Disp_Queue[0] = voltage_q+10; Disp_Queue[2] = voltage_s; Disp_Queue[3] = voltage_g; Disp_Queue[4] = current_q+10; Disp_Queue[5] = current_b; Disp_Queue[6] = current_s; Disp_Queue[7] = current_g; break;

case 5://设定时,电压值第三位闪烁 if( Flag_S ) {

Disp_Queue[2] = 20; } else {

Disp_Queue[2] = voltage_s; }

Disp_Queue[0] = voltage_q+10; Disp_Queue[1] = voltage_b; Disp_Queue[3] = voltage_g; Disp_Queue[4] = current_q+10; Disp_Queue[5] = current_b; Disp_Queue[6] = current_s;

Disp_Queue[7] = current_g; break;

case 6: //设定时,电压值第四位闪烁 if( Flag_S ) {

Disp_Queue[3] = 20; } else {

Disp_Queue[3] = voltage_g; }

Disp_Queue[0] = voltage_q+10; Disp_Queue[1] = voltage_b; Disp_Queue[2] = voltage_s; Disp_Queue[4] = current_q+10; Disp_Queue[5] = current_b; Disp_Queue[6] = current_s; Disp_Queue[7] = current_g; break;

case 7://设定时,电流值第一位闪烁 if( Flag_S ) {

Disp_Queue[4] = 20; } else {

Disp_Queue[4] = current_q+10; }

Disp_Queue[5] = current_b; Disp_Queue[6] = current_s; Disp_Queue[7] = current_g; Disp_Queue[0] = voltage_q+10; Disp_Queue[1] = voltage_b; Disp_Queue[2] = voltage_s; Disp_Queue[3] = voltage_g; break;

case 8://设定时,电流值第二位闪烁 if( Flag_S ) {

Disp_Queue[5] = 20; } else {

Disp_Queue[5] = current_b;

}

Disp_Queue[4] = current_q+10; Disp_Queue[6] = current_s; Disp_Queue[7] = current_g; Disp_Queue[0] = voltage_q+10; Disp_Queue[1] = voltage_b; Disp_Queue[2] = voltage_s; Disp_Queue[3] = voltage_g; break;

case 9: //设定时,电流值第三位闪烁 if( Flag_S ) {

Disp_Queue[6] = 20; } else {

Disp_Queue[6] = current_s; }

Disp_Queue[4] = current_q+10; Disp_Queue[5] = current_b; Disp_Queue[7] = current_g; Disp_Queue[0] = voltage_q+10; Disp_Queue[1] = voltage_b; Disp_Queue[2] = voltage_s; Disp_Queue[3] = voltage_g; break;

case 10://设定时,电流值第四位闪烁 if( Flag_S ) {

Disp_Queue[7] = 20; } else {

Disp_Queue[7] = current_g; }

Disp_Queue[4] = current_q+10; Disp_Queue[5] = current_b; Disp_Queue[6] = current_s; Disp_Queue[0] = voltage_q+10; Disp_Queue[1] = voltage_b; Disp_Queue[2] = voltage_s; Disp_Queue[3] = voltage_g; break;

case 11: //设定时,电压值电流值显示

Disp_Queue[0] = voltage_q+10; Disp_Queue[1] = voltage_b; Disp_Queue[2] = voltage_s; Disp_Queue[3] = voltage_g; Disp_Queue[4] = current_q+10; Disp_Queue[5] = current_b; Disp_Queue[6] = current_s; Disp_Queue[7] = current_g; break;

case 12://设定时,电压值电流值显示

Disp_Queue[0] = voltage_q+10; Disp_Queue[1] = voltage_b; Disp_Queue[2] = voltage_s; Disp_Queue[3] = voltage_g; Disp_Queue[4] = current_q+10; Disp_Queue[5] = current_b; Disp_Queue[6] = current_s; Disp_Queue[7] = current_g; break; default:

break; } }

//LCD显示函数(扫描频率62.5HZ) void Display_Lcd(void) {

static unsigned char i=0; P0=table_d[Disp_Queue[i]]; P2=table_w[i]; i = ++i & 0x07; }

//按键处理模块,支持短击,长击,连击 #include\#include\

//按键检测程序标志位定义

bit Key_Scan_F ;//按键检测使能标志位 bit Key_Dis_F ;//按键禁止响应 bit Flag_Left;//左移键按下标志位 bit Flag_Right;//右移键按下标志位 bit Flag_Add; //加键按下标志位 bit Flag_Dec; //减键按下标志位 //按键检测程序寄存器定义

unsigned char Key_Num ; //本次键码

unsigned char Key_Backup; //备份键码

unsigned char K_ADD_DELAY = AN_XD_DL ;//按键响应延时时间(倒计时器),服务于连按

unsigned char K_DEC_DELAY = AN_XD_DL ;//按键响应延时时间(倒计时器),服务于连按

//unsigned char NOKEY_JSQ;//无键计时器 unsigned char KEY_JSQ;//按键闭合计数器

extern unsigned char WK_MODE;//系统设定工作模式

extern char voltage_q,voltage_b,voltage_s,voltage_g;//最大电压值第一位,第二位,第三位,第四位

extern char current_q,current_b,current_s,current_g;//最大电流值第一位,第二位,第三位,第四位

extern unsigned int Voltage_Max,Current_Max;//最大电压值,最大电流值 extern unsigned char Disp_Queue[8];//显缓区 //执行系统设定键长击操作函数 void Key_Cj_Action(void) {

switch( WK_MODE ) { case 0:

WK_MODE = 1; break; case 11:

WK_MODE = 2; break; case 12:

WK_MODE = 0; break; } }

// 执行系统设定键短击操作函数 void Key_Dj_Action(void) {

switch( WK_MODE ) {

case 1:

WK_MODE = 3; break; case 2:

WK_MODE = 7; break; case 3:

WK_MODE = 11; break;

case 4:

WK_MODE = 11; break; case 5:

WK_MODE = 11; break; case 6:

WK_MODE = 11; break; case 7:

WK_MODE = 12; break; case 8:

WK_MODE = 12; break; case 9:

WK_MODE = 12; break; case 10:

WK_MODE = 12; break; default:

break; } }

//右移键执行函数

void Key_Right_Action(void) {

switch( WK_MODE ) {

case 3:

WK_MODE = 4; break; case 4:

WK_MODE = 5; break; case 5:

WK_MODE = 6; break; case 6:

WK_MODE = 3; break; case 7:

WK_MODE =8 ;

break; case 8:

WK_MODE = 9; break; case 9:

WK_MODE = 10; break; case 10:

WK_MODE = 7; break; default:

break; } }

//左移键执行函数

void Key_Left_Action(void) {

switch( WK_MODE ) { case 3:

WK_MODE = 6; break; case 4:

WK_MODE = 3; break; case 5:

WK_MODE = 4; break; case 6:

WK_MODE = 5; break; case 7:

WK_MODE = 10; break; case 8:

WK_MODE = 7; break; case 9:

WK_MODE = 8; break; case 10:

WK_MODE = 9; break; default:

break; } }

//加键执行函数

void Key_Add_Action(void) {

switch( WK_MODE ) {

case 3:voltage_q++;

if(voltage_q>9)voltage_q=0;

Voltage_Max= voltage_q*1000+voltage_b*100+voltage_s*10+voltage_g; break;

case 4:voltage_b++;

if(voltage_b>9)voltage_b=0;

Voltage_Max= voltage_q*1000+voltage_b*100+voltage_s*10+voltage_g; break;

case 5:voltage_s++;

if(voltage_s>9)voltage_s=0;

Voltage_Max= voltage_q*1000+voltage_b*100+voltage_s*10+voltage_g; break;

case 6:voltage_g++;

if(voltage_g>9)voltage_g=0;

Voltage_Max= voltage_q*1000+voltage_b*100+voltage_s*10+voltage_g; break;

case 7:current_q++;

if(current_q>9)current_q=0;

Current_Max= current_q*1000+current_b*100+current_s*10+current_g; break;

case 8:current_b++;

if(current_b>9)current_b=0;

Current_Max= current_q*1000+current_b*100+current_s*10+current_g; break;

case 9:current_s++;

if(current_s>9)current_s=0;

Current_Max= current_q*1000+current_b*100+current_s*10+current_g; break;

case 10:current_g++;

if(current_g>9)current_g=0;

Current_Max= current_q*1000+current_b*100+current_s*10+current_g; break; default:

break; } }

//减键执行函数

void Key_Dec_Action(void) {

switch(WK_MODE) {

case 3:voltage_q--;

if( voltage_q<0 )voltage_q = 9;

Voltage_Max= voltage_q*1000+voltage_b*100+voltage_s*10+voltage_g; break;

case 4:voltage_b--;

if( voltage_b<0 )voltage_b = 9;

Voltage_Max= voltage_q*1000+voltage_b*100+voltage_s*10+voltage_g; break;

case 5:voltage_s--;

if( voltage_s<0 )voltage_s = 9;

Voltage_Max= voltage_q*1000+voltage_b*100+voltage_s*10+voltage_g; break;

case 6:voltage_g--;

if( voltage_g<0 )voltage_g = 9;

Voltage_Max=voltage_q*1000+voltage_b*100+voltage_s*10+voltage_g; break;

case 7:current_q--;

if( current_q<0 )current_q = 9;

Current_Max= current_q*1000+current_b*100+current_s*10+current_g; break;

case 8:current_b--;

if( current_b<0 )current_b = 9;

Current_Max= current_q*1000+current_b*100+current_s*10+current_g; break;

case 9:current_s--;

if( current_s<0 )current_s = 9;

Current_Max= current_q*1000+current_b*100+current_s*10+current_g; break;

case 10:current_g--;

if( current_g<0 )current_g = 9;

Current_Max= current_q*1000+current_b*100+current_s*10+current_g; break; default:

break;

} }

//按键扫描

void KEYSCAN(void)

{

if( Key_Scan_F )//10ms到按键检测使能 { Key_Scan_F = 0;//按键使能标志位清零 Key_Num = P3&0X7C;//读键值

/************************系统设定键******************************/ if( ( !Key_Set )&&( Key_Num == Key_Backup) )//如果设定键按下 {

if( !Key_Dis_F )//按键操作示响应 {

KEY_JSQ++; //按键闭合计数器加1

if( KEY_JSQ >= AN_CJ_DL )//判定系统设定键长击 {

KEY_JSQ = 0;//闭合计数器清零 Key_Cj_Action();//执行散转函数 Key_Dis_F = 1;//按键禁止响应 } } }

else //松开或键值变化 {

if( ( !Key_Dis_F )&&( KEY_JSQ>=AN_XD_DL )&&( KEY_JSQ <= AN_CJ_DL ) )//系统设定键短击 {

KEY_JSQ = 0;

Key_Dj_Action(); Key_Dis_F = 1; }

Key_Backup = Key_Num; //重新记录键值 Key_Dis_F = 0; }

if( ( ( !Key_Right )||( !Key_Left ) )&&( Key_Num == Key_Backup ) )//左移键或右移键按下,支持短击 {

KEY_JSQ++;

if( ( KEY_JSQ >= AN_XD_DL )&&( !Key_Right ) )//右移键按下 {

KEY_JSQ = 0;

Flag_Right = 1;//右移键按下标志位 }

if( ( KEY_JSQ>=AN_XD_DL )&&( !Key_Left ) )//左移键按下 {

KEY_JSQ = 0;

Flag_Left = 1;//左移键按下标志位

} }

else//松开,短击松开后执行函数 {

if( Flag_Right ) {

Flag_Right = 0; Key_Right_Action(); }

if( Flag_Left ) {

Flag_Left = 0; Key_Left_Action(); }

Key_Backup = Key_Num; //重新记录键值 }

/***************************加键按下***************************/ if( ( !Key_Add )&&( Key_Num == Key_Backup ) ) {

if( ( !( K_ADD_DELAY-- ) )&&( !Key_Add ) ) {

Key_Add_Action();

K_ADD_DELAY = AN_LA_DL; } } else {

Key_Backup = Key_Num; K_ADD_DELAY = AN_XD_DL; }

/**************************减键按下*****************************/ if( ( !Key_Dec )&&( Key_Num == Key_Backup ) ) {

if( ( !( K_DEC_DELAY-- ))&&( !Key_Dec) ) {

Key_Dec_Action();

K_DEC_DELAY = AN_LA_DL; } } else {

Key_Backup = Key_Num; K_DEC_DELAY = AN_XD_DL; }

} }

//A/D模块函数 #include\#include\#include\

unsigned char ch=6; //通道选择

unsigned int MCU_ADC0,MCU_ADC1;//通道0电压值,通道1电压值 //ADC初始化函数 void Adc_Init(void) { P1ASF = 0XC0;//MCU_ADC0(P1.6),MCU_ADC1(P1.7) ADC_RES = 0;//AD转换结果寄存器清零

ADC_CONTR=ADC_POWER|ADC_SPEEDLL|ADC_START|ch; _nop_();//延时 _nop_(); _nop_(); _nop_(); }

//ADC中断服务函数

void Adc_Isr(void) interrupt 5 {

ADC_CONTR &=!ADC_FLAG;//当A/D转换完成后,由软件清零 if(ch==6)//ADC通道0 {

MCU_ADC0=ADC_RES; }

if(ch==7)//ADC通道1 {

MCU_ADC1=ADC_RES; } switch(ch)//ADC通道0和ADC通道1轮番读电压 {

case 6:

ch=7; break; case 7:

ch=6; break; default:

break; } }

//PWMD/A调节模块

本文来源:https://www.bwwdw.com/article/zgz6.html

Top