传感器与检测技术综合实训报告书

 

课 程 设 计 报 告 书

所属课程名称  传感器与检测技术综合课程设计      

                   电子称硬件电路设计                       

                      机电学院           

业、班                             

                     0614100306                     

                                   

                                  

2013   19

目录

1 课 程 设 计 任 务 书... 2

2 总体设计方案... 3

2.1 控制器部分... 3

2.2 数据采集部分... 4

2.2.1 传感器的选择... 4

2.2.2 放大电路选择... 5

2.2.3 A/D转换器的选择... 7

2.2.4 键盘处理部分方案论证... 8

2.3 显示电路部分的选择... 8

2.4 超量程报警部分选择... 9

3 电路的硬件设计... 9

3.1 AT89S52的最小系统电路... 10

3.1.1 单片机芯片AT89S52介绍... 10

3.1.2 AT89S52的最小系统电路构成... 10

3.2 显示电路与AT89S52单片机接口电路设计... 11

3.3 测量电路... 12

3.4 数据采集部分电路设计... 13

3.5 键盘电路与AT89S52单片机接口电路设计... 15

3.6 报警电路的设计... 16

4 电路的软件设计... 16

4.1 主程序设计... 16

4.2 子程序设计... 17

4.2.1 A/D转换启动及数据读取程序设计... 17

4.2.2 显示子程序设计... 18

4.2.3 键盘输入控制程序的设计... 18

4.2.4 报警子程序的设计... 19

5 总结... 19

6 参考文献... 20

附录... 21

附录1 元件清单及其参数... 21

附录2 系统总图... 22

附录3 电子称主程序... 23

辽东学院

1 课 程 设 计 任 务 书

课程设计题目:          电子称硬件电路设计                               

课程设计时间: 20## 7 15 日起至 20## 7 19

课程设计要求:

1.利用单片机实现对所设计的电子秤的各项功能的控制。

2.电子秤能够LCD液晶显示出商品的名称、价格,重量、总价等信息。

3.电子秤称重范围:0~9.999㎏;重量误差不大于0.005㎏。

4.性能稳定、计数要精确,具有校准旋钮,简化电子称的校准操作。

5.电子秤能够自动完成商品的价格计算。

6.具有溢出声光报警,提示用户纠正操作功能。

学生签名:        

2013 07 19

课程设计评阅意见

评阅教师:          

20##  19

2 总体设计方案

按照本设计功能的要求,本设计大致可分为五个模块:数据采集模块、信号放大模块、模数转换模块、单片机控制模块、人机交换模块。(其中人机交换模块中包括:声光报警、LCD显示、键盘输入)系统设计总体方案框图如图2-1所示。

图2-1设计思路框图

测量部分是利用称重传感器检测压力信号,得到微弱的电信号(本设计为电压信号),而后经处理电路(如滤波电路,差动放大电路,)处理后,送A/D转换器,将模拟量转化为数字量输出。控制器部分接受来自A/D转换器输出的数字信号,经过复杂的运算,将数字信号转换为物体的实际重量信号,并将其存储到存储单元中。控制器还可以通过对扩展I/O的控制,对键盘进行扫描,而后通过键盘散转程序,对整个系统进行控制。数据显示部分根据需要实现显示功能。

2.1 控制器部分

本设计使用单片机作为系统的主控制器,可以容易地将计算机技术和测量控制技术结合在一起,组成新型的只需要改变软件程序就可以更新换代的“智能化测量控制系统”。这种新型的智能仪表在测量过程自动化、测量结果的数据处理以及功能的多样化方面,都取得了巨大的进展。

根据总体方案设计的分析,可以选用带EPROM的单片机,由于应用程序不大,应用程序直接存储在片内,不用在外部扩展存储器,这样电路也可简化。在这里选用ATMEL生产的AT89SXX系列单片机。AT89SXX系列与MCS-51相比有两大优势:第一,片内存储器采用闪速存储器,使程序写入更加方便;第二,提供了更小尺寸的芯片,使整个硬件电路体积更小。此外价格低廉、性能比较稳定的MCPU,具有8K×8ROM、256×8RAM、3个16位定时计数器、4个8位I/O接口。这些配置能够很好地实现本仪器的测量和控制要求。

最后我们最终选择了AT89S52这个比较常用的单片机来实现系统的功能要求。AT89S52内部带有8KB的程序存储器,基本上已经能够满足我们的需要。

2.2 数据采集部分

电子秤的数据采集部分主要包括称重传感器、信号放大电路、A/D转换电路及键盘处理方案论证,因此对于这部分的论证主要分四方面。

2.2.1 传感器的选择

传感器属于精密部件,剧烈振动、自由落体、碰撞、过载、过压等都非常容易造成传感器永久损坏或者影响精度和线性。传感器是测量机构最重要的部件,目前常用的有电阻应变是压力传感器和电容式压力传感器、压电式压力传感器。选用是应按照稳定性、精度等级、灵敏度、寿命和安装环境依次作为优先考虑。现比较如下:

1.电容式压力传感器稳定性较差,精度和灵敏度高,寿命较短,对环境要求苛刻,不易长距离传输。

