基于单片机的电子秤

发布者:SerendipityJoy最新更新时间:2015-12-31 来源: eefocus关键字:单片机  电子秤 手机看文章 扫描二维码
随时随地手机看文章
秤是一种在实际工作和生活中经常用到的测量器具。随着计量技术和电子技术的发展,传统纯机械结构的杆秤、台秤、磅秤等称量装置逐步被淘汰,电子称量装置电子秤、电子天平等以其准确、快速、方便、显示直观等诸多优点而受到人们的青睐。

和传统秤相比较,电子秤利用新型传感器、高精度AD转换器件、单片机设计实现,具有精度高、功能强等特点。本课题设计的电子秤具有基本称重、键盘输入、计算价格、显示、超重报警功能。该电子秤的测量范围为0-10Kg,测量精度达到5g,有高精度,低成本,易携带的特点。电子秤采用液晶显示汉字和测量记过,比传统秤具有更高的准确性和直观性。另外,该电子秤电路简单,使用寿命长,应用范围广,可以应用于商场、超市、家庭等场所,成为人们日常生活中不可少的必需品。

一、功能描述

1、采用高精度电阻应变式压力传感器,测量量程0-10kg,测量精度可达5g。

2、采用电子秤专用模拟/数字(A/D)转换器芯片hx711对传感器信号进行调理转换,HX711 采用了海芯科技集成电路专利技术,是一款专为高精度电子秤而设计的24 位A/D 转换器芯片。

3、采用STC89C52单片机作为主控芯片,实现称重、计算价格等主控功能。

4、采用128*64汉字液晶屏显示称重重量、单价、总价等信息。

5、采用4*4矩阵键盘进行人机交互,键盘容量大,操作便捷。

6、具有超量程报警功能,可以通过蜂鸣器和LED灯报警。

7、系统通过USB电源供电,单片机程序也可通过USB线串行下载。

二、硬件设计

1、硬件方案

单片机电子秤硬件方案如图1所示:

图1  单片机电子秤硬件方案

称重传感器感应被测重力,输出微弱的毫伏级电压信号。该电压信号经过电子秤专用模拟/数字(A/D)转换器芯片hx711对传感器信号进行调理转换。HX711 采用了海芯科技集成电路专利技术,是一款专为高精度电子秤而设计的24 位A/D 转换器芯片,内置增益控制,精度高,性能稳定。HX711芯片通过2线串行方式与单片机通信。单片机读取被测数据,进行计算转换,再液晶屏上显示出来。

矩阵键盘主要用于计算金额。当被测物体重量得到后,用户可以通过矩阵键盘输入单价,电子秤自动计算总金额并在液晶屏显示。电源系统给单片机、HX711电路及传感器供电。

2、称重传感器

传感器是测量机构最重要的部件。称重传感器本身具有单调性,其主要参数指标是灵敏度、总误差和温度漂移。

(1) 灵敏度

称重传感器的电灵敏度为满负荷输出电压与激励电压的比值,典型值是2mV/V。当使用2 mV/V灵敏度和5 V激励电压的传感器时,其满度输出电压为10 mV。通常,为了使用称重传感器线性度最好的一段称重范围,应当仅使用满度范围的三分之二。因此满度输出电压应当大约为6mV。当电子秤应用于工业环境时,在6mV满度范围内测量微小的信号变化并非易事。

(2) 总误差

总误差是指输出误差和额定误差的比值。典型电子秤的总误差指标大约是0.02%,这一技术指标相当重要,它限制了使用理想信号调节电路所能达到的精确度,决定了ADC分辨率的选择以及放大电路和滤波器的设计。

(3) 漂移

称重传感器也产生与时间相关的漂移。

目前常用的称重传感器有电阻应变式压力传感器、电容压力传感器、压电式压力传感器。选用时应按稳定行、精度登记、寿命和安装环境要求考虑,其主要特点如下:

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

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

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

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

图2  电阻应变式传感器测量原理

当垂直正压力P作用于梁上时,梁产生形变,电阻应变片R1、R3受压弯拉伸,阻值增加;R2、R4受压缩,阻值减小。电桥失去平衡,产生不平衡电压,不平衡电压与作用在传感器上的载菏P成正比,从而将非电量转化成电量输出。

R1、R2、R3和R4组成惠更斯电桥,将2对电阻应变片的阻值变化转变成输出电压,其工作原理如图3所示。

图3  测量电桥原理

3、电子秤专用24位AD转换芯片HX711及其电路

HX711 采用了海芯科技集成电路专利技术,是一款专为高精度电子秤而设计的24 位A/D 转换器芯片。与同类型其它芯片相比,该芯片集成了包括稳压电源、片内时钟振荡器等其它同类型芯片所需要的外围电路,具有集成度高、响应速度快、抗干扰性强等优点。降低了电子秤的整机成本,提高了整机的性能和可靠性。

