课程设计电子秤.docx
《课程设计电子秤.docx》由会员分享,可在线阅读,更多相关《课程设计电子秤.docx(21页珍藏版)》请在冰豆网上搜索。
课程设计电子秤
电子信息与电气工程系
课程设计报告
课程设计任务书
设计
题目
电子秤的设计
设计类型
实验研究
导师姓名
李海鲲
赵春江
主要内容及目标
1、课题目的
(1)熟练掌握单片机系统的设计方法。
(2)设计并实现一个简易电子称。
2、设计说1)重量显示。
单位为克,最大称重10千克,重量误差不大于5克。
2)单价金额显示及总价金额显示。
单价金额单位为“分”,最大显示金额为999。
99元,单价误差不大于1分。
明
3、设计要求
(1)方案论证
按系统功能实现要求,决定控制系统的实现方案,选择芯片,作出系统框图。
(2)硬件电路设计
按控制系统的实现方案,作出硬件原理图。
(3)系统程序设计
采用模块化设计方法,作出初始化程序、主程序、显示子程序和模/数转换子程序
(4)调试及仿真
用Keil+Proteus进行软、硬件联合仿真和调试。
4、总结报告
写出完成整个设计的详细步骤和系统性能分析。
具有的设计条件
1、计算机
2、Keil+Proteus仿真软件
计划学生数及任务
计划需要1人
计划设计进程
1、从接题开始收集资料、准备设计
2、第1周画出设计框图,制定设计方案,画出电路原理图,进行实验,
3、第2周电路调试和完善,软件设计、仿真,用Keil+Proteus进行软、硬件联合仿真和调试,同时编写设计报告。
参考文献
1、《单片机原理及应用》孙涵芳等编著北京航空航天大学出版社2001
2、《微型计算机原理》吴秀清等编著中国科技大学出版社2001
关键字
附录
1:
摘要
现代社会的发展,对称重技术提出了更高的要求。
目前,台式电了秤在商业贸易中的使用已相当普遍,但存在较大的局限性:
体积大、成本高、需要工频交流电源供应、携带不便、应用场所受到制约。
现有的便携秤为杆秤或以弹簧压缩、拉伸变形来实现计量的弹簧秤,居民用户使用的是国家已经明令淘汰的丰卜秤。
多年来,人们一直期待测量准确、携带方便、价格低廉的便携式电子秤投放市场。
木文设计了一种便携式电子秤,论述了仪器的工作原理,介绍了仪器的误差来源与误差分配,给出了仪器电路设计与软件流程,探讨了仪器的工程设计技术。
针对电容式称重传感器非线性影响大的问题,提出并建立了电容式称重传感器的非线性影响模型与校正模型,为便携式电子秤的低成本准确称量奠定了理论基础。
便携式电子秤主要由电源、称重传感器、单片机、键盘/开关、LCD显示器等部分构成。
主要技术指标为:
称量范围0^-lOkg;分度值O.Olkg;精度等级m级;电源DC1.5V。
关键字:
电子秤,AT89C51,LCD
2:
方案论证及选择:
2.1:
输入模块
方案一:
采用独立式按键作为输入模块,其特点:
直接用I/O口构成单个按键电路,接口电路配置灵活、软件结构简单,但是当键数较多时,占用I/O口较多;
方案二:
采用矩阵式键盘作为输入电路,其特点:
电路和软件稍复杂,但相比之下,当键数越多时越节约I/O口。
本设计使用键盘输入价格值,若采用独立按键,对数值进行递增递减需频繁按键,为软件设计增加负担,且操作界面不友好。
若采用矩阵式按键,可以方便地输入一个价格值,节约了宝贵的I/O口资源。
通过对比,故采用方案二作为系统输入模块。
2.2:
显示模块
方案一:
用LCD显示,液晶显示屏具有低耗电量,无辐射危险,以及影像不闪烁等优势,可视面积大,画面效果好,分辨率高,抗干扰能力强等特点。
方案二:
采用LED数码管并行动态显示,电路简单,同样的功率驱动下,显示亮度不及静态显示,且占用I/O口较多。
综上所述,我们采用方案一使用了1602型号的的LCD进行显示,能显示出更多的重量值以及显示更大的总额从而扩大了称量范围。
3系统硬件及功能:
3.1单片机控制电路功能及介绍
本设计中单片机控制电路是由AT89C51组成,它是一个低功耗,高性能CMOS8位单片机,片内含4kBytesISP(In-systemprogrammable)的可反复擦写1000次的Flash只读程序存储器,器件采用ATMEL公司的高密度、非易失性存储技术制造,兼容标准MCS-51指令系统及80C51引脚结构,芯片内集成了通用8位中央处理器和ISPFlash存储单元,功能强大的微型计算机的AT89S51可为许多嵌入式控制应用系统提供高性价比的解决方案。
AT89C51具有如下特点:
40个引脚,4kBytesFlash片内程序存储器,128bytes的随机存取数据存储器(RAM),32个外部双向输入/输出(I/O)口,5个中断优先级2层中断嵌套中断,2个16位可编程定时计数器,2个全双工串行通信口,看门狗(WDT)电路,片内时钟振荡器。
图
此外,AT89S51设计和配置了振荡频率可为0Hz并可通过软件设置省电模式。
空闲模式下,CPU暂停工作,而RAM定时计数器,串行口,外中断系统可继续工作,掉电模式冻结振荡器而保存RAM的数据,停止芯片其它功能直至外中断激活或硬件复位。
同时该芯片还具有PDIP、TQFP和PLCC等三种封装形式,以适应不同产品的需求。
3.2A/D转换
8位A/D精度:
10Kg/1204=2.44g
考虑到其他部分所带来的干扰,12位A/D无法满足系统精度要求。
所以我们需要选择14位或者精度更高的A/D。
方案一、逐次逼近型A/D转换器,如:
ADS7805、ADS7804等。
逐次逼近型A/D转换,一般具有采样/保持功能。
采样频率高,功耗比较低,是理想的高速、高精度、省电型A/D转换器件。
高精度逐次逼近型A/D转换器一般都带有内部基准源和内部时钟,基于89C52构成的系统设计时仅需要外接几个电阻、电容。
但考虑到所转换的信号为一慢变信号,逐次逼近型A/D转换器的快速的优点不能很好的发挥,且根据系统的要求,14位AD足以满足精度要求,太高的精度就反而浪费了系统资源。
所以此方案并不是理想的选择。
方案二、双积分型A/D转换器:
如:
ICL7135、ICL7109ADC0808等。
双积分型A/D转换器精度高,但速度较慢(如:
ICL7135),具有精确的差分输入,输入阻抗高,可自动调零,超量程信号,全部输出于TTL电平兼容。
双积分型A/D转换器具有很强的抗干扰能力。
对正负对称的工频干扰信号积分为零,所以对50HZ的工频干扰抑制能力较强,对高于工频干扰(例如噪声电压)已有良好的滤波作用。
只要干扰电压的平均值为零,对输出就不产生影响。
尤其对本系统,缓慢变化的压力信号,很容易受到工频信号的影响。
故而采用双积分型A/D转换器可大大降低对滤波电路的要求。
作为电子秤,系统对AD的转换速度要求并不高,精度上8位的AD足以满足要求。
另外双积分型A/D转换器较强的抗干扰能力,和精确的差分输入,低廉的价格。
综合的分析其优点和缺点,我们最终选择了ADC0808。
3.33×4键盘
3×4键盘采用扫描技术进行识别,处值是七个端口都是高电平,对各行进行扫描时,先令第一列全是低电平,若第一列为低电平就表示一行一列为选中即有键按下,若第二行为低电平即二行一列为选中即有键按下,以此类推就可以对所有的见进行编码了。
3.4LCD显示
1602型号的的LCD是能够显示16列2行的液晶显示器,功率小显示面积大。
4设计思路及程序流程图
压力传感器在我设计的系统中,由于只是仿真层面的所有我用力电位器代替,应为单片机只是采集变化的数字量,A\D转换器是将变化的模拟量即电压量,转化为数字量从而可以用电位器改变电压值得到数字量给单片机。
当改变电位器时就会得到相应的数字量,单片机对数字进行运算处理,处理好的数据就是所称的重量,当要输入物品单价时先把键盘的打开键闭合,此时就启动了键盘,然后输入数值,结束时按下确定键,当输入值超出了范围是系统会把最后一位输入同时对系统确定这时:
单片机就会对数据处理,最终得到总价。
并且显示会没一步进行显示在对应的位置。
软件流程图
5结果仿真
1:
当输入不超出位时:
2:
当输入超出位时:
6.总结与体会
两周的课程设计结束了,虽然不轻松但是我学到是很多知识,尽管单片机我们课堂上学了而且感觉还不错但是在实际应用中会发现很多问题,即使很小的错误都能导致很大的错误,我经常会犯的错误就是重复定义不知为什么但是经过了这个课程设计之后,我会不自觉的注意这个问题,特别当对共阴还是共阳管道应用上,在定义时老会出现反的情况,这样就导致根本就的不到值,还有一个问题是我在写键盘程序时用了死循环,然后在最后把所有模块连接时就出现键盘和称重不能同时进行的情况。
从这次的课程设计中,我真真正正的意识到,在以后的学习中,要理论联系实际,把我们所学的理论知识用到实际当中,学习单机片机更是如此,程序只有在经常的写与读的过程中才能提高。
参考文献
1.《手把手教你学单片机》周兴华著北京航空航天出版社2005.4
2.《单片机原理及接口技术》余锡存曹国华著西安电子科技出版社1999.11
3.李朝青.单片机原理及接口技术(简明修订版).杭州:
北京航空航天大学出版社,1998
4. 李广弟.单片机基础[M].北京:
北京航空航天大学出版社,1994
5. 阎石.数字电子技术基础(第三版).北京:
高等教育出版社,1989
6. 廖常初.现场总线概述[J].电工技术,1999.
附录:
源程序
#include
#include"chushi.h"
#include"jianpan.h"
voidmain()
{voidjianpan();
voiddelay2();
OE=0;//定时1开
TMOD=0x02;
TH1=(65536-400)/256;
TL1=(65536-400)%256;
TR1=1;
ET1=1;
EA=1;
ST=1;
ST=0;
Lcd_Init();
while
(1)
{
if(ctrl==0)
{set=!
set;while(ctrl==0);geat=1;t=0;num5=0;}
if(set==1)
{
jianpan();
}
if(EOC==1&&set==0)
{
OE=1;
num1=P3;
delay2();
OE=0;
delay2();
ST=1;
ST=0;
num1=num1*9999/255;
count[0]=num1%10000/1000;
count[1]=num1%1000/100;
count[2]=num1%100/10;
count[3]=num1%10;
max=num1*up;
count[7]=max%10000000/1000000;
count[8]=max%1000000/100000;
count[9]=max%100000/10000;
count[10]=max%10000/1000;
count[11]=max%1000/100;
count[12]=max%100/10;
count[13]=max%10;
DisplayOneChar(0,1,'j');
DisplayOneChar(1,1,'g');
DisplayOneChar(2,1,':
');
DisplayString(6,1,"max:
");
DisplayOneChar(9,1,count[7]+0x30);
DisplayOneChar(10,1,count[8]+0x30);
DisplayOneChar(11,1,count[9]+0x30);
DisplayOneChar(12,1,count[10]+0x30);
DisplayOneChar(13,1,count[11]+0x30);
DisplayOneChar(14,1,count[12]+0x30);
DisplayOneChar(15,1,count[13]+0x30);
DisplayString(0,0,"dj:
");
DisplayOneChar(3,0,count[0]+0x30);
DisplayOneChar(4,0,count[1]+0x30);
DisplayOneChar(5,0,count[2]+0x30);
DisplayOneChar(6,0,count[3]+0x30);
}
}
}
voiddelay2()
{unsignedchari,j,k;
for(k=2;k>0;k--)
for(i=2;i>0;i--)
for(j=248;j>0;j--);
}
voidLcd_Init(void);
voidLcd_WriteCmd(unsignedcharTempData,unsignedcharBuysC);
voidLcd_WriteData(unsignedcharTempData);
voidLcd_ReadStatus(void);
//unsignedcharLcd_ReadData(void);
voidDisplayOneChar(unsignedcharX,unsignedcharY,unsignedcharDData);
voidDisplayString(unsignedcharX,unsignedcharY,unsignedchar*DData);
voidDelay(unsignedintdelaytime);
voidLcd_WriteData(unsignedcharTempData)
{
Lcd_ReadStatus();
Lcd_Data=TempData;
Lcd_RS=1;
Lcd_RW=0;
Lcd_E=0;
Lcd_E=0;
Lcd_E=1;
}
//写指令
voidLcd_WriteCmd(unsignedcharTempData,unsignedcharBuysC)
{
if(BuysC)Lcd_ReadStatus();
Lcd_Data=TempData;
Lcd_RS=0;
Lcd_RW=0;
Lcd_E=0;
Lcd_E=0;
Lcd_E=1;
}
//读数据
/*unsignedcharLcd_ReadData(void)
{
Lcd_RS=1;
Lcd_RW=1;
Lcd_E=0;
Lcd_E=0;
Lcd_E=0;
Lcd_E=0;
Lcd_E=1;
return(Lcd_Data);
}*/
voidLcd_ReadStatus(void)
{
Delay(500);
}
voidLcd_Init(void)//LCM初始化
{
Lcd_Data=0;
Lcd_WriteCmd(0x38,0);//三次显示模式设置,不检测忙信号
Delay(6000);
Lcd_WriteCmd(0x38,0);
Delay(6000);
Lcd_WriteCmd(0x38,0);
Delay(6000);
Lcd_WriteCmd(0x38,1);//显示模式设置,开始要求每次检测忙信号
Lcd_WriteCmd(0x08,1);//关闭显示
Lcd_WriteCmd(0x01,1);//显示清屏
Lcd_WriteCmd(0x06,1);//显示光标移动设置
Lcd_WriteCmd(0x0C,1);//显示开及光标设置
}
//按指定位置显示一个字符
voidDisplayOneChar(unsignedcharX,unsignedcharY,unsignedcharDData)
{
Y&=0x1;
X&=0xF;//限制X不能大于15,Y不能大于1
if(Y)X|=0x40;//当要显示第二行时地址码+0x40;
X|=0x80;//算出指令码
Lcd_WriteCmd(X,0);//这里不检测忙信号,发送地址码
Lcd_WriteData(DData);
}
//按指定位置显示一串字符
voidDisplayString(unsignedcharX,unsignedcharY,unsignedchar*DData)
{
unsignedcharListLength;
ListLength=0;
Y&=0x1;
X&=0xF;//限制X不能大于15,Y不能大于1
while(DData[ListLength]!
='\0')//若到达字串尾则退出
{
if(X<=0xF)//X坐标应小于0xF
{
DisplayOneChar(X,Y,DData[ListLength]);//显示单个字符
ListLength++;
X++;
}
}
}
voidDelay(unsignedintdelaytime)
{
while(delaytime--);
}
voidt1(void)interrupt3using0
{
clock1=!
clock1;
TH1=(65536-4000)/256;
TL1=(65536-4000)%256;
}
intcount[20],up=0,down=0;
unsignedchartab1[10]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09};
unsignedchartab2[3]={0x9d,0xfd,0xff};
longintnum1,max;
intwd=25,a=0,b=0;
charaa,ab,ac,ad,ae=0,af=0,ag=0;
unsignedcharnum3=0,num4;
floatnum2;
sbitL0=P2^0;sbitL1=P2^1;sbitL2=P2^2;sbitL3=P2^3;
sbitclock1=P2^4;sbitOE=P2^7;sbitST=P2^5;sbitEOC=P2^6;
sbithot=P2^0;sbitcold=P2^1;
sbitlie1=P1^0;sbitlie2=P1^1;sbitlie3=P1^2;
sbithan1=P1^3;sbithan2=P1^4;sbithan3=P1^5;sbithan4=P1^6;
sbitctrl=P1^7;
unsignedchartemp,i,j,key,set=0,geat,t=0,num5,c,d=1;
voidLcd_Init(void);
voidLcd_WriteCmd(unsignedcharTempData,unsignedcharBuysC);
voidLcd_WriteData(unsignedcharTempData);
voidLcd_ReadStatus(void);
unsignedcharLcd_ReadData(void);
voidDisplayOneChar(unsignedcharX,unsignedcharY,unsignedcharDData);
voidDisplayString(unsignedcharX,unsignedcharY,unsignedchar*DData);
voidDelay(unsignedintdelaytime);
sbitLcd_RW=P2^1;
sbitLcd_RS=P2^0;
sbitLcd_E=P2^2;
//sbitKM=P3^7;
//sbitled=P3^4;
//sbitspeak=P3^5;
#defineLcd_DataP0
#defineBusy0x80
voidjianpan()
{
if(geat==1){count[1]=tab1[0];count[2]=tab1[0];count[3]=tab1[0];count[4]=tab1[0];}
geat=0;
P1=0xff;
lie1=0;
temp=P1;
temp=temp&0xf8;
if(temp!
=0xf8)
{for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P1;
temp=temp&0xf8;
if(temp!
=0xf8)
{if(han1==0)key=3;
if(han2==0)key=6;
if(han3==0)key=9;
if(han4==0){key=11;set=0;}
}
while(han1==0||han2==0||han3==0||han4==0);
t++;
if(t==1){up=key;}
if(t==2){up=up*10+key;}
if(t==3){up=up*10+key;}
}
P1=0xff;
lie2=0;
temp=P1;
temp=temp&0xf8;
if(temp!
=0xf8)
{for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P1;
temp=temp&0xf8;
if(temp!
=0xf8)
{if(han1==0)key=2;
if(han2==0)key=5;
if(han3==0)key=8;
if(han4==0)key=0;
}
while(han1==0||han2==0||han3==0||han4==0);
t++;
if(t==1){up=key;}
if(t==2){up=up*10+key;}
if(t==3){up=up*10+key;}
}
P1=0xff;
lie3=0;
temp=P1;
temp=temp&0xf8;
if(temp!
=0xf8)
{for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P1;
temp=temp&0xf8;
if(temp!
=0xf8)
{if(han1==0)key=1;
if(han2==0)key=4;
if(han3==0)key=7;
if(han4==0)key=10;
}
while(han1==0||han2==0||han3==0||han4==0);
t++;
if(t==1){up=key;}
if(t==2){up=up*10+key;}
if(t==3){up=up*10+key;}
if(key==10){t=0;up=0;}