2.压电式压力传感器稳定性好,精度和灵敏度高,寿命长,但大量程的压力传感器有待进一步研究。

3.电阻应变式压力传感器稳定性好,精度和灵敏度较高,寿命较长,对测量环境要求不太严格。

电阻应变式压力传感器主要由弹性体、电阻应变片电缆线等组成,内部线路采用惠更斯电桥,当弹性体承受载荷产生变形时,电阻应变片(转换元件)受到拉伸或压缩应变片变形后,它的阻值将发生变化(增大或减小)从而使电桥失去平衡,产生相应的差动信号,供后续电路测量和处理。

通过以上对传感器的比较分析,最终选择了第三种方案。称重范围为0~9.999Kg,重量误差不大于0.005Kg,考虑到秤台自重、振动和冲击分量,还要避免超重损坏传感器,所以传感器量程必须大于额定称重——9.999Kg 。我们选择的是L-PSIII型传感器,量程20Kg,精度为 0.01%,满量程时误差0.002Kg,完全满足本系统的精度要求。

2.2.2 放大电路选择

电阻应变片组成的传感器是把机械应变转换成ΔR/R,而应变电阻的变化一般都很微小,例如传感器的应变片电阻值120Ω,灵敏系数 K=2,弹性体在额定载荷作用下产生的应变为1000ε,应变电阻相对变化量为:

ΔR/R = K×ε= 2×1000×10-6 =0.002  (2-1)

由式2-1可以看出电阻变化只有0.24Ω,其电阻变化率只有0.2%。这样小的电阻变化既难以直接精确测量,又不便直接处理。因此,必须采用转换电路,把应变计的ΔR/R变化转换成电压或电流变化,但是这个电压或电流信号很小,需要增加增益放大电路来把这个电压或电流信号转换成可以被A/D转换芯片接收的信号。在前级处理电路部分,我们考虑可以采用以下几种方案:

方案一 利用普通低温漂运算放大器构成前级处理电路:

普通低温漂运算放大器构成多级放大器会引入大量噪声。由于A/D转换器需要很高的精度,所以几毫伏的干扰信号就会直接影响最后的测量精度。所以,此种方案不宜采用。

方案二 由高精度低漂移运算放大器构成差动放大器,而构成的前级处理电路:

差动放大器具有高输入阻抗,增益高的特点,可以利用普通运放(如LM324)做成一个差动放大器。其设计电路如下图:

图2-2利用普通运放设计的差动放大器

方案三 采用专用仪表放大器,如:INA126,INA121,AD620等构成前级处理电路:

下面举例用AD620专用仪表放大器来实现,其接口如下图所示:

图2-3 AD620的接口图

内部结构如下图所示:

图2-4 AD620的内部等效图

电路的工作原理:A1、A2工作在负反馈状态,其反向输入端的电压与同相输入端的电压相等。即Rg两端的电压分别为Vin+、Vin-。因此

   

(2-2)

设图中电阻R1=R2=R,则A1、A2两输出端的电压差U12为

   

     

                                                          (2-3)

将式(2-4)代入式(2-3)得

   

放大器的增益Av为

   

(2-4)

可见,仅需调整一个电阻Rg,就能方便的调整放大器的增益。由于整个电路对称,调整时不会造成共模抑制比的降低。

在接口图中,通过改变可变电阻R3的阻值大小来改变放大器的增益,放大器增益计算公式如下:

                                             (2-5)

AD620 具有体积小、功耗低、精度高、噪声低和输入偏置电流低的特点。其最大输入偏置电流为20nA,这一参数反映了它的高输入阻抗。AD620在外接电阻Rg时,可实现1~1000范围内的任意增益;工作电源范围为±2.3~±18V;最大电源电流为1.3mA;最大输入失调电压为125V;频带宽度为120kHz(在G=100时)。

基于以上分析,我们决定采用制作方便而且精度很好的专用仪表放大器AD620(仿真中用OPAMP代替)。

2.2.3 A/D转换器的选择

A/D转换部分是整个设计的关键。ADC集成电路主要有以下几种类型:

1.并行比较A/D转换器:如ADC0808、 ADC0809等 。并行比较ADC是现今速度最快的模/数转换器,采样速率在1GSPS以上,通常称为“闪烁式”ADC。它由电阻分压器、比较器、缓冲器及编码器四部分组成。这种结构的ADC所有位的转换同时完成,其转换时间主取决于比较器的开关速度、编码器的传输时间延迟等。缺点是:并行比较式A/D转换的抗干扰能力差,由于工艺限制,其分辨率一般不高于8位,因此并行比较式A/D适合于数字示波器等转换速度较快的仪器中。

2.逐次逼近型A/D转换器:如:ADS7805、ADS7804等。逐次逼近型ADC是应用非常广泛的模/数转换方法,这一类型ADC的优点:高速,采样速率可达 1MSPS;与其它ADC相比,功耗相当低;在分辨率低于12位时,价格较低。缺点:在高于14位分辨率情况下,价格较高;传感器产生的信号在进行模/数转换之前需要进行调理,包括增益级和滤波,这样会明显增加成本。