该芯片与后端MCU 芯片的接口和编程非常简单,所有控制信号由管脚驱动,无需对芯片内部的寄存器编程。输入选择开关可任意选取通道A 或通道B,与其内部的低噪声可编程放大器相连。通道A 的可编程增益为128 或64,对应的满额度差分输入信号幅值分别为±20mV或±40mV。通道B 则为固定的32 增益,用于系统参数检测。芯片内提供的稳压电源可以直接向外部传感器和芯片内的A/D 转换器提供电源,系统板上无需另外的模拟电源。芯片内的时钟振荡器不需要任何外接器件。上电自动复位功能简化了开机的初始化过程。 HX711内部方框图如图4所示。其外部管脚如图5所示。

图4  HX711内部方框图

图5  HX711外部管脚图

图5为HX711芯片应用于计价秤的一个参考电路图。该方案使用内部时钟振荡器(XI=0),10Hz的输出数据速率(RATE=0)。电源(2.7~5.5V)直接取用与MCU 芯片相同的供电电源。通道A与传感器相连,通道B通过片外分压电阻与电池相连,用于检测电池电压。

图6  HX711计价秤应用参考电路图

   本课题设计的HX711电路如图7所示:

图7  HX711电路

4、单片机STC89C52及其电路

(1) STC89C52 单片机概述

STC89C52系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍,内部集成MAX810专用复位电路。

(2) STC89C52 单片机特点

l        增强型 8051 CPU,1T,单时钟/机器周期,指令代码完全兼容传统8051;

l        工作电压: 5.5V - 3.5V(5V单片机);

l        工作频率范围:0~40MHz,相当于普通8051的 0~80MHz;

l        用户应用程序空间 4K//8K/16k/32K/64K字节;

l        片上集成1280字节 RAM;

l        通用I/O口(32/36个),复位后为准双向口/弱上拉(普通8051传统I/O口);

l        ISP(在系统可编程)/IAP(在应用可编程),无需专用编程器/仿真器。

l        每个I/O口驱动能力均可达到20mA,但整个芯片最大不要超过120mA;

l        可通过串口(P3.0/P3.1)直接下载用户程序,数秒即可完成一片;

l        有EEPROM功能;

l        看门狗;

l        内部集成MAX810专用复位电路(外部晶体12M以下时,复位脚可直接1K电阻到地);

l        时钟源:外部高精度晶体/时钟,内部R/C振荡器;

l        用户在下载用户程序时,可选择是使用内部R/C 振荡器还是外部晶体/ 时钟;

l        常温下内部R/C 振荡器频率为:5.0V 单片机为: 11MHz ~ 17MHz;

l        共4个16位定时器,两个与传统8051兼容的定时器/计数器,16位定时器T0和T1,没有定时器2,但有独立波特率发生器做串行通讯的波特率发生器,再加上2路PCA模块可再实现2个16位定时器;

l        外部中断I/O口4路,传统的下降沿中断或低电平触发中断,并新增支持上升沿中断的PCA模块,Power Down模式可由外部中断唤醒;

l        通用全双工异步串行口(UART) ;

l        工作温度范围:-40 ~ +85℃(工业级) / 0 ~ 75℃(商业级) ;

l        封装:PDIP-40, PLCC-44。

  (3) STC89C52 单片机管脚及封装

STC89C52单片机有多种封装形式,本设计中选用40DIP封装,其管脚定义如图8所示。

图8 STC89C52 管脚图 

本课题设计的电子秤的单片机应用电路如图9所示:

图9  STC89C52单片机电路

图中DOUT和PDSCK为单片机与HX711的AD转换电路交换数据的通信线。beep为蜂鸣器报警信号线,alert为报警灯信号线,RXD和TXD为串口通信线,也可以用于单片机程序的串行ISP下载。

5、液晶屏电路

图10  LCD显示电路

液晶屏电路如图10所示。LCD_CS、LCD_RES、LCD_RS、LCD_SDA、LCD_SCK为液晶模块与单片机接口的控制线。CS_ZK、SCK_ZK、SO_ZK和SI_ZK为字库和单片机接口的控制线。

该液晶为晶讯联公司的128*64汉字屏JLX12864G-086-PC显示信息。该显示模块既可以当成普通的图像型液晶显示模块使用(即显示普通图像型的单色图片功能),又含有JLX-GB2312 字库IC,可以从字库IC 中读出内置的字库的点阵数据写入到LCD 驱动IC 中,以达到显示汉字的目的。其接口引脚功能介绍:

表一  液晶模块接口引脚功能

6、矩阵键盘电路

矩阵键盘电路如图11所示:

图11 矩阵键盘电路

图中4*4矩阵键盘可以显示0-9数字、小数点和五个功能键。键盘行扫描信号为ROW1—ROW4,列扫描信号为COL1—COL4。行信号为输入信号,低电平有效;列信号为输出信号。当没有键按下时,即使行扫描输入低电平信号,列信号仍为高电平;当行扫描为低电平并且有键按下时,相应的列输出低电平。该低电平信号可以定位至按下键的位置。

7、声光报警电路

声光报警电路如图12所示。

图12   声光报警电路

    当测量重量超过量程时,beep和alert给出低电平信号,驱动蜂鸣器鸣响,报警灯亮。

8.电源电路

本设计采用USB接口供电,电源电压5V。同时,USB接口通过内含PL2303芯片的转换电路对单片机进行程序编写。其电路原理如图所示。

图16  供电及程序下载电路

三、Protel硬件开发软件

Protel是目前国内最流行的通用EDA软件,它是将电路原理图设计、PCB板图设计、电路仿真和PLD设计等多个实用工具软件组合后构成的EDA工作平台,是第一个将EDA软件设计成基于Windows的普及型产品。它集成了软件界面、仿真功能和PLD设计和信号完整性分析,在此基础上Protel 99SE又增加了一些新的功能,用户使用更加方便灵活。Protel的功能十分强大,在电子电路设计领域占有极其重要的地位。它以其强大功能和实用性,逐渐获得广大硬件设计人员的青睐,是目前众多EDA设计软件中用户最多的产品之一。

1.Protel软件组成

Protel软件主要由电路原理图设计模块、印制电路板设计模块(PCB设计模块)、电路信号仿真模块和PLD逻辑器件设计模块等组成,各模块具有强大的功能,可以很好的实现电路设计与分析。

(1)  原理图设计模块(Schematic模块)

电路原理图是表示电气产品或电路工作原理的重要技术文件,电路原理图主要由代表各种电子器件的图形符号、线路和结点组成。图4.1所示为一张电路原理图。该原理图是由Schematic模块设计完成的。Schematic模块具有如下功能:丰富而灵活的编辑功能、在线库编辑及完善的库管理功能、强大的设计自动化功能、支持层次化设计功能等。 

(2) 印制电路板设计模块(PCB设计模块)

印制电路板(PCB)制板图是由电路原理图到制作电路板的桥梁。设计了电路原理图后,需要根据原理图生设计成印制电路板的制板图,然后在根据制板图制作具体的电路板。印制电路板设计模块具有如下主要功能和特点:可完成复杂印制电路板(PCB)的设计;方便而又灵活的编辑功能;强大的设计自动化功能;在线式库编辑及完善的库管理;完备的输出系统等。

(3) 电路信号仿真模块

电路信号仿真模块是一个功能强大的数字/模拟混合信号电路仿真器,能提供连续的模拟信号和离散的数字信号仿真。它运行在Protel的EDA/Client集成环境下,与Protel Advanced Schematic原理图输入程序协同工作,作为Advanced Schematic的扩展,为用户提供了一个完整的从设计到验证仿真设计环境。

在Protel中进行仿真,只需从仿真用元器件库中放置所需的元器件,连接好原理图,加上激励源,然后单击防真按钮即可自动开始。

2.PCB板设计

(1)  定元件的封装

① 打开网络表(可以利用一些编辑器辅助编辑),将所有封装浏览一遍,确保所有元件的封装都正确无误并且元件库中包含所有元件的封装,网络表中所有信息全部大写,一面载入出问题,或PCB BOM不连续。

② 标准元件全部采用公司统一元件库中的封装。

③ ④⑥⑤元件库中不存在的封装,应自己建立元器件库。

(2) 建立PCB板框

① 根据PCB结构图,或相应的模板建立PCB文件,包括安装孔、禁布区等相关信息。

② 尺寸标注。在钻孔层中应标明PCB的精确结构,且不可以形成封闭尺寸标注。

(3) 载入网络表

① 载入网表并排除所有载入问题,具体请看《PROTEL技术大全》。其他软件载入问题有很多相似之处,可以借鉴。

② 如果使用PROTEL,网表须载入两次以上(没有任何提示信息)才可以确认载入无误。

(4) 布局

① 首先要确定参考点。

一般参考点都设置在左边和底边的边框线的交点(或延长线的交点)上或印制板的插件的第一个焊盘。

② 一但参考点确定以后,元件布局、布线均以此参考点为准。布局推荐使用25MIL网格。

