单片机计算器设计论文_第1页
单片机计算器设计论文_第2页
单片机计算器设计论文_第3页
单片机计算器设计论文_第4页
单片机计算器设计论文_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、目 录原理分析1方案选择12.1主控制芯片12.1.1芯片介绍12.1.2单片机特性12.1.3 参数22.2 显示模块22.3 时钟模块43.电路原理图绘制及仿真43.1元件型号43.2电路原理图53.3仿真结果53.3.1常态下时钟显示63.3.2带小数点的加法运算63.3.3带负数的减法运算63.3.4乘法运算73.3.5除法运算74综合调试74.1硬件电路74.1.1单片机最小系统电路74.1.2时钟电路84.1.3复位电路94.1.4 LCD1602显示电路104.1.5 DS1302电路114.1.6 矩阵键盘电路114.2软件设计124.2.1程序整体框架124.2.2主函数流程

2、图134.2.3时钟显示模式144.2.4计算器模式145.总结16附录一:主函数源程序17附录二:计算器函数22原理分析(陈小波,崔畅,程露)计算器包含了输入按键然后计算再到显示屏显示,主要有3部分构成,输入、计算和显示。采用单片机做主控制单元,从矩阵键盘读取键值送入cpu计算然后将结果送到显示器显示。方案选择(陈小波,崔畅,程露)2.1主控制芯片2.1.1芯片介绍STC89C52是STC公司生产的一种低功耗、高性能CMOS8位微控制器,具有 8K 在系统可编程Flash存储器。STC89C52使用经典的MCS-51内核,但做了很多的改进使得芯片具有传统51单片机不具备的功能。在单芯片上,拥

3、有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。 具有以下标准功能: 8k字节Flash,512字节RAM, 32 位I/O 口线,看门狗定时器,内置4KB EEPROM,MAX810复位电路,3个16 位定时器/计数器,4个外部中断,一个7向量4级中断结构(兼容传统51的5向量2级中断结构),全双工串行口。另外 STC89C52 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU 停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切

4、工作停止,直到下一个中断或硬件复位为止。最高运作频率35MHz,6T/12T可选。2.1.2单片机特性STC89C52RC单片机:8K字节程序存储空间;512字节数据存储空间;内带2K字节EEPROM存储空间;可直接使用串口下载;2.1.3 参数1. 增强型8051单片机,6 时钟/机器周期和12 时钟/机器周期可以任意 选择,指令代码完全兼容传统8051.2. 工作电压:5.5V3.3V(5V单片机)/3.8V2.0V(3V 单片机)3.工作频率范围:040MHz,相当于普通8051 的080MHz,实际工作 频率可达48MHz4. 用户应用程序空间为8K字节5. 片上集成512 字节RAM

5、6. 通用I/O 口(32 个),复位后为:P0/P1/P2/P3 是准双向口/弱上拉, P0 口是漏极开路输出,作为总线扩展用时,不用加上拉电阻,作为 I/O 口用时,需加上拉电阻。7. ISP(在系统可编程)/IAP(在应用可编程),无需专用编程器,无需专用仿真器,可通过串口(RxD/P3.0,TxD/P3.1)直接下载用户程序,数秒即可完成一片8. 具有EEPROM 功能9. 共3 个16 位定时器/计数器。即定时器T0、T1、T210.外部中断4 路,下降沿中断或低电平触发电路,Power Down 模式可 由外部中断低电平触发中断方式唤醒11. 通用异步串行口(UART),还可用定时

6、器软件实现多个UART12. 工作温度范围:-40+85(工业级)/075(商业级)13. PDIP封装。2.2 显示模块1602液晶也叫1602字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此所以它不能很好地显示图形。1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块。1602采用标准的16脚接口,其中:第1脚:GND为电源地第2脚:VCC接5V电源正极第3脚:V0为液晶显示器对比度

7、调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会 产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。第4脚:RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。第5脚:RW为读写信号线,高电平1时进行读操作,电平0时进行写操作。第6脚:E(或EN)端为使能(enable)端,高电平(1)时读取信息,负跳变时执行指令。第714脚:D0D7为8位双向数据端。第1516脚:空脚或背灯电源。15脚背光正极,16脚背光负极。管脚图如下图所示:图1 LCD1602引脚图2.3 时钟模块DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时