3.积分型A/D转换器:如:ICL7135、ICL7109、ICL1549、MC14433等。积分型ADC又称为双斜率或多斜率ADC,是应用比较广泛的一类转换器。积分型ADC两次积分的时间都是利用同一个时钟发生器和计数器来确定,因此所得到的表达式与时钟频率无关,其转换精度只取决于参考电压VR。这类ADC主要应用于低速、精密测量等领域,如数字电压表。其优点是:分辨率高,可达22位;功耗低、成本低。缺点是:转换速率低,转换速率在12位时为100~300SPS。

4.压频变换型ADC:其优点是:精度高、价格较低、功耗较低。缺点是:类似于积分型ADC,其转换速率受到限制,12位时为100~300SPS。

根据系统的精度要求以及综合的分析其优点和缺点,本设计采用了12位A/D转换器ADC0832。ADC0832为8位分辨率A/D转换芯片,其最高分辨可达256级,可以适应一般的模拟量转换要求。其内部电源输入与参考电压的复用,使得芯片的模拟电压输入在0~5V之间。芯片转换时间仅为32μS,据有双数据输出可作为数据校验,以减少数据误差,转换速度快且稳定性能强。独立的芯片使能输入,使多器件挂接和处理器控制变的更加方便。通过DI数据输入端,可以轻易的实现通道功能的选择。

2.2.4 键盘处理部分方案论证

由于电子秤需要设置单价(十个数字键,一个小数点),总共需设置13个键(包括一个清除键和一个确认键)。本设计采用矩阵式键盘:矩阵式键盘的特点是把检测线分成两组,一组为行线,一组列线,按键放在行线和列线的交叉点上。图2-5给出了一个4×4的矩阵键盘结构的键盘接口电路,图中的每一个按键都通过不同的行线和列线与主机相连。4×4矩阵式键盘共可以安装16个键,但只需要8条测试线。当键盘的数量大于8时,一般都采用矩阵式键盘。结合本设计的实际要求,采用4×4矩阵式键盘。

图2-5矩阵式键盘

2.3 显示电路部分的选择

数据显示是电子秤的一项重要功能,是人机交换的主要组成部分,它可以将测量电路测得的数据经过微处理器处理后直观的显示出来。数据显示部分有以下两种方案可供选择:一是LED数码管显示,二是LCD液晶显示两种选择。LCD液晶显示器是一种极低功耗显示器,从电子表到计算器,从袖珍时仪表到便携式微型计算机以及一些文字处理机都广泛利用了液晶显示器。本设计采用的是HJ12864ZW液晶显示器。

2.4 超量程报警部分选择

智能仪器一般都具有报警功能,报警主要用于系统运行出错、当测量的数据超过仪表量程或者是超过用户设置的上下限时为提醒用户而设置。在本系统中,设置报警的目的就是在超出电子秤测量范围以及总价不能正常显示时,发出声光报警信号,提示用户,防止损坏仪器。

超限报警电路是由单片机的I/O口来控制的,当称重物体重量超过系统设计所允许的重量,通过程序使单片机的I/O值为低电平,从而三极管导通,使蜂鸣器BUZZER发出报警声,同时使连接报警灯的I/O置为低电平,则发光二极管导通,二极管发光。在设计过程中一定得注意发光二极管的极性,否则,发光二极管是不会正常发光。

3 电路的硬件设计

根据设计要求与设计思路,此电路由一块AT89S52单片机、复位电路、振荡电路、12864LCD显示器、蜂鸣器及LED灯报警电路、L-PSIII压力传感电路。硬件设计框图如下:

图3-1硬件电路设计框图

在本系统中用于称量的主要器件是称重传感器(一次变换元件),称重传感器在受到压力或拉力时会产生电信号,受到不同压力或拉力是产生的电信号也随着变化,而且力与电信号的关系一般为线性关系。由于传感器输出的为模拟信号,所以需要对其进行A/D转换为数字信号以便单片机接收,因此电路中需要用进行A/D转换。又由于本设计采用的是L-PSIII电阻应变式压力传感器,其输出电压不能够使单片机和A/D转换器正常工作,因此需要设计放大电路来使ADC0832的输入电压达到2V左右。单片机根据称重传感器输出的电信号计算出物体的重量。

本设计电子称的硬件电路包括AT89S52的最小系统构成、传感器检测模块、信号放大模块、数模转换模块、信号处理模块、主控制模块、键盘及报警模块、人-机交换电路等。电路经Proteus软件仿真达到接近实际电路的效果,下面是硬件的设计与仿真结果。

3.1 AT89S52的最小系统电路

3.1.1 单片机芯片AT89S52介绍

AT89S52是一种带8K字节FLASH存储器(FPEROM—Flash Programmable and Erasable Read Only Memory)的低电压、高性能CMOS 8位微处理器,俗称单片机。单片机的可擦除只读存储器可以反复擦除1000次。该器件使用Atmel公司高密度非易失性存储器技术制造,与工业80C51 产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得AT89S52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。AT89S52具有以下标准功能:8k字节Flash,256字节RAM,32位I/O口线,看门狗定时器,2 个数据指针,三个16位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。另外,AT89S52可降至0Hz静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。

3.1.2 AT89S52的最小系统电路构成

