课 程 设 计
系 别: 机械与电子工程系
专 业: 电子信息科学与技术
学 生 姓 名:
学 号:
课程设计题目: 简易计算器的设计
起 迄 日 期: 6月22日~7月4日
课程设计地点:
指 导 教 师:
第一章绪论···················································1
1.1 课程设计的目的················································1
1.2 课程设计的要求················································1
1.2.1 总体设计················································1
1.2.2 硬件设计················································1
1.2.3 软件设计················································2
1.2.4 软、硬件联调············································2
第二章 系统电路设计············································2
2.1 计算器系统设计框架·············································2
2.2 计算器基本设计思路·············································3
2.3 STC12C5A60S2单片机最小系统板简介·····························3
2.3.1 STC12C5A60S2功能介绍··································3
2.3.2 CH452功能介绍··········································6
第三章 系统软件设计············································7
3.1 程序设计流程图·················································7
3.2 算数运算·······················································7
3.3 系统主程序·····················································8
第四章 实验结果分析············································8
4.1 实验使用的仪器·················································8
4.2 测试结果分析···················································8
结束语····························································10
参考文献··························································10
附录·······························································10
第一章 绪论
1.1 课程设计的目的
课程设计是培养和锻炼学生在学习完本门课后综合应用所学理论知识,解决实际工程设计和应用问题的能力的重要教学环节。它具有动手、动脑和理论联系实际的特点,是培养在校工科大学生理论联系实际、敢于动手、善于动手和自主解决设计实践中遇到的各种问题能力的一个重要教学环节。
通过课程设计,要求学生熟悉和掌握微机系统的软件、硬件设计的方法、设计步骤,使学生得到微机开发应用方面的初步训练。让学生或集体讨论设计题目的总体设计方案、编程、软件硬件调试、编写设计报告等问题,真正做到理论联系实际,提高动手能力和分析问题、解决问题的能力,实现由学习知识到应用知识的初步过渡。通过本次课程设计使学生熟练掌握微机系统与接口扩展电路的设计方法。
而本次的课程设计是围绕单片机实现的,是基于STC12C5A60S2单片机的最小系统板搭建的课程设计电路。
1.2 课程设计的要求
设计一计算器,要求至少能完成2位数的加减乘除运算。
1.2.1、总体设计
本阶段的任务是通过调查研究,查阅资料来初步确定系统结构的总体方案,其中主要涉及到硬件和软件的功能划分。
应用系统中硬件和软件具有一定的互换性,即某些功能既可以用硬件实现也可以用软件实现。一般说来,用硬件实现的优点是可以提高系统的工作速度,但会增加电路的复杂性和硬件成本;而用软件代替某些硬件的功能可以使电路简化,便于修改设计,降低硬件成本,但软件工作量增大。
总体设计时,必须在硬件和软件之间权衡,分工明确,然后分头开始设计。
1.2.2、硬件设计
在Proteus环境下,结合课程设计题目,设计硬件原理图,搭建硬件电路。
1.2.3、软件设计
1、采用模块化程序结构设计软件,可将整个软件分成若干功能模块。
2、画出程序流程图。
3、根据流程图,编写源程序。
1.2.4、软、硬件联调
在Proteus环境下,仿真调试程序。
第二章 系统电路设计
2.1 计算器系统设计框架
由于本次试验中用到的最小系统板中的STC12C5A60S2单片机和CH452A芯
片在proteus中没有,所以在proteus仿真中都以atc51单片机仿真。而硬件电路已经搭好,所以选择合适的C语言程序。
51单片机系统: 控制中心和运算中心,将键盘输入的数据进行缓存和处理,最后是将运算的结果送到数码管显示。
4*4键盘: 数值和一些功能键的输入。
复位电路:将单片机系统内的数据清除,以免干扰下一次单片机的操作过程。
晶振电路:为单片机提供工作的时钟脉冲。
2.2计算器基本设计思路
(1)可以进行简单的四则运算,计算结果由数码管显示。
(2)矩阵键盘的16个按键用作数字键(0-9)、功能键(+、- 、*、/)、清除键和等号键。
(3)执行程序:开机显示零,等待键入数值,当键入数字,通过数码管显示出来,当键入+、-、*、/运算符,计算器在内部执行数值转换和存储,并等待再次
键入数值后将显示键入的数值,按等号就会在数码管上输出运算结果。
(4)错误提示:当单片机执行程序中有错误时,会在数码管上显示相应的提示,如:当输入的数值或计算器得到的结果大于计算器的显示范围时,计算器会在数码管上提示溢出;当除数为0时,计算器会在数码管上提示错误,显示255。
基于单片机ATC51的proteus仿真图:
2.3 STC12C5A60S2单片机的最小系统板的简介
1、STC12C5A60S2单片机功能介绍:
STC12C5A60S2/AD/PWM系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。
1.增强型8051CPU,1T,单时钟/机器周期,指令代码完全兼容传统8051;
2. 工作电压:STC12C5A60S2系列工作电压:5.5V-3.3V(5V单片机)STC12LE5A60S2 系列工作电压:3.6V-2.2V(3V单片机);
3. 工作频率范围:0-35MHz,相当于普通8051的0~420MHz;
4. 用户应用程序空间8K /16K / 20K / 32K / 40K / 48K / 52K / 60K / 62K
字节;
5. 片上集成1280字节RAM;
6. 通用I/O口(36/40/44个),复位后为:准双向口/弱上拉(普通8051传统I/O
口),可设置成四种模式:准双向口/弱上拉,推挽/强上拉,仅为输入/高阻,开漏,每个I/O口驱动能力均可达到20mA,但整个芯片最大不要超过55Ma;
7. ISP(在系统可编程)/IAP(在应用可编程),无需专用编程器,无需专用仿真器可通过串口(P3.0/P3.1)直接下载用户程序,数秒即可完成一片;
8. 有EEPROM功能(STC12C5A62S2/AD/PWM无内部EEPROM);
9. 看门狗;
10. 内部集成MAX810专用复位电路(外部晶体12M以下时,复位脚可直接1K电阻到地);
11. 外部掉电检测电路:在P4.6口有一个低压门槛比较器,5V单片机为1.32V,
误差为+/-5%,3.3V单片机为1.30V,误差为+/-3%;
12. 时钟源:外部高精度晶体/时钟,内部R/C振荡器(温漂为+/-5%到+/-10%以
内) 1用户在下载用户程序时,可选择是使用内部R/C振荡器还是外部晶体/时钟,常温下内部R/C振荡器频率为:5.0V单片机为:11MHz~15.5MHz,
3.3V 单片机为:8MHz~12MHz,精度要求不高时,可选择使用内部时钟,但因为有制造误差和温漂,以实际测试为准;
13. 共4个16位定时器两个与传统8051兼容的定时器/计数器,16位定时器T0和T1,没有定时器2,但有波特率发生器做串行通讯的波特率发生器再加上2路PCA模块可再实现2个16位定时器;
14. 2个时钟输出口,可由T0的溢出在P3.4/T0输出时钟,可由T1的溢出在
P3.5/T1输出时钟;
15. 外部中断I/O口7路,传统的下降沿中断或低电平触发中断,并新增支持上升沿中断的PCA模块,PowerDown模式可由外部中断唤醒,
INT0/P3.2,INT1/P3.3,T0/P3.4,T1/P3.5,RxD/P3.0,CCP0/P1.3(也可通过寄存器设置到P4.2 ),CCP1/P1.4(也可通过寄存器设置到P4.3);
16. PWM(2路)/PCA(可编程计数器阵列,2路):——也可用来当2路D/A使用——也可用来再实现2个定时器——也可用来再实现2个外部中断(上升沿中断/下降沿中断均可分别或同时支持);
17. A/D转换,10位精度ADC共8路,转换速度可达250K/S(每秒钟25万次)
18. 通用全双工异步串行口(UART),由于STC12系列是高速的8051,可再用定时器或PCA软件实现多串口;
19. STC12C5A60S2系列有双串口,后缀有S2标志的才有双串口,RxD2/P1.2(可通过寄存器设置到P4.2),TxD2/P1.3(可通过寄存器设置到P4.3);
20. 工作温度范围:-40-+85℃(工业级)/0-75℃(商业级)21.封装:PDIP-40,LQFP-44,LQFP-48I/O口不够时,可用2到3根普通I/O口线外接74HC1/165/595(均可级联)来扩展I/O口,还可用A/D做按键扫描来节省I/O口,或用双CPU,三线通信,还多了串口。
2、CH452功能介绍:
CH452是数码管显示驱动和键盘扫描控制芯片。CH452内置时钟振荡电路,可以动态驱动8位数码管或者位LED,具有BCD译码、闪烁、移位、段位寻址、光柱译码等功能;同时还可以进行键的键盘扫描;CH452通过可以级联的4线串行接口或者2线串行接口与单片机等交换数据;并且可以对单片机提供上电复位信号。
显示驱动
1. 内置电流驱动级,段电流不小于15mA,字电流不小于80mA。
2. 动态显示扫描控制,直接驱动8位数码管、位发光管LED或者级光柱。
3. 可选数码管的段与数据位相对应的不译码方式或者BCD译码方式。
4. BCD译码支持一个自定义的BCD码,用于显示一个特殊字符。
5 .数码管的字数据左移、右移、左循环、右循环。
6. 各数码管的数字闪烁控制,可选快慢两种闪烁速度。
7. 任意段位寻址,控制各个LED或者各数码管的各个段的亮与灭。
8. 级光柱译码,通过个LED组成的光柱显示光柱值。
9. 扫描极限控制,支持1到8个数码管,只为有效数码管分配扫描时间。
10. 可以选择字驱动输出极性,便于外部扩展驱动电压和电流。
键盘控制
1. 内置键键盘控制器,基于8×8矩阵键盘扫描。
2. 内置按键状态输入的下拉电阻,内置去抖动电路。
3. 键盘中断,可以选择低电平有效输出或者低电平脉冲输出。
4. 提供按键释放标志位,可供查询按键按下与释放。
5. 支持按键唤醒,处于低功耗节电状态中的CH452可以被部分按键唤醒
外部接口
1. 同一芯片,可选高速的4线串行接口或者经济的2线串行接口。
2. 4线串行接口:支持多个芯片级联,时钟速度从0到2MHz,兼容CH451芯片。
3. 4线串行接口:DIN和DCLK信号线可以与其它接口电路共用,节约引脚。
4. 2线串行接口:支持两个CH452芯片并联(由ADDR引脚电平设定各自地址)。
5. 2线串行接口:时钟速度从500Hz到200KHz,兼容两线I2C总线,节约引脚。
6. 内置上电复位,可以为单片机提供高电平有效和低电平有效复位输出。
第三章 系统软件设计
3.1程序设计流程图:
3.2程序设计的核心部分——算术运算
算术运算程序的过程为:在进行计算之前,先判断输入的运算符是+、-、*、/中的哪一个,若是+或*,则要判断运算结果是否溢出,溢出则显示错误信息,没溢出就显示运算结果;若是/,则要先判断除数是否为零,如果除数为零就提示错误信息,不为零则显示运算结果;若是-,则直接显示运算结果,如果结果为负数, 显示溢出结果。
3.3 系统主程序
main()
{
EA = 1;
EX0=1; //开启外部中断0的中断允许,开启全局中断允许
CH452_Write(CH452_RESET); //CH452复位命令
CH452_Write(CH452_SYSON2); //开显示键盘
CH452_Write( CH452_BCD | 0X0F ); //BCD直接译码,0x05显示占空比5/16,为0则为16/16
CH452_Write( CH452_DIG0 | 0 );
while(1) /等待CH452产生按键中断
{
display();
}
第四章 实验结果分析
4.1实验使用的仪器设备
最小系统板:一块单片机STC12C5A60S2、一块CH452芯片、2个4位数码管、17个按键(0~9数字键、4个功能键(+、-、*、/)、清零键AC、等号键=、复位键)、一个石英晶振、两个30pf的电容。
4.2测试结果分析
在本次课程设计过程中,我们运用的是STC12C5A60S2单片机的最小系统板,在设计过程中,有好多问题没有考虑到。例如:计算加法时未考虑到结果超出范围,在计算除法时未考虑到除数是否为零等。所以,在老师的指导下,我们重新回来修改C语言程序,将调试中出现的问题一一解决。
基于STC12C5A60S2单片机的最小系统板的计算器实物图:
结束语
通过对这程序的制作,使我对汇编语言的基本知识的使用更加熟练,同时也增加了我对汇编语言的一些认识,在设计完成过程中通过和同学的交流,也增加了合作的技巧。通过查阅以下资料也学到了一些课本上没有的东西,拓宽了自己的知识面,增加了学好单片机C语言的信心。
在简易计算器设计过中,有些子程序的设计是固定的,因此可以直接从指导资料中调用,大多只需要修改几个参数就可以,这大大方便了我们的设计,为我们节省了很多的时间。 在这次课程设计中,我真正体会到了合作的重要性,遇到很多问题时,当我看书查资料不能解决时,这是去找同学讨论一下,收获很大,可以使很多问题迎刃而解,直到问题最终解决。 不可否认,本程序存在不少缺点和不足,但通过这次课程设计的却找出了自己在学习上的不足,对以后的工作也有指导作用。我相信在以后的学习中会克服这些不足,达到熟练掌握汇编语言的目的! 总之,这次课程设计对于我们有很大的帮助,通过课程设计,我更加深入地理解了,微机原理课程上讲到的各种芯片的功能,以及引脚的作用,同时加深了对于主要芯片的应用的认识,同时在试验室的环境里熟悉了汇编程序的编写过程和运行过程,最后还提高了自己的动手能力。感谢老师的悉心指导。
参考文献
[1] 谢维成、杨加国.单片机原理与应用及C51程序设计 第二版 清华大学出版社 2013.12
[2] 康光华.电子技术基础 数字部分(第五版) 高等教育出版社 2005.7
[3]张毅刚. 单片微机原理及应用 高等教育出版社 2003.12
[4]徐建民,《汇编语言程序设计》,电子工业出版社
[5]余锡存、曹国华.单片机原理及接口技术[M].陕西:西安电子科技大学
[6]周明德.微型计算机系统原理及应用.北京:清华大学出版社
[7]戴梅萼,史嘉权.微型计算机技术及应用.北京:清华大学出版社
附录:
#include #include "intrins.h" typedef unsigned char uint8; typedef unsigned int uint16; uint16 temp ,number = 0,count1 = 0; uint8 key,temp1,temp2,j = 0; bit flag =1; sbit CH452_SCL = P1^7; sbit CH452_SDA = P1^6; sbit CH452_INT = P3^2; #define CH452_NOP 0x0000 // 空操作 #define CH452_RESET 0x0201 // 复位 #define CH452_LEVEL 0x0100 // 加载光柱值,需另加7位数据 #define CH452_CLR_BIT 0x0180 // 段位清0,需另加6位数据 #define CH452_SET_BIT 0x01C0 // 段位置1,需另加6位数据 #define CH452_SLEEP 0x0202 // 进入睡眠状态 #define CH452_LEFTMOV 0x0300 // 设置移动方式-左移 #define CH452_LEFTCYC 0x0301 // 设置移动方式-左循环 #define CH452_RIGHTMOV 0x0302 // 设置移动方式-右移 #define CH452_RIGHTCYC 0x0303 // 设置移动方式-右循环 #define CH452_SELF_BCD 0x0380 // 自定义BCD码,需另加7位数据 #define CH452_SYSOFF 0x0400 // 关闭显示、关闭键盘 #define CH452_SYSON1 0x0401 // 开启显示 #define CH452_SYSON2 0x0403 // 开启显示、键盘 #define CH452_SYSON2W 0x0423 // 开启显示、键盘, 真正2线接口 #define CH452_NO_BCD 0x0500 // 设置默认显示方式,可另加3位扫描极限 #define CH452_BCD 0x0580 // 设置BCD译码方式,4位扫描占空比(默认0为16/16) #define CH452_TWINKLE 0x0600 // 设置闪烁控制,需另加8位数据 #define CH452_GET_KEY 0x0700 // 获取按键,返回按键代码 #define CH452_DIG0 0x0800 // 数码管位0显示,需另加8位数据 #define CH452_DIG1 0x0900 // 数码管位1显示,需另加8位数据 #define CH452_DIG2 0x0a00 // 数码管位2显示,需另加8位数据 #define CH452_DIG3 0x0b00 // 数码管位3显示,需另加8位数据 #define CH452_DIG4 0x0c00 // 数码管位4显示,需另加8位数据 #define CH452_DIG5 0x0d00 // 数码管位5显示,需另加8位数据 #define CH452_DIG6 0x0e00 // 数码管位6显示,需另加8位数据 #define CH452_DIG7 0x0f00 // 数码管位7显示,需另加8位数据 //#define CH452_0 0X0510 /*******CH452在BCD译码方式下的特殊字符**********/ #define CH452_BCD_SPACE 0x10 #define CH452_BCD_PLUS 0x11 #define CH452_BCD_MINUS 0x12 #define CH452_BCD_EQU 0x13 #define CH452_BCD_LEFT 0x14 #define CH452_BCD_RIGHT 0x15 #define CH452_BCD_UNDER 0x16 #define CH452_BCD_CH_H 0x17 #define CH452_BCD_CH_L 0x18 #define CH452_BCD_CH_P 0x19 #define CH452_BCD_DOT 0x1A #define CH452_BCD_SELF 0x1E #define CH452_BCD_TEST 0x88 #define CH452_BCD_DOT_X 0x80 /*******2线接口的CH452定义************/ #define CH452_I2C_ADDR0 0x40 // CH452的ADDR=0时的地址 #define CH452_I2C_ADDR1 0x60 // CH452的ADDR=1时的地址,默认值 #define CH452_I2C_MASK 0x3E // CH452的2线接口高字节命令掩码 #define DELAY_IO { _nop_();_nop_();nop_();_nop_();} //IO操作需延时,STC单片机12MHz下2个即可 /****************************** 函数说明:模拟I2C 启动 ******************************/ void CH452_I2c_Start( void ) { CH452_SDA=1; DELAY_IO; //发送起始条件的数据信号 CH452_SCL=1; DELAY_IO; CH452_SDA=0; DELAY_IO; //发送起始信号 CH452_SCL=0; DELAY_IO; //钳住I2C总线,准备发送或接收数据 } /****************************** 函数说明:模拟I2C 结束 ******************************/ void CH452_I2c_Stop( void ) { CH452_SDA=0; DELAY_IO; CH452_SCL=1; DELAY_IO; CH452_SDA=1; DELAY_IO; //发送I2C总线结束信号 } /****************************** 函数说明:模拟I2C 写一个字节数据 入口参数:dat=要写入的数据或者命令 ******************************/ void CH452_I2c_WrByte( unsigned char dat ) { unsigned char i; for( i = 0; i != 8; i++ ) // 输出8位数据 { If ( dat&0x80 ) { CH452_SDA=1; } else { CH452_SDA=0; } DELAY_IO; CH452_SCL=1; dat <<= 1; DELAY_IO; CH452_SCL=0; DELAY_IO; } CH452_SDA=1; DELAY_IO; CH452_SCL=1; DELAY_IO; //接收应答 CH452_SCL=0; DELAY_IO; } /****************************** 函数说明:模拟I2C 读取一个字节数据 出口参数:dat=要读取的数据,一般为按键值 ******************************/ unsigned char CH452_I2c_RdByte( void ) { unsigned char dat; unsigned char i; CH452_SDA=1; DELAY_IO; dat = 0; for( i = 0; i != 8; i++ )// 输入8位数据 { CH452_SCL=1; DELAY_IO; dat <<= 1; if( CH452_SDA ) dat++;//输入1位 CH452_SCL=0; DELAY_IO; } CH452_SDA=1; DELAY_IO; CH452_SCL=1; DELAY_IO; //发出无效应答 CH452_SCL=0; DELAY_IO; return dat; } /****************************** 函数说明:模拟I2C 写入指令 入口参数:cmd=要写入的指令代码 ******************************/ void CH452_Write( unsigned int cmd ) { CH452_I2c_Start(); //启动总线 CH452_I2c_WrByte((unsigned char)(cmd>>7)&CH452_I2C_MASK|CH452_I2C_ADDR1); CH452_I2c_WrByte((unsigned char)cmd); //发送数据 CH452_I2c_Stop(); //结束总线 } /****************************** 函数说明:模拟I2C读取CH452按键值 入口参数:read_cmd=读取指令代码 出口参数:按键值0x00~0x3F ******************************/ unsigned char CH452_Read( unsigned int read_cmd ) { unsigned char temp; CH452_I2c_Start(); //启动总线 CH452_I2c_WrByte((unsigned char)(read_cmd>>7)&CH452_I2C_MASK|CH452_I2C_ADDR1|0x01); temp = CH452_I2c_RdByte(); //读取数据 CH452_I2c_Stop(); //结束总线 return temp; } /****************************** 函数说明:读取CH452按键值 ******************************/ unsigned char CH452_Read_Key() { unsigned char temp , keyboard = 0; temp=CH452_Read(CH452_GET_KEY); switch(temp & 0x3f) { case 0x1b: keyboard = 15; break; case 0x1a: keyboard = 14; break; case 0x19: keyboard = 13; break; case 0x18: keyboard = 12; break; case 0x13: keyboard = 11; break; case 0x12: keyboard = 10; break; case 0x11: keyboard = 9;; break; case 0x10: keyboard = 8; break; case 0x0b: keyboard = 7; break; case 0x0a: keyboard = 6; break; case 0x09: keyboard = 5; break; case 0x08: keyboard = 4; break; case 0x03: keyboard = 3; break; case 0x02: keyboard = 2; break; case 0x01: keyboard = 1; break; case 0x00: keyboard = 0; break; } return keyboard; } void display() { if(temp < 1000) CH452_Write( CH452_DIG3 | CH452_BCD_SPACE); else CH452_Write( CH452_DIG3 | temp/1000); if (temp < 100) CH452_Write( CH452_DIG2 | CH452_BCD_SPACE ); else CH452_Write( CH452_DIG2 | (temp%1000)/100 ); if(temp < 10) CH452_Write( CH452_DIG1 | CH452_BCD_SPACE ); else CH452_Write( CH452_DIG1 | ((temp%1000)%100)/10 ); CH452_Write( CH452_DIG0 | ((temp%1000)%100)%10 ); } void math() { switch(j) { case 1:temp = (temp1+temp2);break; case 2:temp = (temp1-temp2);break; case 3:temp = (temp1*temp2);break; case 4:temp = (temp1/temp2);break; default:; } } uint8 count(void) { if(key<10) { count1 = (count1*10)+key; temp = count1; if(key<10) if(flag) CH452_Write( CH452_DIG0 | CH452_BCD_SPACE ); CH452_Write( CH452_LEFTMOV ); CH452_Write(CH452_BCD|0X0F); CH452_Write( CH452_DIG0 | key ); } return count1; } main() { EA = 1; EX0=1; //开启外部中断0的中断允许,开启全局中断允许 CH452_Write(CH452_RESET); //CH452复位命令 CH452_Write(CH452_SYSON2); //开显示键盘 CH452_Write( CH452_BCD | 0X0F ); //BCD直接译码,0x05显示占空比5/16,为0则为16/16 CH452_Write( CH452_DIG0 | 0 ); while(1) //等待CH452产生按键中断 { display(); } } void Init_int0(void) interrupt 0 //外部中断0的中断服务程序 { key = CH452_Read_Key(); //读按键值,0为返回十六进制数 if(key<10) count(); switch(key) { case 15:j=4;temp1 = count();count1 = 0;break; case 14:j=3;temp1 = count();count1 = 0;break; case 13:j=2;temp1 = count();count1 = 0;break; case 12:j=1;temp1 = count();count1 = 0;break; case 11:temp2 = count();math();break; default :; } flag = 0; }下载本文