找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1982|回复: 1
打印 上一主题 下一主题
收起左侧

基于BQ26500电池测量设计论文与源码下载

[复制链接]
跳转到指定楼层
楼主
ID:336398 发表于 2018-5-23 12:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
摘要

锂离子电池与其他种类的电池相比有着诸多优势,已经成为我们日常生活中必不可少的一部分。相信在使用锂离子电池的过程中,我们常会考虑还剩多少电量的问题,但是又找不到好的电量检测方法,针对该要求,本文设计了一种基于单片机的锂离子电池电量检测系统,该检测系统可以满足我们日常生活中对锂离子电池电量检测的需求,以全面掌握锂离子电池的电量状态。
本文主要叙述了基于单片机的锂离子电池电量检测系统的研究和设计,该系统主要由模拟量采集、锂离子电池检测模块、单片机模块、以及LED驱动显示电量等相应的部分组成,介绍了锂离子电池的特点、电池电量检测原理、系统的结构及性能,重点介绍了该系统的软硬件设计等。
考虑到检测系统的复杂程度、精确性、可靠性等各个方面,本文介绍的设计方案能够满足我们对锂离子电池电量检测的要求。随着电力系统电量的日益扩大和电压运行等级的不断提高,传统的电量检测系统暴露出越来越多的缺点,难以满足现代电网向自动化、数字化发展的需要。本文首先概述了系统的设计,LCD显示部分方面的设计。然后介绍了AT89C51和BQ26500中电子接口的各项特性,同时对单元的结构原理和功能划分进行了分析和研究,提出了软件系统方面的设计方案,主程序和子程序的流程方案。
目录

摘要

abstract

1. 绪论

1.1 研究背景

1.2研究意义

1.3 主要研究内容

2. 总体方案设计

2.1方案选择

2.2 LCD显示部分

2.2.1 LCD12864 概述

2.2.2 LCD12864基本用途

2.3  电池电量检测芯片BQ26500

2.3.1 测量原理

2.3.2  电路图设计

2.4  数据传输存储芯片24C64

2.4.1  24C64概述

2.4.2  24C64引脚说明

2.4.3  24C64特性介绍

2.5  时钟芯片DS1302

2.5.1  DS1302概述

2.5.2  DS1302引脚说明

3.软件系统设计            

3.1 C语言简介            

3.2  程序设计流程

3.2.1  初始化

3.2.2  主程序流程图

3.2.3A/D转换与中断服务

3.3  BQ26500总线时序

4.总结

致谢

参考文献

附录