AT89S52单片机的最小系统由时钟电路、复位电路、电源电路及单片机构成。单片机的时钟信号用来提供单片机片内各种操作的时间基准,复位操作则使单片机的片内电路初始化,使单片机从一种确定的初态开始运行。

单片机的时钟信号通常用两种电路形式得到:内部振荡方式和外部振荡方式。在引脚XTAL1和XTAL2外接晶体振荡器(简称晶振)或陶瓷谐振器,就构成了内部振荡方式。由于单片机内部有一个高增益反相放大器,当外接晶振后,就构成了自激振荡器并产生振荡时钟脉冲。

3.2 显示电路与AT89S52单片机接口电路设计

本设计采用HJ12864ZW液晶显示器,HJ12864ZW是一种图形点阵液晶显示器,它主要由行驱动器/列驱动器及128X64全点阵液晶显示器组成,可完成图形显示,也可以显示4行16个中文字形(16X16点阵汉字,与外部CPU接口可采用串行或并行方式控制)或者,4行32个字符(8X16)。本设计采用并行接口,下面仅介绍并行接口:

    表 3-1 12864 并行接口引脚介绍

12864LCD显示器与单片机的接口电路如图3-2所示:

图3-2 12864LCD显示器与单片机的接口电路

3.3 测量电路

测量电路的组成包括:传感器检测电路、模拟信号放大电路;在仿真环境里L-PSIII型传感器的检测原理可用如下电桥电路代替:

图3-3传感器检测电路

滑动变阻器的作用是在L-PSIII的输出电压范围内模拟其在不同应变下输出的不同电压,将其输出给下一级信号放大电路进行电压放大,放大电路如下图;我们采用OPAMP的差动式放大器来实现该功能,通过输出端的电压表,我们可以很方便的在仿真环境里,使用校准电阻对输出端进行校准操作。

图3-4模拟信号放大电路

3.4 数据采集部分电路设计

数据采集部分电路包括传感器输出信号电路、A/D转换器与单片机接口电路。我们采用L-PSIII压力传感器,数据采集模块与单片机的接口连接如图3-5所示:

图3-5数据采集模块与单片机接口电路

ADC0832 是美国国家半导体公司生产的一种8位分辨率、双通道A/D转换芯片。由于它体积小、兼容性强、性价比高,因此深受单片机爱好者及企业欢迎。ADC0832的管脚如图3-6所示:

图3-6 ADC0832管脚图

芯片接口说明:

CS 片选使能,低电平芯片使能。

CH0 模拟输入通道0,或作为IN+/-使用。

CH1 模拟输入通道1,或作为IN+/-使用。

GND 芯片参考0 电位(地)。

DI 数据信号输入,选择通道控制。

DO 数据信号输出,转换数据输出。

CLK 芯片时钟输入。

Vcc/REF 电源输入及参考电压输入(复用)。

正常情况下ADC0832 与单片机的接口应为4条数据线,分别是CS、CLK、DO、DI。但由于DO端与DI端在通信时并未同时有效并与单片机的接口是双向的,所以电路设计时可以将DO和DI 并联在一根数据线上使用。当ADC0832未工作时其CS输入端应为高电平,此时芯片禁用,CLK 和DO/DI 的电平可任意。当要进行A/D转换时,须先将CS使能端置于低电平并且保持低电平直到转换完全结束。此时芯片开始转换工作,同时由处理器向芯片时钟输入端CLK 输入时钟脉冲,DO/DI端则使用DI端输入通道功能选择的数据信号。在第1个时钟脉冲的下沉之前DI端必须是高电平,表示启始信号。在第2、3个脉冲下沉之前DI端应输入2 位数据用于选择通道功能。当此2 位数据为“1”、“0”时,只对CH0 进行单通道转换。当2位数据为“1”、“1”时,只对CH1进行单通道转换。当2 位数据为“0”、“0”时,将CH0作为正输入端IN+,CH1作为负输入端IN-进行输入。当2 位数据为“0”、“1”时,将CH0作为负输入端IN-,CH1 作为正输入端IN+进行输入。到第3 个脉冲的下沉之后DI端的输入电平就失去输入作用,此后DO/DI端则开始利用数据输出DO进行转换数据的读取。从第4个脉冲下沉开始由DO端输出转换数据最高位DATA7,随后每一个脉冲下沉DO端输出下一位数据。直到第11个脉冲时发出最低位数据DATA0,一个字节的数据输出 。

3.5 键盘电路与AT89S52单片机接口电路设计

矩阵式键盘的结构与工作原理:在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式。在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。这样,一个端口(如P1口)就可以构成4*4=16个按键,比直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。

在本系统中键盘采用矩阵式键盘并采用中断工作方式。键盘为4 X 4键盘,包括0、1、2、3、4、5、6、7、8、9、十个数字及确认、清除键以及小数点键。采用中断工作方式提高了CPU的利用效率,没键按下时没有中断请求,有键按下时,向CPU提出中断请求,CPU响应后执行中断服务程序,在中断程序中才对键盘进行扫描。下图就是键盘电路与AT89S52单片机接口电路图。

图3-7键盘电路与AT89S52单片机接口电路图