③ 根据要求先将所有有定位要求的元件固定并锁定。

④ 布局的基本原则

A. 遵循先难后易、先大后小的原则。

B. 布局可以参考硬件工程师提供的原理图和大致的布局,根据信号流向规律放置主要原器件。

C. 总的连线尽可能的短,关键信号线最短。

D. 强信号、弱信号、高电压信号和弱电压信号要完全分开。

E. 高频元件间隔要充分。

F. 模拟信号、数字信号分开。

⑤ 相同结构电路部分应尽可能采取对称布局。

⑥ 按照均匀分布、重心平衡、版面美观的标准来优化布局。

(5) PCB设计遵循的规则

① 地线回路规则:

图17 地线回路规则

环路最小规则,即信号线与其回路构成的环面积要尽可能小,环面积要尽可能小,环面积越小,对外的辐射越少,接收外界的干扰也越小。针对这一规则,在地平面分割时,要考虑到地平面与重要信号走线的分布,防止由于地平面开槽等带来的问题;在双层板设计中,在为电源留下足够空间的情况下,应该将留下的部分用参考地填充,且增加一些必要的过孔,将双面信号有效连接起来,对一些关键信号尽量采用地线隔离,对一些频率较高的设计,需特别考虑其地平面信号回路问题,建议采用多层板为宜。

② 窜扰控制

窜扰(CrossTalk)是指PCB上不同网络之间因较长的平行布线引起的相互干扰,主要是由于平行线间的分布电容和分布电感的作用。克服窜扰的主要措施是:

A.加大平行布线的间距,遵循3W规则。

B.在平行线间插入接地的隔离线。

C.减少布线层与地平面的距离

③ 屏蔽保护

图18  屏蔽保护

对应地线回路规则,实际上也是为了尽量减小信号的回路面积,多用于一些比较重要的信号,如时钟信号,同步信号;对一些特别重要,频率特别高的信号,应该考虑采用铜轴电缆屏蔽结构设计,即将所布的线上下左右用地线隔离,而且还要考虑好如何有效的让屏蔽地与实际地平面有效结合。

④ 走线方向控制规则

相邻层的走线方向成正交结构,避免将不同的信号线在相邻层走成同一方向,以减少不必要的层间窜扰;当由于板结构限制(如某些背板)难以避免出现该情况,特别是信号速率较高时,应考虑用地平面隔离各布线层,用地信号线隔离各信号线。

⑤ 电源与地线层的完整性规则

对于导通孔密集的区域,要注意避免孔在电源和地层的挖空区域相互连接,形成对平面层的分割,从而破坏平面层的完整性,并进而导致信号线在地层 的回路面积增大。

四、  软件设计

1、软件流程图

本设计主程序使用了定时器,用来实现每0.5秒称重一次的功能,流程图如图19所示。键盘扫描程序如图20所示。

                               

    图19  时钟中断程序流程图               图20  键盘扫描程序流程图

主程序软件流程如图21所示。

             

图21  主程序流程图             

3、主程序

    下面介绍main.c主程序编写,其他程序略。

(1)  头文件和一些宏定义

#include

#include

#include

#include "lcd.h"

#include "hx711.h"

#include "keyboard.h"

 

//定义量程系数

#define RATIO     2114/1623

 

(2) 管脚、常量、变量定义

//定义标识

volatile bit FlagTest = 0;                  //定时测试标志,每0.5秒置位,测完清0

volatile bit FlagKeyPress = 0;  //有键按下标志,处理完毕清0

volatile bit FlagSetPrice = 0;  //价格设置状态标志,设置好为1。

 

//管脚定义

sbit LedA = P2^2;

sbit beep = P1^0;

sbit alert = P1^1;

 

//显示用变量

int Counter;

uchar idata str1[6] = "000000";

int i, iTemp;

//称重用变量

unsigned long idata FullScale; //满量程AD值/1000

unsigned long AdVal;     //AD采样值

unsigned long weight;    //重量值,单位g

unsigned long idata price;     //单价,长整型值,单位为分  

unsigned long idata money;     //总价,长整型值,单位为分

//键盘处理变量

uchar keycode;

uchar DotPos;                                    //小数点标志及位置

 

(3) 函数声明

void int2str(int, char *);

void Data_Init();

void Port_Init(); 

void Timer0_Init();

void Timer0_ISR () ;

void INT1_Init();

void KeyPress(uchar);

void To_Zero();

void Display_Price();

void Display_Weight();

void Display_Money();

[page]

(4) 各子程序

//整型转字符串的函数,转换范围0--65536

void int2str(int x, char* str)