1. 绪论
1.1 研究背景
电池(电池)是指将电解质溶液和金属电极保持在杯、槽、或其他容器或复合容器空间的一部分中产生电流的装置,其将化学能转化为电能。这是一个积极的和消极的观点。随着科学技术的进步,电池通常是指发电的小型设备。比如太阳能电池。电池的性能参数主要包括电动势、容量、比能和电阻。
采用电池作为能源,可获得稳定的电压、稳定的电流、长时间稳定的电源、受外界影响小的电流、电池结构简单、携带方便、充放电操作容易、不受外界气候和温度的影响。RE,稳定可靠的性能,以及在现代社会生活中。所有方面都起着很大的作用,如手机、手表等电子数字便携设备!
额定电压
电池在常温下的典型工作电压也称为标称电压。为选择不同类型的电池提供参考。电池的实际工作电压等于正压电极和负电极的平衡电极电位的差值。它仅与电极中活性物质的类型有关,而与活性物质的量无关。电池电压本质上是直流电压,但在某些特殊条件下,由电极反应引起的金属晶体或某些相膜的相变将引起电压的轻微波动。这种现象被称为噪声。波动幅度很小,但频率范围很宽,因此可以区别于电路中的自激噪声。
开路电压
开路电压下的电池端电压称为开路电压。电池的开路电压等于电池正极电势与负极电极电位在电池开路时的差值(即,没有电流通过两极)。电池的开路电压由V表示,即V开路=++-,其中,++和C分别是电池的正极和负极电位。电池的开路电压通常小于其电动势。这是因为电池两极电解液中的电极电位通常不是一个平衡的电极电位,而是一个稳定的电极电位。通常可以认为,电池的开路电压是电池的电动势。
1.2研究意义
锂离子电池自问世以来,到现在已经发展成为我们每个人众多生活必需品当中的一部分,是如今人们在日常生活中使用极其广泛的一种电池。我国通讯、电力电子等相关行业的飞速发展,使人们对锂离子电池的利用率和维护工作的重视程度不断提高,锂离子电池电量检测的市场需求随之越来越大。然而现在的实际情况却是由于国内目前的一些检测设备的检测方法不精确等原因,使其不能完全满足我们对锂离子电池电量检测的需求,同时国外的同类检测设备虽然性能较好,但是价格太高,不适合我们日常检测使用。微处理器技术的发展与电池电量检测方法的不断改善,为提高锂离子电池电量检测系统的性能和降低其制造成本提供了可能。针对该要求,本文设计了一种基于单片机的锂离子电池电量检测系统,该检测系统的设计对全面掌握锂离子电池的电量状态,提高其利用率具有现实意义。本设计的研究成果如果能够得到大家的一致认同,以致今后被广泛应用于我们的日常生活当中,比如应用于生活中常用的或常见的便携式电子产品领域,这必将提高人们的日常生活质量,并且还能起到提高锂离子电池利用率的作用,从另一方面看,这也是从某种程度上响应了国家“节能减排”政策。
1.3 主要研究内容
该课题是设计一个锂离子电池电量检测系统,研究对象为符合国标GB/T 18287-2000的锂离子电池,其主要参数有:标称电压3.7V,标称容量1050mAH,充电电压4.2V。在做毕业设计的这段时间里,自己通过互联网查询、图书馆书籍资料搜索等多种途径,对该课题的研究内容进行了充分的理解与学习,使我对锂离子电池的电量检测原理,以及一些基于单片机的C程序编写等内容,都有了进一步的了解与掌握。
本课题研究如何设计一个满足我们日常生活要求的锂离子电池电量检测系统,要求适用于日常使用,必须控制成本,并且需要满足精度的要求。本文的设计思路是利用单片机及一些市场上常见的功能芯片,经过综合所有应考虑的重要因素后,最终确定了该检测系统里的一些重要器件类型,其锂离子电池的电量检测部分就选用流行于目前市场上并且较专业的电池电量检测芯片BQ26500,输出部分决定采用LCD输出显示。利用电池电量检测芯片BQ26500,并且数码输出显示我们所需数据的锂离子电池电量检测系统,该系统由模拟量参数采集部分、电量检测部分、中央处理控制部分(单片机)以及LED驱动显示等相应模块组成,前两部分可由BQ26500完成。至此,该基于单片机的锂离子电池电量检测系统的整体框架便已明了。
本文重点介绍了该锂离子电池电量检测系统的硬件设计和软件设计。硬件设计的主要职责就是将系统分割成的各个功能部分组合成一个合理的可行性方案。





2. 总体方案设计2.1方案选择
该系统总体结构可以划分为几个重要部分:锂离子电池模拟量参数采集部分、电量检测部分、中央处理控制部分(单片机)和LED驱动显示部分。每个部分重要器件的选型已经在前面具体说明,将系统总体结构分为以上各部分后,整个系统的工作原理及重要模块等信息便简单明了,系统每个部分都有着其自己重要的责任,只有系统内的每个模块都按其职责正常运行,整个锂离子电池电池检测系统才能正常工作。如图2-1所示,该图为锂离子电池电量检测系统的总体结构框图,其中模拟量参数采集部分负责通过传感器及测量电路等来采集锂离子电池的模拟量参数,这些参数包括锂离子在放电过程中的电流(压)大小、检测到的温度值等相关参数;电量检测部分主要负责依据上部分已经采集到的参数,对锂离子电池的电量进行检测与计算,这两个部分可由BQ26500完成;中央处理控制部分即单片机负责对整个系统进行控制;LCD驱动显示部分负责驱动LCD,并对被测锂离子电池的剩余电量信息进行数码输出显示。
⑴根据设计要求,选择STC89C51单片机为核心控制器件。
⑵A/D转换采用ADC0809实现,与单片机的接口为P1口和P2口的高四位引脚。
⑶将转换结果进行运算,化为测量值。
方案一:
硬件电路设计由6个部分组成:A/D转换电路,STC89C51单片机系统,LCD显示系统、时钟电路、复位电路以及测量电压输入电路。硬件电路设计框图如图所示。
方案二:
硬件电路设计由6个部分组成:A/D转换电路,STC89C51单片机系统,LCD12864显示系统、时钟电路、复位电路以及测量电压输入电路。硬件电路设计框图如图所示。