按数字键和小数点键可设置商品单价,按下“=”键显示商品的总价,当按下ON/C键时清除所设商品单价及计算结果。当所放商品的质量超过10Kg或商品总价超过255元时,报警电路便会发出持续报警声,LED灯点亮,直到物品重量或商品总价值低于上限。

3.6 报警电路的设计 

当电路检测到称重的物体超过仪器的测量限制时,将产生一个信号给报警电路。使报警电路报警从而提醒工作人员注意,超限报警电路如图3-8示。

图3-8报警电路

它是由AT89S52的P3.1口来控制的,当超过设置的重量时,通过程序使P3.1口置为低电平,从而使三极管导通,报警电路接通,使蜂鸣器发出报警声,同时使报警灯LED发光。

4 电路的软件设计

根据系统的控制任务,本系统的软件设计主要由主程序、初始化程序、显示子程序、数据采集子程序和延时程序等组成。

4.1 主程序设计

软件主要三个方面:一是初始化系统;二是按键检测;三是数据采集、数据处理并进行显示。这三个方面的操作分别在主程序中来进行。程序采用模块化的结构,这样程序结构清楚,易编程和易读性好,也便于调试和修改。系统上电后,初始化程序将 RAM 的30H~5FH内存单元清零,P3.1引脚置成高电平,防止误报警。

主程序模块主要完成编程芯片的初始化及按需要调用各模块(子程序),程序设计流程图如图4-1所示。

图4-1系统主程序流程图

4.2 子程序设计

系统子程序主要包括A/D转换启动及数据读取程序设计、显示程序设计、键盘输入控制程序设计以及报警子程序的设计等。

4.2.1 A/D转换启动及数据读取程序设计

A/D转换子程序主要是指在系统开始运行时,把称重传感器传递过来的模拟信号转换成数字信号并传递到单片机所涉及到的程序设计。设计流程图如图4-2所示。

图4-2 AD转换子程序设计流程图

4.2.2 显示子程序设计

显示子程序主要是来判断是否需要显示,以及如何去显示,也是十分重要的程序之一。而显示子程序是其他程序所需要调用的程序之一,因此,显示子程序的设计就显得举足轻重,设计的时候也要十分的小心和卖力。本设计含有总价显示程序和数据录入显示程序。设计显示子程序的流程图如下图4-3所示:

图4-3显示子程序流程图

4.2.3 键盘输入控制程序的设计

如图2-5所示:键盘电路设计成4×4矩阵式,在程序中可以先判断按键编码,然后根据编码将键盘代表的数值送到相应的存储单元,再进行功能选择或数据处理。键盘扫描子程序的流程图如下:

图4-4键盘扫描子程序流程图

4.2.4 报警子程序的设计

由于要求要键盘设定阈值,所以要求有报警电路,报警电路可以有声报警也可有光报警,将设定的阈值与实时显示的值进行比较,如果设定值小于实时显示的值,则将P3.1置为1,将发光二极管点亮,或使蜂鸣器发出声音。这就需要一段比较程序以及一小段置1清0程序。

图4-5报警子程序流程图

5 总结

随着集成电路和计算机技术的迅速发展,使电子仪器的整体水平发生巨大变化,传统的仪器逐步的被智能仪器所取代。智能仪器的核心部件是单片机,因其极高的性价比得到广泛的应用与发展,从而加快了智能仪器的发展。而传感器作为测控系统中对象信息的入口,越来越受到人们的关注。传感器好比人体“五官”的工程模拟物,它是一种能将特定的被测量信息(物理量、化学量、生物量等)按一定规律转换成某种可用信号输出的器件或装置本次设计中的半桥电子秤就是在以上仪器的基础上设计而成的。因此,只有充分了解有关智能仪器、单片机、传感器以及各部分之间的关系才能达到要求。

通过这次课程设计与仿真,让我更明确的了解了一些芯片的用途功能,也熟练了对它们的运用。在这个设计的过程中,需要不断地思考,不断地请教,需要对知识深入的掌握,去解决设计中存在的一些问题和调试时出现的一些故障。经过软件的最终仿真结果,本设计实现了上述功能,系统可以连续稳定可靠运行,实现了预期功能,完成设计目标。

6 参考文献

[1] 赵广平,孙雯萍,孙建军. 电子称重技术现状及发展趋势[J]. 仪表技术传感器,2007,(07).

[2] 孙莹. 单片机在电子秤中的应用[J]. 仪器仪表用户,2001,(03).

[3] 李燕. 电子秤的结构和工作原理[J]. 物理通报,2006,(06).

[4] 张海霞等. 新型便携式电子秤设计[J]. 计量技术,2005,(09).

[5] 谭浩强.C程序设计.2005,(7).

[6] 杨凌霄. 单片机原理及应用技术 .2007,(10).

[7]全国大学生电子设计竞赛组委会.全国大学生电子设计竞赛获奖作品汇编[J].北京理工大学出版社.2005,(11).

[8]艾永乐等.模拟电子技术.中国电力出版社.2008,(8).

[9]康华光等.电子技术基础(数字部分).高等教育出版社.2006,(1).

附录

附录1 元件清单及其参数

附录2 系统总图

附录3 电子称主程序

void main()