8、时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力。DS1302的引脚排列,其中Vcc1为主电源,VCC2为后备电源。在主电源关闭的情况下,也能保持时钟的连续运行。DS1302由Vcc1或Vcc2两者中的较大者供电。当Vcc2大于Vcc1+0.2

9、V时,Vcc2给DS1302供电。当Vcc2小于Vcc1时,DS1302由Vcc1供电。X1和X2是振荡源,外接32.768kHz晶振。RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据传送的方法。当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。上电运行时,在Vcc>2.0V之前,RST必须保持低电平。只有在SCLK为低电平时,才能将RST置为高电

10、平。I/O为串行数据输入输出端(双向),后面有详细说明。SCLK为时钟输入端。 下图为DS1302的引脚功能图:图2 DS1302引脚图3.电路原理图绘制及仿真(陈小波,崔畅,程露)3.1元件型号本设计主要采用单片机做主控制,所以采用protues仿真。元件型号:AT89C51 x1DS1302 x1LCD1602 x110K排阻 x112Mhz排阻 x1按键 若干电阻 若干电容 若干3.2电路原理图仿真原理图用protues绘制,图中大部分导线连接采用网络标号代替。图3 protues仿真原理图3.3仿真结果 3.3.1常态下时钟显示图4 时钟显示3.3.2带小数点的加法运算图5 带小数的加

11、法3.3.3带负数的减法运算图6 带负数的减法3.3.4乘法运算图7 乘法运算3.3.5除法运算图8 除法运算结果中如果只取前三位的时候,第四位四舍五入。4综合调试(陈小波,崔畅,程露)4.1硬件电路4.1.1单片机最小系统电路单片机的最小系统是由组成单片机系统必需的一些元件构成的,除了单片机之外,还需要包括电源供电电路、时钟电路、复位电路。单片机最小系统电路如图所示。图9 最小系统原理图4.1.2时钟电路单片机工作时,从取指令到译码再进行微操作,必须在时钟信号控制下才能有序地进行,时钟电路就是为单片机工作提供基本时钟的。单片机的时钟信号通常有两种产生方式:内部时钟方式和外部时钟方式。在单片机

12、XTAL1和XTAL2引脚上跨接上一个晶振和两个稳频电容,可以与单片机片内的电路构成一个稳定的自激振荡器。晶振的取值范围一般为024MHz,常用的晶振频率有6MHz、12 MHz、11.0592 MHz、24 MHz等。一些新型的单片机还可以选择更高的频率。外接电容的作用是对振荡器进行频率微调,使振荡信号频率与晶振频率一致,同时起到稳定频率的作用,一般选用2030pF的瓷片电容。电路如下:图10 晶振电路外部时钟方式则是在单片机XTAL1引脚上外接一个稳定的时钟信号源,它一般适用于多片单片机同时工作的情况,使用同一时钟信号可以保证单片机的工作同步。时序是单片机在执行指令时CPU发出的控制信号在

13、时间上的先后顺序。51单片机的时序概念有4个,可用定时单位来说明,包括振荡周期、时钟周期、机器周期和指令周期。振荡周期:是片内振荡电路或片外为单片机提供的脉冲信号的周期。时序中1个振荡周期定义为1个节拍,用P表示。时钟周期:振荡脉冲送入内部时钟电路,由时钟电路对其二分频后输出的时钟脉冲周期称为时钟周期。时钟周期为振荡周期的2倍。时序中1个时钟周期定义为1个状态,用S表示。每个状态包括2个节拍,用P1、P2表示。机器周期:机器周期是单片机完成一个基本操作所需要的时间。一条指令的执行需要一个或几个机器周期。一个机器周期固定的由6个状态S1S6组成。指令周期:执行一条指令所需要的时间称为指令周期。一

14、般用指令执行所需机器周期数表示。51单片机多数指令的执行需要1个或2个机器周期,只有乘除两条指令的执行需要4个机器周期。4.1.3复位电路无论是在单片机刚开始接上电源时,还是运行过程中发生故障都需要复位。复位电路用于将单片机内部各电路的状态恢复到一个确定的初始值,并从这个状态开始工作。单片机的复位条件:必须使其RST引脚上持续出现两个(或以上)机器周期的高电平。单片机的复位形式:上电复位、按键复位。上电复位和按键复位电路如下。上电复位电路中,利用电容充电来实现复位。在电源接通瞬间,RST引脚上的电位是高电平(Vcc),电源接通后对电容进行快速充电,随着充电的进行,RST引脚上的电位也会逐渐下降