方案论证:
    两种方案相比较,第二种方案拥有明显优势。首先方案一的功能太过单一,虽然达成了设计任务,但实用性较差,没有实际价值。如果对其进行功能扩展的话,虽然可以解决功能单一的缺陷,但又会由于过多的显示内容而导致由LED数码管构成的显示模块过于复杂,对焊接工作造成困难,同时显示效果一般。反观方案二,在吸取方案一的优点的前提之下,将显示模块升级为LCD12864,这样做就可以弥补方案一中的诸多不足,具有显示内容丰富,编程简单,电路复杂程度低等优势。
    综上所述,方案二是一套更为切实可行的方案。
2.2 LCD显示部分

LCD 12864 外观图

2.2.1 LCD12864 概述
12864 是一种具有4 位/8 位并行、2 线或3 线串行多种接口方式,内部含有国标一级、二级简体 中文字库的点阵图形液晶显示模块;其显示分辨率为128×64, 内置8192 个16*16 点汉字,和128 个16*8 点ASCII 字符 集.利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。可以显示8×4 行16×16 点 阵的汉字. 也可完成图形显示.低电压低功耗是其又一显著特点。由该模块构成的液晶显示方案与同类型的图形点阵液晶 显示模块相比,不论硬件电路结构或显示程序都要简洁得多,且该模块的价格也略低于相同点阵的图形液晶模块。 被测电流信号 ﹝或被测电压信号 ﹞经电流测头1﹝或电压测头2﹞隔离变换,在二次回路形成高精度毫安级跟踪电流,经采样电路3转换为跟踪电压信号,在经定标放大器4进行放大、定标,形成跟踪电压输出Vg;跟踪电压信号经AC/DC转换器5后,形成直流电压输出 。 输出经V/I转换器6后形成直流输出 , 输出经V/F变换器7后形成频率输出 。只有输出跟踪电压 的产品才使用正负电源﹝+E,-E﹞,其他产品才使用单一正电源。
图2-1中电流测头1和电压测头2是本系列产品的关键部件,属于精密互感器系列,承担隔离和线性变换的双重作用,改变电流测头规格或改变电压测头的输入电阻可以改变传感器的测量范围。定标放大器4是一个宽带交流放大器,它产生的电压输出 ,在波形和相位上快速跟踪输入信号的变化, 输出型传感器适用于交流采样系统。转换器5是配套研发的专用厚膜集成器件,它把交流电压信号变换为直流电压或直流电流输出。转换原理分为平均值转换和真有效值转换,平均值转换器成本低,适用于标准正弦交流信号转换;真有效值转换器适用于含有多次谐波的交流信号(如三角波、矩形波、梯形波、可控硅调功波等),单成本较高。转换器5(或转换器6) 的“基准波”接地时,他输出0~5V(或0~20mA);为它们配加以个高稳定的偏置电路,就形成1V~5V(或4mA~20mA);为它们配加一个高稳定的偏置电路,就形成了1V~5V(4mA~20mA)输出。
2.2.2 LCD12864基本用途
1.使用前的准备
先给模块加上工作电压,再按照下图的连接方法调节LCD的对比度,使其显示出黑色的底影。此过程亦可以初步检测LCD有无缺段现象。
2.字符显示
带中文字库的128X64-0402B每屏可显示4行8列共32个16×16点阵的汉字,每个显示RAM可显示1个中 文字符或2个16×8点阵全高ASCII码字符,即每屏最多可实现32个中文字符或64个ASCII码字符的显示。带中文字库的128X64-0402B内部提供128×2字节的字符显示RAM缓冲区(DDRAM)。字符显示是通过将字符显示编码写入该字符显示RAM实现的。根据写入内容的不同,可分别在液晶屏上显示CGROM(中文字库)、HCGROM(ASCII码字库)及CGRAM(自定义字形)的内容。三种不同字符/字型的选择编码范围为:0000~0006H(其代码分别是0000、0002、0004、0006共4个)显示自定义字型,02H~7FH显示半宽ASCII码字符,A1A0H~F7FFH显示8192种GB2312中文字库字形。字符显示RAM在液晶模块中的地址80H~9FH。字符显示的RAM的地址与32个字符显示区域有着一一对应的关系,其对应关系如下表所示。
80H
81H
82H
83H
84H
85H
86H
87H
90H
91H
92H
93H
94H
95H
96H
97H
88H
89H
8AH
8BH
8CH
8DH
8EH
8FH
98H
99H
9AH
9BH
9CH
9DH
9EH
9FH
3、图形显示
先设垂直地址再设水平地址(连续写入两个字节的资料来完成垂直与水平的坐标地址)
垂直地址范围 AC5...AC0
水平地址范围 AC3…AC0
2.3  电池电量检测芯片BQ26500
2.3.1 测量原理
BQ26500的电量检测原理我们也需要做简单的了解,BQ26500内置了温度传感器,它通过内置的温度传感器和内部计数器来估算被测锂离子电池的放电程度,放电的同时还可以根据温度需要进行温度补偿,并且能够通过锂离子电池的放电周期,校准锂离子电池的实际容量,外接内部写有初始化程序的EEPROM,负责控制电池的管理工作,串口和外部EEPROM可以用来编程。
在日常生活中,使用锂离子电池是一般都不需要进行温度保护,因为日常情况下,锂离子电池工作所在环境温度不会超过其工作温度范围之外,除非需要该锂离子电池一直处于长期的持续的工作状态,这时候应该采取适当的温度保护措施。但是BQ26500是一款流行与目前市场上相当专业的电池电量检测芯片,BQ26500对被测锂离子电池进行电量检测的同时,会检测锂离子电池的温度情况,因为BQ2040内置了温度传感器,可以进行过热保护等控制措施,不需要外接热敏电阻,如果检测到温度过低,这时候BQ26500还可以进行温度补偿,不需要外接谐振器等相关器件,进一步减少了器件,降低了设计成本。
2.3.2  电路图设计
作为一款电池电量检测芯片,BQ2040负责完成锂离子电池的电量检测模块的功能,它先采集所需被测锂离子电池的信号参数,然后按照原先已经设定好的算法检测计算出被测锂离子电池的电量,通过I2C总线与单片机部分进行数据交换,最终通过LCD驱动显示部分数码输出显示锂离子电池的电量信息给用户。电量检测结果用LCD数码输出显示,从而让我们及时了解电量信息,完全掌握锂离子电池的用电状态,提高利用率。
本系统电量检测部分采用电池电量检测芯片BQ2040,除了支持对锂离子电池的高精度电量检测,还满足其他多种电池的电量检测工作,比如能够很好的检测镍镉电池、镍氢电池的电量。
                                  BQ26500 电路图