{   uchar temp;

    lcd_init();

    clear_screen(0);

    lcd_display_hanzi(1,0,0,0);

    lcd_display_hanzi(1,0,1,1);

    lcd_display_shuzi(1,0,4,10);

    lcd_display_hanzi(1,1,0,2);

    lcd_display_hanzi(1,1,1,3);

    lcd_display_shuzi(1,1,4,10);

    lcd_display_hanzi(1,2,0,3);

    lcd_display_hanzi(1,2,1,4);

    lcd_display_shuzi(1,2,4,10);

   k=0;

 while(1)

  {ad();//模数转换

      changs(); //重量数据处理

      display();//重量数据显示

      P1=0xf0;  //按键判断

      temp=P1;

     temp=temp&0xf0;

     if(temp!=0xf0)

       {jianpan();//调键盘程序

         if(k==1)//判断是数字输入则变数据

            {dap=0;//显示单价

             datainput();//数据处理与显示

            }

        if(k=='.')

           { lcd_display_shuzi(1,1,4+s,11);

          dip=1;

          }

        if(k=='=')//如果是等号输入则调计算程序

           {s=0;dap=1;//显示金额,S为第几次按键识别

            display2();  //金额处理及显示程序

           }

        if(k==' ')//清屏

          { n=0;date=0;date1=0;date2=0;dap=0;//数据为0

           k=0;speak=1;dip=0;bb=0;s=0;data3=0;

          str_TME1[0]=0;

          str_TME1[1]=0;

          str_TME1[2]=0;

          str_TME1[3]=0;clear_screen(0);

       lcd_display_hanzi(1,0,0,0);

       lcd_display_hanzi(1,0,1,1);

       lcd_display_shuzi(1,0,4,10);

       lcd_display_hanzi(1,1,0,2);

       lcd_display_hanzi(1,1,1,3);

       lcd_display_shuzi(1,1,4,10);

       lcd_display_hanzi(1,2,0,3);

       lcd_display_hanzi(1,2,1,4);

       lcd_display_shuzi(1,2,4,10);

          }

      if(k=='-')

         {str_TME1[0]=str_TME[0];

           str_TME1[1]=str_TME[1];

           str_TME1[2]=str_TME[2];

           str_TME1[3]=str_TME[3];

           data3 = data1;

           lcd_display_hanzi(1,3,0,10);       //去

           lcd_display_hanzi(1,3,1,11);       //皮

           lcd_display_shuzi(1,3,4,10);       //:

           lcd_display_shuzi(1,3,5,str_TME1[0]);

           lcd_display_shuzi(1,3,6,11);

           lcd_display_shuzi(1,3,7,str_TME1[1]);

           lcd_display_shuzi(2,3,0,str_TME1[2]);

           lcd_display_shuzi(2,3,1,str_TME1[3]);

         }  

       }

  }

}

C语言完整程序

#include<reg52.h>

#include<LCD.h>

#define uchar unsigned char

#define uint unsigned int

uchar code table[]="0123456789";  //数字

uchar code *weight="Weight:  .   Kg ";//要显示的第一行内容

uchar code *price="Price:";

uchar code *mone="Money:";

uchar code *runout="Runout";

uchar n,k,s,bb=0,data1,dip=0,dap=0,data3=0;//n用来显示总输入,k识别输入字符性质,dap识别显示方式,dip为小数识别,bb小数字位数识别

double sum,money,date,date1,date2;  //sum为重量,money为总金额, date为输入单价, date1单价整数,data3去皮重量

uchar str_TME[]={0,0,0,0,0};//重量显示

uchar money1[]={0,0,0,0,0,0};//金额显示

uchar str_TME1[]={0,0,0,0,0}; //去皮重量

void jianpan() ;//键盘函数申明

sbit speak=P3^1;//报警

void delay(uint z)    //延时1mS函数

{

uint x,y;

for(x=z;x>0;x--)

for(y=10;y>0;y--);

}

/******************************************************************************

                            液晶子程序

*******************************************************************************/

sbit lcden=P2^1;

sbit lcdrs=P2^0;

void write_com(uchar com)   //写指令函数

{

lcdrs=0;

P0=com;

delay(5);

lcden=1;    //en需要下降沿才能写入

delay(5);

lcden=0;

}

void write_data(uchar date)

{

lcdrs=1;

P0=date;

delay(5);

lcden=1;       // en需要下降沿才能写入

delay(5);

lcden=0;

}

void init()  //初始化

{

lcden=0;

write_com(0x38);//功能设置为2行显示,5X7点阵

write_com(0x0c);

write_com(0x06);

write_com(0x01);

}

/**********设置第(xPos,yPos)个字符的地址************/

//参数:xPos为显示第几列,yPos为显示第几行

void LcdPos(uchar xPos, uchar yPos)

{  uchar tmp;

   xPos&=0x0f; //x:0-15

   yPos&=0x01; //y:0-1

   if(yPos==0) //显示第1行

     tmp=xPos;

   else

     tmp=xPos+0x40;

   tmp|=0x80;

   write_com(tmp);

}

/*********************在指定行列显示指定字符***********/

//参数:xPox 光标所在列  yPos 光标所在行 c 待显示字符