{

    int i=1;

    int tmp=10;

    while(x/tmp!=0)

    {

        i++;

        tmp*=10;

    }

    tmp=x;

    str[i]='';

    while(i>1)

    {

        str[--i]='0'+(tmp%10);

        tmp/=10;

    }

    str[0]=tmp+'0';

}

 

//重新找回零点,每次测量前调用

void To_Zero()

{

   FullScale=ReadCount()/1000;

   price=0;

}

 

//显示单价,单位为元,四位整数,两位小数

void Display_Price()

{

   unsigned int i,j;

 

   display_GB2312_string(5,44,"       ");

  

   i = price/100;    //得到整数部分

   j = price - i*100;//得到小数部分

   int2str(i,str1);

   //显示整数部分

   if (i>=1000)

   {

      display_GB2312_string(5,44,str1);

   }

   else if (i>=100)

   {

      display_GB2312_string(5,52,str1);

   }

   else if (i>=10)

   {

      display_GB2312_string(5,60,str1);

   }

   else

   {

      display_GB2312_string(5,68,str1);

   }

   //显示小数点

   display_GB2312_string(5,76,".");  

   //显示小数部分

   int2str(j,str1);

   if (j<10)

   {

      display_GB2312_string(5,84,"0");

      display_GB2312_string(5,92,str1);

 

   }

   else

   {

      display_GB2312_string(5,84,str1);

   }

}

 

//显示重量,单位kg,两位整数,三位小数

void Display_Weight()

{

   unsigned int i,j;

  

   display_GB2312_string(3,60,"      ");

   //weight单位是g

   i = weight/1000;    //得到整数部分

   j = weight - i*1000;//得到小数部分

   int2str(i,str1);

   if (i>=10)

   {

      display_GB2312_string(3,60,str1);

   }

   else

   {

      display_GB2312_string(3,68,str1);

   }

   display_GB2312_string(3,76,".");  

   int2str(j,str1);

   if (j<10)

   {

      display_GB2312_string(3,84,"00");

           display_GB2312_string(3,100,str1);

   }

   else if (j<100)

   {

      display_GB2312_string(3,84,"0");

           display_GB2312_string(3,92,str1);

 

   }

   else

   {

      display_GB2312_string(3,84,str1);

   }

}

 

//显示总价,单位为元,四位整数,两位小数

void Display_Money()

{

   unsigned int i,j;

 

   display_GB2312_string(7,44,"       ");

   if (money>999999)         //超出显示量程

   {

      display_GB2312_string(7,44,"-------");

      return;      

   }  

 

   i = money/100;    //得到整数部分

   j = money - i*100;//得到小数部分

   int2str(i,str1);

   //显示整数部分

   if (i>=1000)

   {

      display_GB2312_string(7,44,str1);

   }

   else if (i>=100)

   {

      display_GB2312_string(7,52,str1);

   }

   else if (i>=10)

   {

      display_GB2312_string(7,60,str1);

   }

   else

   {

      display_GB2312_string(7,68,str1);

   }

   //显示小数点

   display_GB2312_string(7,76,".");  

   //显示小数部分

   int2str(j,str1);

   if (j<10)

   {

      display_GB2312_string(7,84,"0");

      display_GB2312_string(7,92,str1);

 

   }

   else

   {

      display_GB2312_string(7,84,str1);

   }

}

 

//数据初始化

void Data_Init()

{

   price = 0;

   DotPos = 0;

   beep = 1;

   alert = 1;

}

 

//管脚配置

void Port_Init()

{

        

}

 

//定时器0初始化

void Timer0_Init()

{

         ET0 = 1;        //允许定时器0中断

         TMOD = 1;       //定时器工作方式选择

         TL0 = 0x06;    

         TH0 = 0xf8;     //定时器赋予初值

         TR0 = 1;        //启动定时器

}

 

//定时器0中断

void Timer0_ISR (void) interrupt 1 using 0

{

         TL0 = 0x06;

         TH0 = 0xf8;     //定时器赋予初值

 

         //每0.5秒钟刷新重量

    Counter ++;

    if (Counter >= 200)

    {

       FlagTest = 1;

            Counter = 0;

    }

}

 

 

//按键响应程序,参数是键值

//返回键值:

//         7          8    9      10(清0)

//         4          5    6      11(删除)

//         1          2    3      12(未定义)

//         14(未定义) 0    15(.)  13(确定价格)

 

void KeyPress(uchar keycode)