2.4  数据传输存储芯片24C642.4.1  24C64概述
24C64芯片属于24C系列里面常见的一款,该系列的主要功能是数据的存储及传输。既然是数据传输存储芯片,那么就会有每款芯片带有多少存储位的问题,该系列的芯片拥有多少存储位可以从24C后面的数字读出来。如ATMEL的24C64,从后面的数字可以读出其存储位为64K。这个系列的芯片具有许多的优势,例如能重复擦写1百万次以上,并且在其内部已经存储成功的数据能够长期保持,时间达100年之久。24C64具有多种封装形式可供选择,现如今已被广大电子行业从业者所接受,广泛应用于电力电子各个领域。
ATMEL的24C64是I2C 总线的EEPROM,I2C总线(Inter Integrated Circuit 内部集成电路总线)是两线式串行总线,只占用微处理器的2个I/O 引脚,仅需要时钟和数据两根线就可以进行数据传输,令用户使用起来十分便捷。
2.4.2  24C64引脚说明
图2-6  24C64引脚分布

表2.5  24C64引脚说明
引脚符号
引脚名称
引脚描述
A0到A2
地址输入端
确定连接器件的地址
SDA
串行数据端
需要附加一个上拉电阻,双向引脚,可以输出或输入地址及数据。
SCL
串行时钟输入端
产生串行同步时钟信号
VCC
电源输入端
电源电压输入
GND
接地端
接地

2.4.3  24C64特性介绍
  •   低功耗器件
  •   2线串行接口
  •   双向数据传输协议
  •   写保护引脚用于硬件数据保护
  •   高可靠性

2.5  时钟芯片DS13022.5.1  DS1302概述
DS1302是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。通过简单的串行接口,采用三线接口与CPU进行同步通信,内部有一个31×8的用于临时性存放数据的静态RAM。它具有主电源/后备电源双电源引脚,VCC1为后备电源,VCC2为主电源。在主电源关闭的情况下,也能保持时钟的连续运行。DS1302由VCC1或VCC2两者中的较大者供电。当Vcc2大于Vcc1+0.2V时,DS1302由VCC2供电;当VCC2小于VCC1时,DS1302由VCC1供电。
DS1302功能:①日期时间信息;②每月的天数和闰年的天数可自动调整;③通过AM/PM指示决定采用24或12小时格式;④保持数据和时钟信息时功率小于1mW。
2.5.2  DS1302引脚说明
图2-7  DS1302引脚分布