void WriteChar(uchar c, uchar xPos, uchar yPos)

{ LcdPos(xPos, yPos);

  write_data(c);

}

/************显示字符串********************************/

//参数: *s 指向待显示字符串;yPos光标所在行;xPos光标所在列

void WriteString(uchar *s, uchar xPos, uchar yPos)

{ uchar i;

  if(*s==0)   //遇到字符串结束

      return;

  for(i=0;;i++)

  {  if(*(s+i)==0)

        break;

        WriteChar(*(s+i), xPos, yPos);

        xPos++;

        if(xPos>15)

            break;

   }

}

/******************************************************************************

                            AD0832AD转换子程序

*******************************************************************************/

sbit bADcs=P3^5;   //片选位

sbit bADcl=P3^6;   //时钟位

sbit bADda=P3^7;   //数据位

void ad(void)

{   uchar i;

     bADcs = 0;//当ADC0832未工作时其CS输入端应为高电平,此时芯片禁用,开始工作CS为低电平

        bADcl=0;  //第一个时钟下降沿前da为1,第二个与第三时钟下降沿前的数据为通道选择

        bADda=1;  //选置起始位

        bADcl=1;

        bADcl=0;   //   1down

        bADda=1;   //通道选择第1位

        bADcl=1;

        bADcl=0;   //   2 down

        bADda=0;   //通道选择第2位,通道选择为1,0选通道0

        bADcl=1;

        bADcl=0;   //   3 down

        bADda=1;

        bADcl=1;

        bADcl=0;   //   4 down

        for(i=8;i>0;i--)

             {           

             data1<<=1;  //从第7位开始,要左移data1=data1<<1

             bADcl=0;

              bADcl=1;

              if(bADda==1) data1|=0x01;  //如果输出1,data1最后一位补1

             }

       bADcs=1;     //转换完后CS置1

}

/******************************************************************************

                            AD0832AD数据处理程序

*******************************************************************************/

void changs()  //数据处理程序

{    

    uchar val_Integer;             //定义整数变量

    unsigned int val_Decimal;      //定义小数变量

       data1 = data1-data3;

    sum=data1*0.0196*2 ;                   //data1*5/255

    val_Integer=(uchar)sum;

    val_Decimal=(unsigned int)((sum-val_Integer)*1000);

    str_TME[3]=val_Decimal%10;

    str_TME[2]=val_Decimal/10%10;

    str_TME[1]=val_Decimal/100;

    str_TME[0]=val_Integer;

}

void display(void)//重量显示程序

{

lcd_display_shuzi(1,0,5,str_TME[0]);

lcd_display_shuzi(1,0,6,11);

lcd_display_shuzi(1,0,7,str_TME[1]);

lcd_display_shuzi(2,0,0,str_TME[2]);

lcd_display_shuzi(2,0,1,str_TME[3]);

lcd_display_hanzi(2,0,2,5);

lcd_display_hanzi(2,0,3,6);

lcd_display_hanzi(2,1,2,7);

lcd_display_hanzi(2,2,2,7);

}

/******************************************************************************

                           总价=单价与重量相乘数据显示程序

*******************************************************************************/

display2()

{

    uchar val_Integer;             //定义整数变量

    unsigned int val_Decimal;      //定义小数变量

    money=sum*date;     //总价计算

       if(money<256)//金额小于256正常显示,超出报警

       {

   

  val_Integer=(uchar)money;

  val_Decimal=(unsigned int)((money-val_Integer)*1000);

       money1[3]=val_Decimal/10%10;

       money1[2]=val_Decimal/100;

       money1[1]=val_Integer%10;

       money1[0]=val_Integer/10;

    lcd_display_shuzi(1,2,5,money1[0]);

       lcd_display_shuzi(1,2,6,money1[1]);

       lcd_display_shuzi(1,2,7,11);

       lcd_display_shuzi(2,2,0,money1[2]);

       lcd_display_shuzi(2,2,1,money1[3]);

    }

       else  //报警

       {

     WriteString(mone,0,1);

     WriteString(runout,7,1);

        speak=0;

       }

}

/******************************************************************************

                       数据录入显示及处理程序

*******************************************************************************/

datainput()

  lcd_display_shuzi(1,1,4+s,n);

if(s>3)

lcd_display_shuzi(2,1,s-4,n);

  if(dip==0)//如果为整数,处理整数办法

   {

   if(s>1)

   date1=date1*10+n;//如果是第二次以上输入,数据处理

   else

   date1=n;//第一次输入数据等于输入值

   }

   else//小数处理办法,

   {

   if(bb==0)//第一位小数

   date2=n*0.1;

   if(bb==1)//第二小数,只能处理两位,第三位不处理,但能显示

   date2=date2+n*0.01;

   bb++;   //小数位识别加1

   }

   date=date1+date2;//录入数据等于整数加小数

   k=0;//输完一次则K置0

}

void main()