15、为低电平。只要保证RST引脚上高电平出现的时间大于两个机器周期,便可以实现正常复位。按键复位电路中,当按键没有按下时,电路同上电复位电路。如在单片机运行过程中,按下RESET键,已经充好电的电容会快速通过200电阻的回路放电,从而使得RST引脚上的电位快速变为高电平,此高电平会维持到按键释放,从而满足单片机复位的条件实现按键复位。按键复位图如下:图11 复位电路4.1.4 LCD1602显示电路LCD1602显示电路图如下,该部分主要负责常态的时钟显示,计算器模式时按键数字以及结果的显示,使得系统更加直观。图12 LCD1602电路4.1.5 DS1302电路DS1302负责时钟显示部分的数据

16、,能在单片机掉电的情况下使用备用电池维持时间的正常。主要电路如下:图13 DS1302电路4.1.6 矩阵键盘电路本系统键盘输入采用4x4矩阵键盘,键盘包括0-9以及加减乘除小数点等按键。电路图如下:图14 矩阵键盘电路该矩阵键盘带中断,当有按键发生只有产生一个终端请求,单片机跳入终端读取键值,改设计可以使IO复用,在没有按键事件发生的时候按键接的IO口可以正常的数据输入输出,并使得单片机不用一直扫描按键,CPU工作量大大降低。4.2软件设计本系统所有代码全部采用C语言编写,keil编译调试。程序整体框架包含信息采集和信息显示两方面。首先由MCU主控制从外部矩阵键盘读入键值,时钟芯片读取时间等

17、,然后控制液晶显示器的不同功能显示。4.2.1程序整体框架MCU主控芯片LCD显示读取时间矩阵键盘 图15 程序整体框架主函数只要处理两个大任务,分别为时钟显示和计算器模式。有一个外部中断按键控制切换显示器显示。上电复位之后开始外围器件的初始化,初始化完成开始读取有外部中断连接的独立按键KEY1,键值默认为0,键值为0的时候系统处于时钟显示模式,显示当前时间以及日期。当检测到有按键按下后,键值取反为1,当键值为1的时候主函数执行计算器模式,开始矩形键盘的扫描,扫描到的键值全部存入数组待处理。再次触发按键键值再次取反,从计算器模式中挑出,并清空存键值数组数据。系统再次进去时钟显示模式。交替运行互

18、不干扰,以实现整个系统任务。4.2.2主函数流程图结束读取键值计算器模式时钟显示模式0 ?1?初始化开始 图16 主函数流程图4.2.3时钟显示模式单片机从IO口读取外设DS1302输出的数据,读取完成后存入数组,由于DS1302读出的事BCD码,所以要对其进行处理转化为10进制码以便显示。转换完成后送1602显示,显示完成继续读取重复以上步骤,实现数据时间实时更新效果。DS1302外部接有备用电池,单片机以及芯片电源断开的时候,备用电池供电时间不短依旧在持续运行,故下次单片机上电可直接读取到当前时间,送显示。4.2.4计算器模式当单片机进去计算器模式后,LCD显示清除屏幕,等待读取输入键值的

19、显示。矩阵不停行列扫描,有按键按下后进行判断为哪一位的键值,存数组并送显示。等号键按下为本次输入的结束标志,呆等号键松开后,进入计算器函数,先遍历一边数组,首先判断是否有多个符号输入,当有多个符号输入的时候分几种情况,有一个或者两个负数的输入,一个负号输入的时候有判断前一个数为负或者后一个为负,进行不同的处理。当检测到的多个符号并不属于负号输入的时候跳出并显示ERROR表示输入错误。当负号判断处理完成之后把运算负号存入一个标志位,然后对数组数据进行由字符到数值的处理,处理完成后进入对应负号的计算,计算出结果并显示。显示完成等待任意按键清除屏幕以及数组并等待下一次的输入。本系统加入了小数点的输入

20、,当检测到小数点的时候会对相应数值处理并以float形式进行保存和运算。图17 错误输入演示最后显示的结果分有小时和没显示显示,有小数的时候默认显示小数点后3位小时,没有小数点的时候不显示小数。图18 结果小数显示另外结果可显示负数结果。图19 结果负号显示5.总结(陈小波,崔畅,程露)本次实验刚开始认为比较简单,想法方案没有仔细想就采用了一个笨方法,加之对C语言的一些库函数的不熟悉,导致走了很多弯路。最后在大神同学的指导启发下对方案进行了大的调整,花了更多的心思,写了更少量的代码实现了更多的功能。在此非常感谢大神的帮助。本组在经过一系列的失败以及反思,请教之后完成了作品。感触最深刻的就是不论