表2.6  DS1302引脚说明
引脚符号
引脚名称
引脚描述
X1、X2
晶振引脚
32.768KHz
GND
接地引脚
接地
CE
复位脚
在读/写数据期间必须为高
I/O
数据输入/输出
三线接口时的双向数据线
SCLK
串行时钟引脚
控制数据的输入与输出
VCC1、VCC2
电源供电引脚
VCC1:主电源;VCC2:备份电源





3.软件系统设计3.1 C语言简介

C语言是近年来在国内外普遍使用的一种程序设计语言。C语言功能丰富,表达能力强应用广,既有高级语言的特点,也有汇编语言的特点。C是中级语言。它把高级语言的基本结构和语句与低级语言的实用性结合起来。C 语言可以像汇编语言一样对位、字节和地址进行操作, 而这三者是计算机最基本的工作单元。

C是结构式语言。结构式语言的显著特点是代码及数据的分隔化,即程序的各个部分除了必要的信息交流外彼此独立。这种结构化方式可使程序层次清晰,便于使用、维护以及调试。C 语言是以函数形式提供给用户的,这些函数可方便的调用,并具有多种循环、条件语句控制程序流向,从而使程序完全结构化。

C语言功能齐全。具有各种各样的数据类型,并引入了指针概念,可使程序效率更高。另外C语言也具有强大的图形功能,支持多种显示器和驱动器。而且计算功能、逻辑判断功能也比较强大。

3.2 程序设计流程3.2.1  初始化

初始化程序流程图

初始化程序的功能就是初始化各个端口,使其各部件完成先前的准备工作。设置好各个端口的功能,比如哪些端口设置为中断的输入口,哪些设置为外部模块。设置完成以后就可以打开各个中断使能,使系统响应相对应的中断跳转程序。


3.2.2  主程序流程图

主程序流程图
3.2.3A/D转换与中断服务
AT89C51内部有两个16位的可编程定时器/计数器,T0和T1。定时器实际上是工作在计数方式下 ,只不过对固定平率的脉冲计数,由于脉冲周期也固定,由计数值可以计算出计数时就爱你,有定时的功能。AT89C51的T/C是加1计数的。当工作在定时器方式时,对振荡源12分频的脉冲计数,即每个机器周期计数值加1,计数速率1/12fosc,当fosc=12MHz时,计数速率=1000KHz,即计数器每加1用时1us。


  A/D转换与中断服务流程图
3.3  BQ26500总线时序
BQ26500采用电源系统管理Veil.0(SMBus)协议,支持智能电池数据管理命令(SBData)和智能电池充电控制(SBData)功能,通过串行接口可以检测锂离子电池的充电状态、剩余电量、放电剩余时间、电池材料等信息。
SMBus是System Management Bus的缩写,译为系统管理总线,SMBus是一种二线制串行总线,它大部分基于I2C(Inter-Integrated Circuit)总线规范。I2C两线(串行数据SDA和串行时钟SCL线)式串行总线,用于连接微控制器及其外围设备,是微电子通信控制领域广泛采用的一种总线标准。I2C是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点。和I2C一样,SMBus不需增加额外引脚,但是工作频率只能在10kHz到最高100kHz范围内,且专门面向智能电池管理应用。SMBus为系统电源管理等任务提供了一条控制总线,使用SMBus的系统,设备之间发送和接收消息都是通过SMBus,而不是使用单独的控制线,这样可以节省设备的管脚数。
SMBus最初的目的是为智能电池、充电电池和与其他系统通信的微控制器之间的通信链路而定义的,如今也被用来连接各种设备,包括电源相关设备,系统传感器,EEPROM通讯设备等等,但SMBus最适用于笔记本电脑上,检测各元件状态并更新硬件设置。

4.总结
    硬件设计完成将待设计的系统分割成各个功能模块,然后组合成一个合理的可行性方案的任务,用Protel等相关软件完成硬件原理图的设计后,制成PCB板。软件设计则负责根据系统相关的功能要求,进行模块的编程等,完成硬件设计后,我们可以通过Keil4.0等类似软件对单片机烧入程序,最后便可进行锂离子电池电量检测系统的检测试验,定时记录相关数据,对锂离子电池电量检测结果的准确性进行测试。