{

  uchar temp;

       lcd_init();

       clear_screen(0);

       lcd_display_hanzi(1,0,0,0);

       lcd_display_hanzi(1,0,1,1);

       lcd_display_shuzi(1,0,4,10);

       lcd_display_hanzi(1,1,0,2);

       lcd_display_hanzi(1,1,1,3);

       lcd_display_shuzi(1,1,4,10);

       lcd_display_hanzi(1,2,0,3);

       lcd_display_hanzi(1,2,1,4);

       lcd_display_shuzi(1,2,4,10);

   k=0;

 while(1)

  {

    

      ad();//模数转换

      changs(); //重量数据处理

      display();//重量数据显示

      P1=0xf0;  //按键判断

      temp=P1;

     temp=temp&0xf0;

     if(temp!=0xf0)

       {

         jianpan();//调键盘程序

         if(k==1)//判断是数字输入则变数据

            {

             dap=0;//显示单价

             datainput();//数据处理与显示

            }

        if(k=='.')

           {

                 lcd_display_shuzi(1,1,4+s,11);

                 dip=1;

                 }

        if(k=='=')//如果是等号输入则调计算程序

           {

            s=0;dap=1;//显示金额,S为第几次按键识别

            display2();  //金额处理及显示程序

           }

        if(k==' ')//清屏

          {

                 n=0;date=0;date1=0;date2=0;dap=0;//数据为0

           k=0;speak=1;dip=0;bb=0;s=0;data3=0;

                 str_TME1[0]=0;

                 str_TME1[1]=0;

                 str_TME1[2]=0;

                 str_TME1[3]=0;

           clear_screen(0);

              lcd_display_hanzi(1,0,0,0);

              lcd_display_hanzi(1,0,1,1);

              lcd_display_shuzi(1,0,4,10);

              lcd_display_hanzi(1,1,0,2);

              lcd_display_hanzi(1,1,1,3);

              lcd_display_shuzi(1,1,4,10);

              lcd_display_hanzi(1,2,0,3);

              lcd_display_hanzi(1,2,1,4);

              lcd_display_shuzi(1,2,4,10);

          }

         if(k=='-')

                {

                   str_TME1[0]=str_TME[0];

                     str_TME1[1]=str_TME[1];

                     str_TME1[2]=str_TME[2];

                     str_TME1[3]=str_TME[3];

                     data3 = data1;

                     lcd_display_hanzi(1,3,0,10);       //去

                     lcd_display_hanzi(1,3,1,11);       //皮

                     lcd_display_shuzi(1,3,4,10);       //:

                     lcd_display_shuzi(1,3,5,str_TME1[0]);

                     lcd_display_shuzi(1,3,6,11);

                     lcd_display_shuzi(1,3,7,str_TME1[1]);

                     lcd_display_shuzi(2,3,0,str_TME1[2]);

                     lcd_display_shuzi(2,3,1,str_TME1[3]);

                }  

       }

  }

}

/******************************************************************************

                           键盘子程序

*******************************************************************************/

 void jianpan()

{ uchar temp;

  EX1=0;

  P1=0xfe;//判断7、8、9、。

  temp=P1;

  temp=temp&0xf0;//判断有无按键

  if(temp!=0xf0)

  {

    delay(5);

       temp=P1;

    temp=temp&0xf0;

       while(temp!=0xf0)//有按键

       {

         temp=P1;

         switch(temp)

         {

           case 0xee:n=7;k=1,s++;break;//K为数字与功能的判断

           case 0xde:n=8;k=1,s++;break;

           case 0xbe:n=9;k=1,s++;break;

           case 0x7e:k='.';s++;break;        

      }

         while(temp!=0xf0)//等待按键放开

         {

          temp=P1;

        temp=temp&0xf0;

         }

       }

  }

  P1=0xfd;

  temp=P1;

  temp=temp&0xf0;

  if(temp!=0xf0)

  {

    delay(5);

       temp=P1;

    temp=temp&0xf0;

       while(temp!=0xf0)

       {

         temp=P1;

         switch(temp)

         {

           case 0xed:n=4;k=1;s++;break;

           case 0xdd:n=5;k=1;s++;break;

           case 0xbd:n=6;k=1;s++;break;

         }

         while(temp!=0xf0)

         {

          temp=P1;

        temp=temp&0xf0;

         }

       }

  }

  P1=0xfb;

  temp=P1;

  temp=temp&0xf0;

  if(temp!=0xf0)

  {

    delay(5);

       temp=P1;

    temp=temp&0xf0;

       while(temp!=0xf0)

       {

         temp=P1;

         switch(temp)

         {

           case 0xeb:n=1;k=1;s++;break;

           case 0xdb:n=2;k=1;s++;break;

           case 0xbb:n=3;k=1;s++;break;

              case 0x7b:k='-';break;

        

         }

         while(temp!=0xf0)

         {

          temp=P1;

        temp=temp&0xf0;

         }

       }

  }

  P1=0xf7;

  temp=P1;

  temp=temp&0xf0;

  if(temp!=0xf0)

  {

    delay(5);

       temp=P1;

    temp=temp&0xf0;

       while(temp!=0xf0)

       {

         temp=P1;

         switch(temp)

         {

           case 0xe7:k=' ';break;

           case 0xd7:n=0;k=1;s++;;break;

           case 0xb7:k='=';break;

         

         }

         while(temp!=0xf0)

         {

          temp=P1;

        temp=temp&0xf0;

         }

        } 

  }

 }

相关推荐