21、做什么之前应该先深思方法步骤,不要急于下手,学会用巧妙的办法解决更多的事。收获颇丰!本系统还存在一些可以改进的地方,后期我希望能在时钟显示的基础上加入闹钟,以及时间校准功能,但由于期末来临更多的心思放在了学习上。待期末结束后会进行进一步的功能完整以及方案的完整改进。附录一:主函数源程序#include "reg52.h"#include "1602.h"#include "key_board.h"#include "calculator.h"#include "ds1302.h"#include

22、 <stdio.h>#define const_key_time1 500 /按键去抖动延时的时间bit ucKeySec=0; /被触发的按键编号unsigned int uiKeyTimeCnt1=0; /按键去抖动延时计数器unsigned char ucKeyLock1=0; /按键触发后自锁的变量标志sbit key = P37;void cal_function(void);void button_servce(void);void button_scan(void);static void delay_ms(unsigned int z)unsigned int x,

23、y;for(x=z;x>0;x-)for(y=114;y>0;y-);int main(void) EA=1; /全局中断开 EX1=1; /外部中断0开 IT1=0; /琁T1=0表示电平触发 EX0=1; /外部中断0开 IT0=0; /琁T1=0表示电平触发lcd_init(); /lcd初始化Ds1302_Init(); /DS1302初始化/Ds1302_Write_Time();/Ds1302_Init();while(1)/lcd_write_char('c');button_servce();void button_scan(void)if(key=

24、1)/IO是高电平,说明按键没有被按下,这时要及时清零一些标志位 ucKeyLock1=0; /按键自锁标志清零 uiKeyTimeCnt1=0;/按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。 else if(ucKeyLock1=0)/有按键按下,且是第一次被按下 +uiKeyTimeCnt1; /延时计数器 if(uiKeyTimeCnt1>const_key_time1) uiKeyTimeCnt1=0; ucKeyLock1=1; /自锁按键置位,避免一直触发 ucKeySec=ucKeySec; /触发1号键 void button_servce(void)/

25、button_scan();if(ucKeySec=0) delay_ms(50); Ds1302_Read_Time();delay_ms(50);/读取时间Ds1302_Display();delay_ms(50); /显示时间/button_scan();else if(ucKeySec=1) lcd_clr();/cal_function();/计算器/button_scan(); void cal_function(void)unsigned char temp=0; unsigned char input_buf20; /输入的数据转换为字符串保存unsigned char out

26、put_buf20; /输出的数据保存空间unsigned char *ptr=input_buf; long double output=0; /输出结果,double型unsigned char i;for(i=0; i<sizeof(input_buf); i+) /遍历一遍输入数组,使其清空input_bufi = 0;ptr=input_buf;locateXY(0,0);do/button_scan();if(ucKeySec=0)break;temp = 0;temp = key_board();while(P1&0XF0) != 0XF0); /等待按键弹起swi

27、tch(temp)case 1 : *ptr+ = '1' break;case 2 : *ptr+ = '2' break;case 3 : *ptr+ = '3' break;case 5 : *ptr+ = '4' break;case 6 : *ptr+ = '5' break;case 7 : *ptr+ = '6' break;case 9 : *ptr+ = '7' break;case 10 : *ptr+ = '8' break;case 11 :

28、*ptr+ = '9' break;case 14 : *ptr+ = '0' break;case 15 : *ptr+ = '.' break;case 13 : *ptr+ = '0' break;case 4 : *ptr+ = '+' break;case 8 : *ptr+ = '-' break;case 12 : *ptr+ = '*' break;case 16 : *ptr+ = '/' break; /按键对应符号if(temp) /显示到屏幕上