系统测试的思路可以针对BQ2040内的三个重要寄存器:Full Charge Capacity(FCC)、Remaining Capacity(RM)、Discharge Count Register(DCR)。通过每隔一定时间读取这三个寄存器的数据,这样记录多组数据后,可以通过以下几个主要关系进行验证分析系统的准确性及可靠性:
  • RM ≤ FCC。
  • 放电的逆过程即充电,充电期间,RM数值停止递增,则RM=FCC,这时我们读取的RM应近似等于FCC,此时DCR=0。若要锂离子电池充分充电,我们还可以根据BQ2040进行充电控制,向RM写入一个用户自定义的值。
  • DCR随着RM的递减逐渐增大,直到RM=0,锂离子电池放电和自放电都会使DCR增大,但当RM=0后,只有放电才使DCR增大。

我做的基于单片机的电量检测系统课程设计完成了,基本上达到了预期的目的。当初拿到这个题目的时候都不知道怎么入手,但在老师的指导下,自己找资料、看书,总算完成了。通过此次的毕业设计,使我对单片机有了更深一层的了解,从理论和实践我都得到了很大的提高,所以这次任务的完成使我学到了很多知识。首先,丰富了自己的知识面,学通了以前没学通的东西,具体了解了怎么去完成一个电路的设计。在此次的设计中,学到了单片机AT89C51的内部结构及工作原理,了解了时钟电路和控制电路的工作原理,还有共阳极数码管的工作原理,同时也提高了我的C语言使用能力,并且挺高了自己分析问题和解决问题的能力,有了理论联系实际的机会,为以后从事这个方面的工作打好了基础,这也是这次毕业设计的最大收获。
这次的毕业设计总的来说还是比较成功的,能够实现电压显示,如果单独查看电压或电流,可以通过安检控制查看电压或电流,但是还是有许多不足之处,不过的确从中学到了很多,也发现了自己的很多问题,为自己以后的学习、进步打下了不错的基础。
致谢

经过两个多月的时间,我在导师廖建文的指导下,完成了整个系统的设计和制作。在这段时间当中,感受最深的就是解决问题的一些方法、技巧。在整个设计过程中,我遇到了很多的问题,通过查阅相关资料、冷静理性的分析、方案的对比和实验证明,最终解决了所遇到的问题。

对我而言,知识上的收获重要,精神上的丰收更加可喜。挫折是一份财富,经历是一份拥有。这次实习必将成为我人生旅途上一个非常美好的回忆!此次课程设计,学到了很多课内学不到的东西,比如独立思考解决问题,出现差错的随机应变,和与人合作共同提高,都受益匪浅,今后的制作应该更轻松,自己也都能扛的起并高质量的完成项目。对于我来说,收获最大的是自己主动去解决问题,并在试验中总结解决方法,学会去分析问题出现的原因,以及应该从哪个部分去解决,但无法出现正确结果是,需耐心的检查电路,因为大多数出问题都是因为一两根线没接或接错的问题。
总体来说,通过这次课程设计学习,让我对各种电路都有了大概的了解,也学会了常用绘图软件的使用,在平时的理论学习中遇到的问题都一一解决,加深了我对专业的了解,培养了我对学习的兴趣,为以后的学习打下了好的开端,我受益匪浅。同时,让我明白:这些电路还是应该自己动手实际操作才会有深刻理解,才会有收获,所谓“一行胜千言”果然不假。
最后,我要感谢我系安排了此次课程设计,这为我们以后的毕业设计奠定了良好的基础,并更好地复习和巩固了以前学过的理论知识。总之,本次课程设计让我们受益匪浅!

