资源描述
一 实验目的
1、能用矩阵键盘设置单价,加重后能同时显示重量、单价和金额;
2、重量显示:单位为千克;最大称重为10千克,重量误差不大于±0.001千克;
3、单价金额及总价金额显示:单价金额和总价金额的单位为元,最大金额数值为99.9元,总价金额误差不大于0.1元;
4、具有去皮功能和锁定屏幕及其解除功能。
二 实验原理
称重电子秤主要以单片机STC89C51RC控制核心,实现电子秤的基本控制功能。系统可以分为最小系统、数据采集、人机交互界面和系统电源四大部分。最小系统部分主要包括STC89C51RC和经典复位电路;数据采集部分由称重传感器、信号放大和A/D转换部分组成,信号放大和A/D转换部分主要由专用型高精度24位AD转换芯片HX711实现;人机交互界面为键盘输入和点阵式液晶显示,主要使用4*4矩阵键盘和1602液晶显示器,可以方便的输入数据和直观的显示数据;系统在称量时还具有超量程报警功能。整个系统结构简单,使用方便,功能齐全,精度高,具有一定的开发价值。
三 硬件电路的设计
1 系统设计原理框图
数据采集
AD转换
单片机处理
LCD显示
计量显示
按键处理
超重报警
图1 系统结构图
由称重传感器采集到的模拟信号,经过A/D转换芯片hx711放大作为输入,经过采样转换为数字信号输入到单片机中,单片机对数据进行处理。若超过量程,蜂鸣器超重报警,如不超过量程,将数据传入LCD中显示重量。其中键盘输入单价,并且单片机处理数据后,送入LCD中显示单机以及金额。
2 Hx711芯片介绍
HX711 是一款专为高精度称重传感器而设计的24位A/D 转换器芯片。
HX711管脚说明如图2所示:
图2 HX711管脚图
HX711管脚描述如表1所示:
表1 HX711管脚描述表
HX711是一款专为高精度称重传感器而设计的24位A/D 转换器芯片。与同类型其它芯片相比,该芯片集成了包括稳压电源、片内时钟振荡器等其它同类型芯片所需要的外围电路,具有集成度高、响应速度快、抗干扰性强等优点。降低了电子秤的整机成本,提高了整机的性能和可靠性。该芯片与后端MCU 芯片的接口和编程非常简单,所有控制信号由管脚驱动,无需对芯片内部的寄存器编程。输入选择开关可任意选取通道A 或通道B,与其内部的低噪声可编程放大器相连。通道A 的可编程增益为128 或64,对应的满额度差分输入信号幅值分别为±20mV 或±40mV 。通道B 则为固定的32 增益,用于系统参数检测。芯片内提供的稳压电源可以直接向外部传感器和芯片内的A/D 转换器提供电源,系统板上无需另外的模拟电源。芯片内的时钟振荡器不需要任何外接器件。上电自动复位功能简化了开机的初始化过程。
高精度高增益24位A/D芯片HX711具有以下特点:
1) 两路可选择差分输入;
2) 片内低噪声可编程放大器,可选增益为64 和128;
3) 片内稳压电路可直接向外部传感器和芯片内A/D 转换器提供电源;
4) 片内时钟振荡器无需任何外接器件,必要时也可使用外接晶振或时钟;
5) 上电自动复位电路;
6) 简单的数字控制和串口通讯:所有控制由管脚输入,芯片内寄存器无需编程;
7) 可选择10Hz 或80Hz 的输出数据速率;
8) 同步抑制50Hz 和60Hz 的电源干扰;
9) 耗电量(含稳压电源电路):典型工作电流:< 1.7mA, 断电电流:< 1μA ;
10) 工作电压范围:2.6 ~ 5.5V ;
高精度高增益24位A/D芯片HX711在电子秤应用中的典型电路如图3所示:
图3 HX711在电子秤应用中的典型应用方案图
3 LCD1602芯片介绍
1602LCD主要技术参数:
显示容量:16×2个字符
芯片工作电压:4.5—5.5V
工作电流:2.0mA(5.0V)
模块最佳工作电压:5.0V
字符尺寸:2.95×4.35(W×H)mm
1602LCD采用标准的16脚(带背光)接口,各引脚接口说明如表2所示
编号
符号
引脚说明
编号
符号
引脚说明
1
VSS
电源地
9
D2
数据
2
VDD
电源正极
10
D3
数据
3
VL
液晶显示偏压
11
D4
数据
4
RS
数据/命令选择
12
D5
数据
5
R/W
读/写选择
13
D6
数据
6
E
使能信号
14
D7
数据
7
D0
数据
15
BLA
背光源正极
8
D1
数据
16
BLK
背光源负极
表2 LCD1602引脚说明
4 单片机最小电路设计
系统主控电路由AT89S52单片机及晶振电路和复位电路组成,该电路作为整个系统功能实现的核心单元,其连接方式如图4所示
图4 单片机最小系统原理图
5 hx711硬件电路的设计
使用内部时钟振荡器的输出数据速率,电源直接取用与MCU芯片相同的供电电源。并且使用通道A和传感器输出连接。如图5 hx711硬件原理图所示
图5 hx711硬件原理图
6 电源电路设计
由于该系统中 51 单片机及 AD 转换芯片及液晶显示器所需供电电压均为 5V 电压,所以要保证系统稳定可靠的工作,需要设计一个可以稳定提供 5V 电压的供电系统。本设计采用USB 接口供电方便程序调试,系统电源输入接口要加滤波电容以确保工作电压稳定。电源输出接口加上LED 电源指示灯,用来判定电源是否正常工作。该系统电源电路设计如图 6所示
图6 电源电路原理图
7 显示电路设计
显示部分采用LCD1602液晶显示模块,液晶板上排列着若干 5×7或 5×10点阵的字符显示位,每个显示位可显示1个字符,从规格上分为每行 8、16、20、24、32、40位,有一行、两行及四行三类。其与单片机的连接电路如图7所示
图7 显示电路原理图
8 报警电路设计
超重报警指示电路用来在称重测量超出最高值时报警提示,以免重量太高的情况下损坏传感器。报警指示电路由PNP三极管9012驱动蜂鸣器来实现,单片机IO口控制三极管的基极,当单片机的IO口输出为低电平时,三极管导通,蜂鸣器的正极与电源接通,蜂鸣器通电发出报警声,当单片机IO口输出高电平时,三极管截止,蜂鸣器停止报警。报警指示电路如图8所示
图8 报警电路原理图
9 键盘电路设计
按键输入电路用来在电子称测量过程中输入单价值,按键输入电路采用4*4矩阵键盘实现,矩阵键盘电路如图9所示
图9 键盘电路原理图
四 系统软件设计
1系统主程序设计
主程序模块主要完成编程芯片的初始化及按需要调用各模块(子程序),在系统初始化过程中,将系统设置成10Kg量程,并写出量程标志。主程序软件流程如图1所示。
图1 系统主程序流程图
2 A/D转换启动及数据读取程序设计
A/D转换子程序主要是指在系统开始运行时,把称重传感器传递过来的模拟信号转换成数字信号并传递到单片机所涉及到的程序设计。设计流程图如图2所示。
开始
启动A/D转换
A/D转换完?成?、、
数据储存
数据显示
图 2 A/D转换程序流程图
3键盘模块的设计
在程序中可以先判断按键编码,然后根据编码将键盘代表的数值送到相应的存储单元,再进行功能选择或数据处理。如图3键盘模块流程图所示,
图 3 键盘模块流程图
4 超重报警模块
当个测量重量超过量程时,beep给出低电平信号,驱动蜂鸣器导通发出警报
5显示模块设计
通过lcd1602显示物品的重量、单价及金额等。如图 4 显示模块流程图所示。
开始
显示重量
显示单价
显示金额
结束
图 4 显示模块流程图
五 硬件调试
电路板实物做完以后,接下来的工作就是调试。这是理论指导实践最重要的一步。调试工作需要耐心与恒心。所以在调试过程中必须保持冷静的头脑,较强的电路分析能力。一个系统的调试需要软硬件结合调试。
在软硬件结合调试的过程中所遇到的问题:
1、电子电路的设计中对各种影响因素的考虑不够完全,比如在对过电压情况的处理中未作防范措施。
2、系统设计不够优化,有待改善。比如系统的超量程信号直接由单片机送入报警电路,没有设计保护电路再入单片机处理后送入报警电路。
3、显示的调试,在给控制电路上电时,发现了一个奇怪的现象,LCD屏上有“鬼影”,显示的字符不清晰,于是查看1602液晶显示屏的使用手册,发现3脚VL是液晶显示器对比度调整端,接电源时对比度最弱,接电源时对比度最高,对比度高时会产生“鬼影”,在观察LCD接口电路的外围有一个可调电位器,就试着调动电位器,发现屏幕上的字符有变化,把对比度调好后,LCD显示无异常。
六 实验测试数据及分析
传感器输出电压测试
将传感器两端接入5v电压,分别在压力传感器上放置不同重量的砝码,用数字万用表测量传感器两输出端的电压差。测量数据如下表
次数
1
2
3
均值
砝码(kg)
mv
0
0.2
0.2
0.2
0.2
1
1
1
1
1.0
2
1.8
1.8
1.8
1.8
3
2.6
2.6
2.6
2.6
4
3.4
3.4
3.4
3.4
5
4.1
4.1
4.1
4.1
6
4.9
4.9
4.9
4.9
根据测量的结果表明,该传感器输出的线性度很好,误差也很好。而且hx711转换芯片将模拟量转换为数字量,模拟输入的最大量有供电电压VCC决定,当模拟输入为最大输入时即模拟输入等于VCC,输出数字值也为最大值,因其为24位A/D转换,所以最大的数字输出值为2的24次方,即当输入为5V时,输出为2的24次方,分辨率则为5V/2^24.即输入信号每增加5V/2^24,输出就增加1,所以输出=输入/分辨率。即输入为10mV,由于采用128增益,所以放大后输入电压为1280mV,输出为1280/(5000/2^24)=4294967.296。所以设定系数为4.294。由于该传感器为线性输出,所以测量时只需要更改系数,就可以校准测量结果。
七 总结
采用STC89C51RC单片机计的电子计重秤, 无论是计量精度, 还是稳定性都满足国家对A级电子秤的要求, 它具有较好的标定校准方法, 性能稳定, 操作简单, 价格低廉。该电子秤集合了传感器技术、微计算机技术、数字显示技术于一体、其反应灵敏、准确度高、显示直观,便于使用。通过硬件的少量扩展和软件的修改, 能设计出性能优越的计价秤、电子台秤等, 满足各行各业对现代电子衡器的需求。
本课题软件和硬件相结合,有相当大的难度,同时也有很大的实用性。在做毕业设计的过程中,我的理论和实践水平都有了较大的提高。在本课题的设计中,我熟练掌握了单片机硬件设计和接口技术,同时对称重传感器的原理及应用有了一定的了解,掌握了各种控制电路及其相关元器件的使用。通过这次毕业设计,我不仅学会如何将所学专业知识运用到实际生活中,还学会如何克服未知的困难,解决难题的方法。
八 谢辞
首先要感谢老师给予这样一个锻炼自己的机会,通过这次实验,我完整的学习了一个系统的设计。在本次试验过程中,遇到了很多困难和问题,除了自己独立解决之外,也得到了一些同学的指导与帮助,同学们的耐心讲解与讨论,给了我很大的帮助与支持。
九 参考文献
[1] 郭天祥编著.51单片机C语言教程.电子工业出版社
[2] 黄智伟.全国大学生电子设计竞赛系统设计[M].北京:北京航空航天大学出版社,2006.
[3] 张洪润等.单片机应用设计200例.北京:北京航空航天大学出版社,2006.
[4] 孙鑫、余安萍等编著。VC++深入详解。电子工业出版社
[5] 赵茂泰.智能仪器原理及应用[M].北京:电子工业大学出版社,2004.
[6] 高吉祥.电子仪器仪表设计[M].北京:电子工业出版社,2007.6.
附录
附录一:系统原理图
附录三:程序
主程序
#include "main.h"
#include "LCD1602.h"
#include "HX711.h"
#include "KEY.h"
unsigned long HX711_Buffer = 0;
unsigned long Weight_Maopi = 0,Weight_Shiwu = 0;
char Price_Count = 0;
unsigned char KEY_NUM = 0;
unsigned char Price_Buffer[3] = {0x00,0x00,0x00};
unsigned long Money = 0;
bit Flag_OK = 0;
//****************************************************
//主函数
//****************************************************
void main()
{
Init_LCD1602(); //初始化LCD1602
LCD1602_write_com(0x80); //指针设置
LCD1602_write_word("Welcome to use! "); //开机画面第一行
Delay_ms(2000); //延时2s
loop:Price_Count = 0;
Price_Buffer[0] = 0;
Price_Buffer[1] = 0;
Price_Buffer[2] = 0;
Flag_OK = 0;
LCD1602_write_com(0x80); //指针设置
LCD1602_write_word(" Kg |Y/Kg| Yuan");
LCD1602_write_com(0x80+0x40); //指针设置
LCD1602_write_word("0.000| . |000.0");
maopi: Get_Maopi(); //称毛皮重量
while(1)
{
if( Flag_OK == 0)
{
Get_Weight(); //称重
//显示当前重量
LCD1602_write_com(0x80+0x40);
LCD1602_write_data(Weight_Shiwu/1000 + 0x30);
LCD1602_write_data('.');
LCD1602_write_data(Weight_Shiwu%1000/100 + 0x30);
LCD1602_write_data(Weight_Shiwu%100/10 + 0x30);
LCD1602_write_data(Weight_Shiwu%10 + 0x30);
Money = Price_Buffer[0] * 100 + Price_Buffer[1] * 10 + Price_Buffer[2];
Money = Money * Weight_Shiwu / 1000;
LCD1602_write_com(0x80+0x40+11);
LCD1602_write_data(Money/1000 + 0x30);
LCD1602_write_data(Money%1000/100 + 0x30);
LCD1602_write_data(Money%100/10 + 0x30);
LCD1602_write_data('.');
LCD1602_write_data(Money%10 + 0x30);
}
KEY_NUM = KEY_Scan();
if( KEY_NUM != 0x55) //当返回的不是初值时候,确认按键按下。
{
if(KEY_NUM == 16) //数字A键,去皮功能
{
goto maopi; //去皮
}
if(KEY_NUM == 15) //数字B键清除键,二次测量
{
goto loop;
}
if(KEY_NUM == 12) //数字C输入单价错误时返回上一步
{
Price_Count--;
if( Price_Count < 0)
{
Price_Count = 0;
}
Price_Buffer[Price_Count] = 0; //清除上一个输入的数据
switch(Price_Count)
{
case 0:
LCD1602_write_com(0x80+0x40+6);
LCD1602_write_data(' ');
break;
case 1:
LCD1602_write_com(0x80+0x40+7);
LCD1602_write_data(' ');
break;
case 2:
LCD1602_write_com(0x80+0x40+9);
LCD1602_write_data(' ');
break;
default : break;
}
}
if(KEY_NUM == 13) //数字D键,计算总价
{
Money = Price_Buffer[0] * 100 + Price_Buffer[1] * 10 + Price_Buffer[2];
Money = Money * Weight_Shiwu / 1000;
LCD1602_write_com(0x80+0x40+11);
LCD1602_write_data(Money/1000 + 0x30);
LCD1602_write_data(Money%1000/100 + 0x30);
LCD1602_write_data(Money%100/10 + 0x30);
LCD1602_write_data('.');
LCD1602_write_data(Money%10 + 0x30);
Flag_OK = 1;
}
if(KEY_NUM == 11)
{
Flag_OK = 0;
}
if(KEY_NUM >= 0 && KEY_NUM <= 9) //显示输入的价格值
{
Price_Buffer[Price_Count] = KEY_NUM;
switch(Price_Count)
{
case 0:
LCD1602_write_com(0x80+0x40+6);
LCD1602_write_data(Price_Buffer[0] + 0x30);
break;
case 1:
LCD1602_write_com(0x80+0x40+7);
LCD1602_write_data(Price_Buffer[1] + 0x30);
break;
case 2:
LCD1602_write_com(0x80+0x40+9);
LCD1602_write_data(Price_Buffer[2] + 0x30);
break;
default : break;
}
Price_Count++;
if( Price_Count >= 3)
{
Price_Count = 3;
}
}
}
}
}
//****************************************************
//称重
//****************************************************
void Get_Weight()
{
HX711_Buffer = HX711_Read();
HX711_Buffer = HX711_Buffer/100;
if(HX711_Buffer > Weight_Maopi)
{
Weight_Shiwu = HX711_Buffer;
Weight_Shiwu = Weight_Shiwu - Weight_Maopi; //获取实物的AD采样数值。
Weight_Shiwu = (unsigned int)((float)Weight_Shiwu/4.826+0.05); //计算实物的实际重量
//因为不同的传感器特性曲线不一样,因此,每一个传感器需要矫正这里的4.30这个除数。
//当发现测试出来的重量偏大时,增加该数值。
//如果测试出来的重量偏小时,减小改数值。
//该数值一般在4.0-5.0之间。因传感器不同而定。
//+0.05是为了四舍五入百分位
Buzzer = 1; //关闭警报
}
// else if(HX711_Buffer < Weight_Maopi - 30)
// {
// Buzzer = 0; //负重量报警
// }
// else if(HX711_Buffer > Weight_Maopi + 24970) //大于5Kg的最大量程,报警
// {
// Buzzer = 0;
// }
if(Weight_Shiwu > 6000 || HX711_Buffer < Weight_Maopi - 30)
{
Buzzer = 0;
}
else
{
Buzzer = 1;
}
}
//****************************************************
//获取毛皮重量
//****************************************************
void Get_Maopi()
{
HX711_Buffer = HX711_Read();
Weight_Maopi = HX711_Buffer/100;
}
//****************************************************
//MS延时函数(12M晶振下测试)
//****************************************************
void Delay_ms(unsigned int n)
{
unsigned int i,j;
for(i=0;i<n;i++)
for(j=0;j<123;j++);
}
A/D转换程序
#include "HX711.h"
//****************************************************
//延时函数
//****************************************************
void Delay__hx711_us(void)
{
_nop_();
_nop_();
}
//****************************************************
//读取HX711
//****************************************************
unsigned long HX711_Read(void) //增益128
{
unsigned long count;
unsigned char i;
HX711_DOUT=1;
Delay__hx711_us();
HX711_SCK=0;
count=0;
while(HX711_DOUT);
for(i=0;i<24;i++) //25个脉冲 则选用128增益
{
HX711_SCK=1; //至高 发送脉冲
count=count<<1; //下降沿来时变量count左移一位 右侧补零
HX711_SCK=0; //置低
if(HX711_DOUT)
count++;
}
HX711_SCK=1;
count=count^0x800000;//第25个脉冲下降沿来时,转换数据
Delay__hx711_us();
HX711_SCK=0;
return(count);
}
Lcd显示程序
#include "LCD1602.h"
//****************************************************
//MS延时函数(12M晶振下测试)
//****************************************************
void LCD1602_delay_ms(unsigned int n)
{
unsigned int i,j;
for(i=0;i<n;i++)
for(j=0;j<123;j++);
}
//****************************************************
//写指令
//****************************************************
void LCD1602_write_com(unsigned char com)
{
LCD1602_RS = 0;
LCD1602_delay_ms(1);
LCD1602_EN = 1;
LCD1602_PORT = com;
LCD1602_delay_ms(1);
LCD1602_EN = 0;
}
//****************************************************
//写数据
//****************************************************
void LCD1602_write_data(unsigned char dat)
{
LCD1602_RS = 1;
LCD1602_delay_ms(1);
LCD1602_PORT = dat;
LCD1602_EN = 1;
LCD1602_delay_ms(1);
LCD1602_EN = 0;
}
//****************************************************
//连续写字符
//****************************************************
void LCD1602_write_word(unsigned char *s)
{
while(*s>0)
{
LCD1602_write_data(*s);
s++;
}
}
void Init_LCD1602()
{
LCD1602_EN = 0;
LCD1602_RW = 0; //设置为写状态
LCD1602_write_com(0x38); //显示模式设定
LCD1602_write_com(0x0c); //开关显示、光标有无设置、光标闪烁设置
LCD1602_write_com(0x06); //写一个字符后指针加一
LCD1602_write_com(0x01); //清屏指令
}
键盘扫描程序
#include "KEY.h"
//****************************************************
//矩阵键盘扫描
//****************************************************
unsigned char KEY_Scan()
{
unsigned char temp = 0;
unsigned char com = 0x55 , com1 = 0 , com2 = 0;
P1=0xf0;
if(P1!=0xf0)
{
com1=P1;
P1=0x0f;
com2=P1;
}
P1=0xf0;
while(P1!=0xf0);
temp=com1|com2;
if(temp==0xee)com=1;//数字1
if(temp==0xed)com=4;//数字4
if(temp==0xeb)com=7;//数字7
if(temp==0xe7)com=11;//备用键*号键
if(temp==0xd7)com=0;//数字0
if(temp==0xb7)com=14;//备用键*号键
if(temp==0xde)com=2; //数字2
if(temp==0xdd)com=5; //数字5
if(temp==0xdb)com=8;//数字8
if(temp==0xbe)com=3;//数字3
if(temp==0xbd)com=6; //数字6
if(temp==0xbb)com=9;//数字9
if(temp==0x7e)com=16;//数字A键,去皮功能
if(temp==0x7d)com=15;//数字B键清除键,二次测量
if(temp==0x7b)com=12;//数字C输入单价错误时返回上一步
if(temp==0x77)com=13;//数字D键,计算总价
return(com);
}
展开阅读全文