29、lcd_write_char(*(ptr-1);while(temp!=13);delay_ms(10); /当按键为'='时跳出循环 locateXY(0,0); lcd_write_str(input_buf); lcd_write_str(" ");output = calculator(input_buf); /保存结果if(output = ERROR)locateXY(5,1);lcd_write_str("Error"); /输入错误,在屏幕显示ERRORelseif(output - (long int)output !=

30、 0) /如果结果有小数,转换为小数形式保存字符串sprintf(output_buf,"%.3f",output);elsesprintf(output_buf,"%ld",(long)output); /如果结果是整数,保存为长整数形式保存字符串locateXY(0,1);lcd_write_char('=');lcd_write_str(output_buf);delay_ms(15);do/button_scan();if(ucKeySec=0)break;temp = 0;/"="键进行下一次计算temp =

31、 key_board();while(P1&0XF0) != 0XF0);while(temp=0);lcd_clr(); /清屏void ISR_INT1(void) interrupt 2 if(!INT1) delay_ms(10);/在此处可以添加去抖动程序,防止按键抖动造成错误 if(!INT1) while(!INT1);/等待按键释放 ucKeySec=ucKeySec; void ISR_INT0(void) interrupt 0 if(!INT0) delay_ms(10);/在此处可以添加去抖动程序,防止按键抖动造成错误 if(!INT0) while(!INT0

32、);/等待按键释放 Ds1302_Write_Time(); 附录二:计算器函数#include "calculator.h"static long double count(long double x,long double y,unsigned char sign) /两个数之间的运算(参数一,参数二,符号)switch(sign)case '+' : return (x+y);case '-' : return (x-y);case '*' : return (x*y);case '/' : return

33、 (y=0)? ERROR:(x/y);/除数为0,返回错误return ERROR; /符号错误,返回错误long double calculator(unsigned char *sbuf)long double temp1=0,temp2=0;unsigned char sign=0;unsigned char i=0;unsigned char point_flag=0;for(i=0; sbufi!='0' i+) /遍历一遍数组,看看是否有运算符号if(sbufi = '+' | sbufi = '-' | sbufi = '

34、*' | sbufi = '/')sign = sign + 1; /记录运算符号个数switch(sign)case 1: if(sbuf0>'9' | sbuf0<'0') /运算符号为1个,如果第一个字符不是数字返回错误return ERROR;for(i=0,point_flag=0; ; i+) /把符号前面的字符串转换为数字if(sbufi='+' | sbufi='-' | sbufi='*' | sbufi='/')sign=sbufi; /sig

35、n保存运算符号break;if(sbufi = '.')/如果数据中有小数i+;point_flag = 1; /小数标志位置为if(point_flag = 0) /如果是整数部分temp1 = temp1*10 + (sbufi - 0x30);/上一次乘以10加上这次else /小数部分temp1 = temp1 + (sbufi-0x30)/(10*point_flag); /上次结果加上本次除以10的n次阶乘point_flag = point_flag * 10;if(sbuf+i = '0') /如果最后一个字符是符号返回错误return ERRO

36、R;for(point_flag=0; sbufi!='0' i+) /把符号后面的字符串转换为数字if(sbufi = '.')i+;point_flag = 1;if(point_flag = 0)temp2 = temp2*10 + (sbufi - 0x30);else temp2 = temp2 + (sbufi-0x30)/(10*point_flag);point_flag = point_flag * 10;break;case 2: if(sbuf0 = '-')if(sbuf1>'9' | sbuf1&l

37、t;'0') /如果第一个字符是负号,第二个字符不是数字返回错误return ERROR;for(i=1,point_flag=0;i+) /把符号前面的字符串转换为数字if(sbufi='+' | sbufi='-' | sbufi='*' | sbufi='/')sign=sbufi; /sign保存运算符号break;if(sbufi = '.')i+;point_flag = 1;if(point_flag = 0)temp1 = temp1*10 + (sbufi - 0x30);else

38、 temp1 = temp1 + (sbufi-0x30)/(10*point_flag);point_flag = point_flag * 10;temp1 = temp1 * -1;if(sbuf+i = '0') /如果最后一个字符是符号返回错误return ERROR;for(point_flag=0;sbufi!='0'i+) /把符号后面的字符串转换为数字if(sbufi = '.')i+;point_flag = 1;if(point_flag = 0)temp2 = temp2*10 + (sbufi - 0x30);else temp2 = temp2 + (sbufi-0x30)/(10*point_flag);point_flag = point_flag * 10;elsefor(i=0,point_flag=0;i+) /把符号前面的字符串转换为数字if(sbufi='+' | sbufi='-' | sbufi='*' | sbufi='/')sign=sbufi;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论