{

   switch (keycode)

   {

      case 0:

      case 1:

      case 2:

      case 3:

      case 4:

      case 5:

      case 6:

      case 7:

      case 8:

      case 9:

              //目前在设置整数位,要注意price是整型,存储单位为分

              if (DotPos == 0)

                    { 

                       //最多只能设置到千位

                            if (price<100000)

                            {

                          price=price*10+keycode*100;

                            }

                    }

                    //目前在设置小数位

                   else if (DotPos==1)  //小数点后第一位

                    {

                       price=price+keycode*10;

                            DotPos++;

                    }

                    else if (DotPos==2)

                    {

                       price=price+keycode;

                    }

                    Display_Price();

              break;

      case 10:   //清零键

              To_Zero();

                    Display_Price();

                    FlagSetPrice = 0;

                    DotPos = 0;

                    break;

           case 11:  //删除键,按一次删除最右一个数字

              if (DotPos==2)

                    {

                       price=price/10;

                            price=price*10;

                            DotPos--;

                    }

                    else if (DotPos==1)

                    {

                       price=price/100;

                            price=price*100;

                            DotPos--;

                    }

                    else if (DotPos==0)

                    {

                       price=price/1000;

                            price=price*100;

                    }

                   Display_Price();

         break;

      case 13:   //确认键

              FlagSetPrice = 1;

                    break;

           case 15:   //小数点按下

                    if (DotPos == 0) 

                    {  

                            DotPos = 1;      //小数点后第一位

                    }

              break;

 

   }

}

 

 

 

 

//===============main program===================//

void main(void)

{

   Rom_CS=1;

   initial_lcd();

   EA = 0;

   Data_Init();

   Port_Init();

   Timer0_Init();

   //初始化完成,开中断

   EA = 1;

   //背光

   LedA = 1;

   clear_screen();    //clear all dots

   display_GB2312_string(1,1,"电子秤初始化....");

   To_Zero();

   display_GB2312_string(1,1,"电子秤初始化成功");

   display_GB2312_string(3,1,"重量:         kg");

   display_GB2312_string(5,1,"单价:         元");

   display_GB2312_string(7,1,"金额:         元");

   Display_Price();  

 

   while(1)

   {

      //每0.5秒称重一次

           if (FlagTest==1)

           {

              //称重,得到重量值weight,单位为g

                    AdVal=ReadCount();

                    weight=FullScale-AdVal/1000;

                    if (weight>0x8000) weight=0;

                    weight=10000*weight/FullScale;

                    weight=weight*RATIO;

                    //如果超量程,则报警

                    if (weight >= 10000)

                    {

                       beep = 0;

                            alert = 0;

                            display_GB2312_string(3,60,"------");

                            display_GB2312_string(7,44,"--------");

                    }

                    //如果不超量程

                    else

                    {

                       beep = 1;

                            alert = 1;

                            //显示重量值

                 Display_Weight();          

                           //如果单价设定好了,则计算价格

            if (FlagSetPrice == 1)

                       {

                          money = weight*price/1000;  //money单位为分

                          //显示总金额

                          Display_Money();

                       }

                       else

                       {

                          display_GB2312_string(7,44,"        ");

                       }

                       //清测试标志

                       FlagTest = 0;

              }

           }

           //获取按键

           keycode = Getkeyboard();

           //有效键值0-15

           if ((keycode<16)&&(FlagKeyPress==0))

           {

              FlagKeyPress = 1;

                    KeyPress(keycode);

                    FlagKeyPress = 0;

           }

           delay(20);

   }

}

五、  下载与调试

提供例程在uVision4环境下编译,如果是其他版本uVision,只需将所有.c和.h 文件拷贝至新建项目,重新编译即可。当编译生成.hex文件后,就可以下载并进行调试了。

1、 USB转串口驱动安装