单片机源程序如下:
  1. #include<reg51.h>
  2. #include <intrins.h>

  3. #define uchar unsigned char
  4. #define uint unsigned int


  5. #define LCD_data  P0       //数据口
  6. uchar code DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
  7. sbit CLK=P1^3;   //时钟信号
  8. sbit ST=P1^2;    //启动信号
  9. sbit EOC=P1^1;   //转换结束信号
  10. sbit AD_OE=P1^0;    //输出使能
  11. sbit LCD_RS  =  P2^6;      //寄存器选择输入
  12. sbit LCD_RW  =  P2^5;      //液晶读/写控制
  13. sbit LCD_EN  =  P2^7;      //液晶使能控制
  14. sbit LCD_PSB =  P3^2;      //串/并方式控制
  15. sbit LCD_RST =  P3^7;      //液晶复位端口
  16. sbit OE = P3^0;
  17. sbit LE = P3^1;
  18. signed char result = 0;
  19. #define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
  20. /*********************************************************/
  21. uchar code  DIS1[] = {"**电压测量系统**"};
  22. uchar code  DIS2[] = {"**U = --.- (V)**"};
  23. uchar code  DIS3[] = {"**I = --.- (A)**"};
  24. uchar code  DIS4[] = {"**P = --.- (W)**"};
  25. /*********************************************************/

  26. void DelayMS(uint ms)   //延时
  27. {
  28.               uchar i;
  29.               while(ms--)
  30.                             for(i=0;i<120;i++)
  31.                             {;}
  32. }

  33. void Display_Result(uchar d)   //显示转换结果
  34. {
  35.               P2=0xf7;  //第4个数码管显示个位数
  36.               P0=DSY_CODE[d%10];

  37.               DelayMS(5);

  38.               P2=0xfb;   //第3个数码管显示十位数
  39.               P0=DSY_CODE[d%100/10];

  40.               DelayMS(5);
  41.                                                                                                                                                                                                                                              
  42.               P2=0xfd;  //第2个数码管显示百位数
  43.               P0=DSY_CODE[d/100];
  44.               DelayMS(5);
  45. }

  46. void delay(int ms)
  47. {
  48.     while(ms--)
  49.               {
  50.       uchar i;
  51.                 for(i=0;i<150;i++)
  52.                  {
  53.                   _nop_();                                            
  54.                             _nop_();
  55.                             _nop_();
  56.                             _nop_();
  57.                  }
  58.               }
  59. }            
  60. /*******************************************************************/
  61. /*                                                                 */
  62. /*  延时函数                                                       */
  63. /*                                                                 */
  64. /*******************************************************************/
  65. void delay1(int ms)
  66. {
  67.     while(ms--)
  68.               {
  69.       uchar y;
  70.                 for(y=0;y<100;y++) ;
  71.               }
  72. }                                         
  73. /*******************************************************************/
  74. /*                                                                 */
  75. /*检查LCD忙状态                                                    */
  76. /*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。      */
  77. /*                                                                 */
  78. /*******************************************************************/
  79. bit lcd_busy()
  80. {                        
  81.     bit result;

  82.               LE = 1;
  83.               delay(1);

  84.               LCD_RS = 0;
  85.     LCD_RW = 1;
  86.     LCD_EN = 1;
  87.     delayNOP();
  88.     result = (bit)(P0&0x80);
  89.     LCD_EN = 0;
  90.             
  91.     delay(1);
  92.               LE = 0;

  93.     return(result);
  94. }
  95. /*******************************************************************/
  96. /*                                                                 */
  97. /*写指令数据到LCD                                                  */
  98. /*RS=L,RW=L,E=高脉冲,D0-D7=指令码。                             */
  99. /*                                                                 */
  100. /*******************************************************************/
  101. void lcd_wcmd(uchar cmd)
  102. {                        
  103.    while(lcd_busy());
  104.     LE = 1;
  105.               delay(1);
  106.             
  107.               LCD_RS = 0;
  108.     LCD_RW = 0;
  109.     LCD_EN = 0;
  110.     _nop_();
  111.     _nop_();
  112.     P0 = cmd;
  113.     delayNOP();
  114.     LCD_EN = 1;
  115.     delayNOP();
  116.     LCD_EN = 0;
  117.             
  118.               delay(1);
  119.               LE = 0;
  120. }
  121. /*******************************************************************/
  122. /*                                                                 */
  123. /*写显示数据到LCD                                                  */
  124. /*RS=H,RW=L,E=高脉冲,D0-D7=数据。                               */
  125. /*                                                                 */
  126. /*******************************************************************/
  127. void lcd_wdat(uchar dat)
  128. {                        
  129.    while(lcd_busy());
  130.                
  131.               LE = 1;
  132.               delay(1);
  133.     LCD_RS = 1;
  134.     LCD_RW = 0;
  135.     LCD_EN = 0;
  136.               delay(1);
  137.               LE = 0;

  138.     P0 = dat;
  139.     delayNOP();
  140.               LE = 1;
  141.               delay(1);
  142.     LCD_EN = 1;
  143.     delayNOP();
  144.     LCD_EN = 0;
  145.               delay(1);
  146.               LE = 0;
  147. }
  148. /*******************************************************************/
  149. /*                                                                 */
  150. /*  LCD初始化设定                                                  */
  151. /*                                                                 */
  152. /*******************************************************************/
  153. void LCD12864_init()
  154. {
  155.     LCD_PSB = 1;         //并口方式

  156.               LCD_RST = 0;                            //液晶复位
  157.     delay(3);                  
  158.     LCD_RST = 1;     
  159.     delay(3);

  160.     lcd_wcmd(0x34);      //扩充指令操作
  161.     delay(5);
  162.     lcd_wcmd(0x30);      //基本指令操作
  163.     delay(5);
  164.     lcd_wcmd(0x0C);      //显示开,关光标
  165.     delay(5);
  166.     lcd_wcmd(0x01);      //清除LCD的显示内容
  167.     delay(5);
  168. }

  169. void T1_INIT(void )
  170. {
  171.               TMOD=0x02;  //T1工作模式2
  172.               TH0=0x14;
  173.               TL0=0x00;
  174.               IE=0x82;
  175.               TR0=1;
  176.               P1=0x3f;  //选择ADC0809的通道3(0111)(P1.4~P1.6)
  177. }
  178. void Locker_init(void )
  179. {
  180.               OE = 0;
  181.               LE = 1;                           
  182. }
  183. /*********************************************************/
  184. /*                                                       */
  185. /* 设定显示位置                                          */
  186. /*                                                       */
  187. /*********************************************************/
  188. void lcd_pos(uchar X,uchar Y)
  189. {                        
  190.    uchar  pos;
  191.    if (X==1)
  192.      {X=0x80;}
  193.    else if (X==2)
  194.      {X=0x90;}
  195.    else if (X==3)
  196.      {X=0x88;}
  197.    else if (X==4)
  198.      {X=0x98;}
  199.    pos = X+Y ;

  200.    lcd_wcmd(pos);     //显示地址
  201. }
  202. /*********************************************************
  203. *                                                        *
  204. * 清屏函数                                               *
  205. *                                                        *
  206. *********************************************************/
  207. void  clr_screen()
  208. {
  209.    lcd_wcmd(0x34);      //扩充指令操作
  210.    delay(5);   
  211.    lcd_wcmd(0x30);      //基本指令操作
  212.    delay(5);
  213.    lcd_wcmd(0x01);      //清屏
  214.    delay(5);   
  215. }

  216. void Various(uchar line,uchar num)
  217. {
  218.               uchar a,b,c;
  219.               a = 48+num/100;
  220.               b = 48+num%100/10;
  221.               c = 48+num%10;
  222.             
  223.               switch( line )
  224.               {
  225.                             case 1:line = 0x80;
  226.                                              break;
  227.                             case 2:line = 0x90;
  228.                                              break;
  229.                             case 3:line = 0x88;
  230.                                              break;
  231.                             case 4:line = 0x98;
  232.                                              break;
  233.                             default:break;
  234.               }
  235.             
  236.               lcd_wcmd(line+3);      //写入垂直坐标值
  237.               lcd_wdat(a);
  238.               lcd_wdat(b);
  239.               lcd_wdat('.');
  240.               lcd_wdat(c);            
  241. }

  242. void UI_Display(void )
  243. {
  244.               uchar i;
  245.             
  246.                  lcd_pos(1,0);             //设置显示位置为第一行
  247.               for(i=0;i<16;i++)
  248.      {
  249.        lcd_wdat(DIS1[i]);
  250.        delay(30);
  251.      }

  252.      lcd_pos(2,0);             //设置显示位置为第二行
  253.      for(i=0;i<16;i++)
  254.      {
  255.        lcd_wdat(DIS2[i]);
  256.        delay(30);
  257.      }
  258.      lcd_pos(3,0);             //设置显示位置为第三行
  259.      for(i=0;i<16;i++)
  260.      {
  261.        lcd_wdat(DIS3[i]);
  262.        delay(30);
  263.      }
  264.      lcd_pos(4,0);             //设置显示位置为第四行
  265.      for(i=0;i<16;i++)
  266.      {
  267.        lcd_wdat(DIS4[i]);
  268.        delay(30);
  269.      }
  270. }

  271. void AD_gather(void )
  272. {
  273.               ST=0;ST=1;ST=0; //启动A/D转换
  274. ……………………

  275. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
基于BQ26500电池测量.doc (871.46 KB, 下载次数: 30)


评分

参与人数 2黑币 +58 收起 理由
穿着安踏去拉萨 + 8 51有你更精彩
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:779899 发表于 2021-1-9 16:52 | 只看该作者
十分不错的思路!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表