打开USB驱动文件夹下的PL2303_Prolific_DriverInstaller_v130.exe安装文件,按提示安装USB转串口驱动程序。安装完成后,插入USB下载线后,在[开始]-[控制面板]-[打印机和其他硬件]-[设备管理器],在“端口”分支下有(Prolific USB-to-Serial Comm Port(COMX)。X表示串口号,如果没有说明USB转串口驱动没有安装,须重新安装。记住括号里的COM口号。

图22 成功安装USB转串口驱动示意图

2、 下载程序

打开STC单片机下载软件文件夹,点击运行STC_ISP_V481.exe程序,出现如下界面。

图23 下载软件

正确选择MCU 类型为STC89C52,COM口(与刚才安装的COM号一致),最高波特率和最低波特率选择高速,如果不成功则尝试降低拨特率,并打开正确的.hex数据文件。

点击“Download/下载”按纽,窗口出现提示:

Chinese:正在尝试与 MCU/单片机 握手连接 ...

Connection is failure. You can try:

 1.Give your MCU Power On Reset.

 2.Stop operation, then re-select COM Port.

 3.Because PLCC-DIP/PQFP-DIP Socket trace too long.

 4.Update the STC ISP.exe version.

 5.If still error, your MCU Firmware is error

   or null.

Chinese:连接失败,请尝试以下操作:

 1.在单片机停电状态下,点下载按钮,再给单片机上电

 2.停止下载,重新选择 RS-232 串口, 接好电缆

 3.可能需要先将 P1.0/P1.1 短接到地

 4.可能外部时钟未接

 5.因 PLCC、PQFP 转换座引线过长而引起时钟不振荡,请

   调整参数

 6.可能要升级电脑端的 STC ISP.exe 软件

 7.若仍然不成功,可能 MCU/单片机内无 ISP 系统引导码,

   或需退回升级,或 MCU 已损坏

 8.若使用 USB 转 RS-232 串口线下载,可能会遇到不兼容

   的问题,可以让我们帮助购买兼容的 USB 转 RS-232

   串口线

 

 仍在连接中, 请给 MCU 上电...

 

按下电路板上的电源按纽,保证其有个失电至上电的过程,则窗口显示开始烧录芯片。

六、  运行与使用

1、上电运行

下载完成后程序自动运行,或重上电后程序正常运行,如图23所示。

图23  上电运行图

2、键盘操作说明

4*4矩阵键盘定义如下

         7          8           9           10(清0)

         4          5           6           11(删除)

         1          2           3           12(未定义)

         14(未定义)  0          15(.)         13(确定价格)

其中:

l      键0—9为数字键,用于单价设定。

l      键15为小数点,也用于单价设定。

l      键10为清零键,每次测量之前,请先按清0键,以使重量和价格回零。

l      键11为删除键,逐位删除敲错的单价。

l      键13为单价确定键,按下该键则设定的单价有效,开始计算总价。

3、常用使用步骤:

l      打开电源,屏幕显示电子秤初始化成功,此时重量和单价为0,金额为空;

l      通过数字键和小数点键键入单价,完成后按下单价确定键。

l      在支架上放上待称重物体,液晶屏显示重量(单位为kg),单价(单位为元)和总金额(单位为元)。

l      称重量程为0—10kg,单价设定范围为0.01元—9999.99元,总金额显示范围为0元—9999.99元。超过量程声光报警。

关键字:单片机  电子秤 引用地址:基于单片机的电子秤

上一篇:基于AT89S52单片机直流电机PWM控制系统
下一篇:51单片机P0口上拉电阻的深入研究

推荐阅读最新更新时间:2024-03-16 14:42

使用8051微控制器测量任何信号频率的方式
频率定义为每秒的周期数。它也可以定义为总时间“T”的倒数。在本项目中,我们将计算进入8051微控制器端口3.5的脉冲数,并将其显示在16 * 2 LCD显示屏上。所以基本上我们测量了8051端口3.5的信号频率。这里我们使用了AT89S528051芯片,在非稳定模式下使用555 IC来生成采样脉冲进行演示。 所需组件: 8051 微控制器 (AT89S52) 16*2液晶显示屏 频率源(555 定时器) 电位计 连接线 电路图: 使用 8051 定时器测量频率: 8051微控制器是一款8位微控制器,具有128字节的片上RAM,4K字节的片上ROM,两个定时器,一个串行端口和四个8位端口。8052微控制器是微控制器的扩
[单片机]
使用8051<font color='red'>微控制器</font>测量任何信号频率的方式
MCU系统低功耗设计问题
(1)系统中单片机以外的其它电路器件尽可能选用静态功耗低的器件,如选用CMOS电路芯片。 (2)外部设备的选择也要尽可能支持低功耗设计。 (3)设计外部中断唤醒电路,使单片机在等待时可进人体眠模式或待机模式,需要时由外部中断信号唤醒。 (4)设计外部器件的电源控制电路.使外部器件或设备在不工作时关断供电,减少无效功耗。 (5)设计充分利用系统低功耗特点的软件。
[单片机]
基于8031单片机的工业顺序控制
掌握工业顺序控制程序的简单编程,中断的使用。 实验内容 1.实验原理图: 2.实验内容 8032的P1.0—P1.6控制注塑机的七道工序,现模拟控制七只发光二极管的点亮,高电平有效,设定每道工序时间转换为延时,P3.4为开工启动开关,低电平启动。P3.3为外故障输入模拟开关,P3.3为0时不断告警。P1.7为报警声音输出,设定6道工序只有一位输出,第七道工序三位有输出。 3、实验说明 实验中用外部中断0,编中断服务程序的关键是: (1)保护进入中断时的状态,并在退出中断之前恢复进入状态。 (2)必须在中断程序中设定是否允许中断重入,即设置EX0位。 一般中断程序进入时应保护PSW、ACC以及中断程序使用但非其专用的寄存器,本
[单片机]
基于8031<font color='red'>单片机</font>的工业顺序控制
CMOS型单片机时钟电路图
  MCS-51内部都有一个反相放大器,XTAL1、XTAL2分别为反相放大器输入和输出端,外接定时反馈元件以后就组成振荡器,产生时钟送至单片机内部的各个部件。AT89C51是属于CMOS8位微处理器,它的时钟电路在结构上有别于NMOS型的单片机。   CMOS型单片机内部(如AT89C51)有一个可控的负反馈反相放大器,外接晶振(或陶瓷谐振器)和电容组成振荡器,下图为CMOS型单片机时钟电路框图。振荡器工作受/PD端控制,由软件置“1”PD(即特殊功能寄存器PCON.1)使/PD=0,振荡器停止工作,整个单片机也就停止工作,以达到节电目的。清“0”PD,使振荡器工作产生时钟,单片机便正常运行。图中SYS为晶振或陶瓷谐振器,振荡
[单片机]
CMOS型<font color='red'>单片机</font>时钟电路图
ARM7单片机(学习ing)—(三)、UART—01
三、UART 三—(01)、UART相关应用和寄存器的介绍~~ 一、UART0(UART1与UART0相同,只是增加了一个调制解调器(Moderm)接口~~我就不介绍了~~ 1、特性:(个人感觉特性的了解是入门的必经之路~~尤其是FIFO的性能~~无人能挡啊~~) 1)16字节收发FIFO 2)寄存器位置符合‘550’工业标准 3)接收器FIFO触发点可以为1、4、8、和14字节 4)内置波特率发生器 2、管脚描述: 3、寄存器描述:(这个尤其的重要~~) a、接收缓存寄存器 U0RBR 0XEOOOCOOO, DLAB=0, 只读(它包含了最早接收到的字符~~) b、发送器保持寄存器 U0THR 0X
[单片机]
ARM7<font color='red'>单片机</font>(学习ing)—(三)、UART—01
STM32C0开发(1)----概述
概述 STM32C0系列微控制器是意法半导体公司推出的一款低功耗、高性能的微控制器产品。它们被设计用于需要小型、低功耗和高度可集成的应用程序,如传感器、消费品、电池供电设备、家庭自动化和安全等应用。该系列的微控制器采用ARM Cortex-M0内核,具有丰富的外设。 最近在弄ST和GD的课程,需要样片的可以加群申请:615061293。 样品申请 框架 产品列表 STM32C031最大支持48-pin 管脚,同时flash和RAM可以达到32 K /12 K。 STM32C011最大支持20-pin 管脚,同时flash和RAM可以达到32 K /6 K。 STM32C031比STM32C011功能更强大,但也更
[单片机]
STM32C0开发(1)----概述
HT1621显示屏驱动芯片单片机源程序
HT1621是128 点内存映象和多功能的LCD 驱动器 , HT1621 的软件配置特性使它适用于多种 LCD 应用场合,包括 LCD 模块和显示子系统。用于连接主控制器和HT1621 的管脚只有 4 或 5 条, HT1621 还有一个节电命令用于降低系统功耗。在虎风所做的这个系统中 ht1621 用于驱动一个静态的 LCD 液晶显示器。液晶显示的方式分为静态显示和动态显示 。 静态与动态的区别在于静态显示是持续供电的 , 而动态显示是利用人的视觉停留效果 , 快速扫描数码管各个段 , 让人在视觉上感觉到数码管是同时显示的。 各位大牛下午好,我用STC12C5204单片机控制1621驱动液晶 程序调了几天都没进展,
[单片机]
HT1621显示屏驱动芯片<font color='red'>单片机</font>源程序
座舱域控制器硬件架构方案:SoC + MCU
座舱域控制器是什么 座舱域控制器(Cabin Domain Controller)是一种用于航空飞机中的电子系统,用于集中管理和控制飞机内部的各种功能和系统。它是飞机电气系统的关键组件之一。 座舱域控制器的主要功能是将飞机上的各种设备和系统进行集成和协调,以实现对飞机座舱内部的各种功能和服务的控制和管理。它承担了多个子系统的集中控制和管理任务,包括各种显示系统、通信系统、音视频系统、照明系统、环境控制系统、安全系统等。座舱域控制器通过接收和处理来自这些子系统的命令和数据,控制和协调它们的工作状态,并向座舱内的用户提供各种功能和服务。 座舱域控制器还负责监测和诊断座舱各个子系统的状态和健康状况。它可以通过传感器和数据总线获取各个
[嵌入式]
座舱域控制器硬件架构方案:SoC + <font color='red'>MCU</font>
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved