蜂鸣数字计算器(共15页).doc

上传人:飞****2 文档编号:13500549 上传时间:2022-04-29 格式:DOC 页数:15 大小:142.50KB
返回 下载 相关 举报
蜂鸣数字计算器(共15页).doc_第1页
第1页 / 共15页
蜂鸣数字计算器(共15页).doc_第2页
第2页 / 共15页
点击查看更多>>
资源描述

《蜂鸣数字计算器(共15页).doc》由会员分享,可在线阅读,更多相关《蜂鸣数字计算器(共15页).doc(15页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、精选优质文档-倾情为你奉上一、课程设计内容及要求1、蜂鸣计算器设计利用普中科技HC6800-ES V2.0单片机开发板设计一款带蜂鸣器的电子计算器。主要使用开发板上的数码管、LED点阵、矩阵键盘、蜂鸣器等模块功能。开发板配有光盘,里面有各个模块的使用说明和程序范例可供参考。2、设计要求1) 上电开机或者复位键按下之后,数码管自动显示个人学号的后8位。2) 定义矩阵键盘的S1-S9代表数字按键1-9,键盘S10代表数字按键0,键盘S11-S16分别代表按键+、-、=、C,其中C按键为计算器清零按键,按下C键计算器开始新的计算。3) 计算器计算过程中,用LED点阵显示+、-、运算符号,用8位数码管

2、显示键入的数字和运算的结果。键入时依次显示并自动移位,例如18+9=27,先键入1,显示1,再键入8,1自动左移一位显示18,键入+,LED点阵显示+,键入9,数码管之前显示的18消失并重新显示为9,键入=,数码管显示运算结果27。4) 为这16个矩阵键盘的按键分配不同的蜂鸣器频率,使得按下不同的按键蜂鸣器响声不同,便于识别按键。5) 按键应具有一定的消除抖动功能。6) 所有单片机程序代码都用C语言编写,并烧写到单片机中上电自动运行。二、 设计思想蜂鸣器计算器设计包括矩阵键盘模块、数码管及矩阵LED动态显示模块、输入逻辑计算显示模块和蜂鸣器响应模块这四大模块。具体实施方法如下:1、 矩阵键盘模

3、块,四乘四的矩阵键盘,设计按键扫描函数,在定时中断中调用,调用定时器中断,中断间隔时间设置为1ms,选择P2IO口,P2.0到P2.3做输出KeyOut,P2.4做P2.7做输入KeyIn,每次在按键扫描中断中,每次让矩阵按键的一个 KeyOut 输出低电平,其它三个输出高电平,判断当前所有 KeyIn 的状态,然后再让下一个 KeyOut 输出低电平,其它三个输出高电平,再次判断所有 KeyIn,通过四次扫描,确定按下的键,再通过快速的中断不停的循环进行判断,就可以最终确定哪个按键按下了。 同时在按键模块,还需要消抖使按键稳定。通常我们采用延迟再次检测的方式消抖,但是太过消耗单片机的CUP。

4、所以为了避免通过延时消抖占用单片机执行时间,将其转化成了一种按键状态判定而非按键过程判定,只对当前按键的连续 16ms 的 4 次状态进行判断,全为0就断定对于的键按下了,全为1就断定为没有按下。2、数码管及矩阵LED动态显示模块,通过每毫秒进行动态扫描进行显示,由于数码管和矩阵LED动态显示模块都需要通过P1.3和P1.4进行选择来控制,所以在写刷新数据和符号的时候需要先在函数开始调好对应的控制位。而所需要的显示的数字和符号保存在数组中,以便需要的时候直接调用。3、输入逻辑计算显示模块,在编写程序的时候,对于这个简易计算器,以正整数的连续加减乘除为基本编程目的。在第一次输入为0-9这十个按键

5、的时候,此时设置了标记符号flag=0,直接保存到数据保存数组addflag中,若继续输入数字就把addflag乘以10再加上新输入的数字;若扫描到加减乘除这四个符号的时候,先把标记符号flag置为1,再把算数符号保存到符号标记sign中,把需要LED矩阵显示的全局符号变量tx设置为对应的数字,继续扫描到数字的时候就会把数据保存到add1(flag=1)中;如果接下来输入为等于号,就判断sign数值然后对add0和add1做对应的计算;如果输入还是计算符号,就先计算把计算结果保存到add0中,再清零add1,再继续扫描。4、蜂鸣器响应模块,由于开发板上面的蜂鸣器是无源蜂鸣器,所以需要通过输出p

6、wm脉冲来驱动蜂鸣器,同时由于脉冲频率不同对于蜂鸣器发声也不一样,所以通过一个需要传入频率参数的函数。通过该频率参数,来设置中断定时器T1,控制蜂鸣器驱动端口输出高低电平,然后在按键处理函数处判断对应需要的频率送给蜂鸣器响应函数。三、 程序流程图 1、整体流程图2、算数逻辑流程四、详细程序 1、总程序Calculator.c#include #include #include #include void main() Init();ShowNumber();/显示学号while (1) KeyDriver(); /调用按键驱动函数 /* T0中断服务函数,用于数码管显示扫描与按键扫描 */vo

7、id InterruptTimer0() interrupt 1 TH0 = 0xFC; /重新加载初值 TL0 = 0x67; LedScan(); /调用数码管显示扫描函数 KeyScan(); /调用按键扫描函数ShowPhoto(tx);/调用点阵显示函数/* T1中断服务函数,用于蜂鸣器 */ void InterruptTimer1() interrupt 3 TH1 = T1RH; /重新加载重载值 TL1 = T1RL; BUZZ = BUZZ; /反转蜂鸣器控制电平2、宏定义头文件sys.c#ifndef _sys_h_#define _sys_h_#include sys.

8、h#define uint unsigned int#define uchar unsigned charsbit ADDR0 = P10;sbit ADDR1 = P11;sbit ADDR2 = P12;sbit ADDR3 = P13;sbit ENLED = P14;sbit KEY_IN_1 = P24;sbit KEY_IN_2 = P25;sbit KEY_IN_3 = P26;sbit KEY_IN_4 = P27;sbit KEY_OUT_1 = P23;sbit KEY_OUT_2 = P22;sbit KEY_OUT_3 = P21;sbit KEY_OUT_4 = P2

9、0;sbit BUZZ = P16; /蜂鸣器控制引脚unsigned char T1RH = 0; /T0重载值的高字节unsigned char T1RL = 0; /T0重载值的低字节unsigned char tx = 0; /矩阵led显示unsigned char code LedChar = /数码管显示字符转换表 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E;unsigned char LedBuff6 = /数码管显示缓冲区 0xFF

10、, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF;unsigned char code KeyCodeMap44 = /矩阵按键编号到标准键盘键码的映射表 0x31, 0x32, 0x33, 0x26 , /数字键1、数字键2、数字键3、加键 0x34, 0x35, 0x36, 0x25 , /数字键4、数字键5、数字键6、乘键 0x37, 0x38, 0x39, 0x28 , /数字键7、数字键8、数字键9、减键 0x30, 0x1B, 0x0D, 0x27 /数字键0、ESC键、等号键、 除键;unsigned char KeySta44 = /全部矩阵按键的当前状态 1, 1

11、, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1;unsigned char code image68 = /符号的字模表 0xFF,0xBD,0x5A,0xFF,0xFF,0xBD,0xDB,0xE7,/笑脸 0xE7,0xE7,0xE7,0x00,0x00,0xE7,0xE7,0xE7,/加号 0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF, /减号 0x3C,0x18,0x81,0xC3,0xC3,0x81,0x18,0x3C, /乘号 0xE7,0xE7,0xFF,0x00,0x00,0xFF,0xE7,0xE7, /

12、除号0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF /等号;void Init();void ShowNumber(unsigned long num);void KeyAction(unsigned char keycode);void KeyDriver();void KeyScan();void LedScan();void OpenBuzz(unsigned int frequ);void StopBuzz();void Delay();void Buzz(unsigned int frequ);void ShowPhoto(unsigned int a

13、);#endif3、函数头文件fun.c#ifndef _fun_h_#define _fun_h_#include fun.hvoid Init()EA = 1; /使能总中断 TMOD = 0x11; /设置T0为模式1 TH0 = 0xFC; /为T0赋初值0xFC67,定时1ms TL0 = 0x67; ET0 = 1; /使能T0中断TR0 = 1; /启动T0 /* 将一个无符号长整型的数字显示到数码管上,num-待显示数字 */void ShowNumber(unsigned long num) signed char i; unsigned char buf6; for (i=

14、0; i=1; i-) /从最高位起,遇到0转换为空格,遇到非0则退出循环 if (bufi = 0) LedBuffi = 0xFF; else break; for ( ; i=0; i-) /剩余低位都如实转换为数码管显示字符 LedBuffi = LedCharbufi; /* 按键动作函数,根据键码执行相应的操作,keycode-按键键码 */void KeyAction(unsigned char keycode) static unsigned long result = 0; /用于保存运算结果 static unsigned long add2 = 0; /用于保存输入的数字

15、static unsigned intsign2 = 0;/用作统计前一次和当前运算符号,03依次代表加减乘除 static unsigned int flag = 0; /用于统计次数switch(keycode) /不同按键蜂鸣器发出不同频率声音case 0x30 : Buzz(1000);break;case 0x31 : Buzz(1500);break;case 0x32 : Buzz(2000);break;case 0x33 : Buzz(2500);break;case 0x34 : Buzz(3000);break;case 0x35 : Buzz(3500);break;c

16、ase 0x36 : Buzz(4000);break;case 0x37 : Buzz(4500);break;case 0x38 : Buzz(5000);break;case 0x39 : Buzz(5500);break;case 0x26 : Buzz(6000);break;case 0x28 : Buzz(6500);break;case 0x25 : Buzz(7500);break;case 0x27 : Buzz(8000);break;case 0x0D : Buzz(8500);break;case 0x1B : Buzz(9000);break;default : b

17、reak; if (keycode=0x30) & (keycode=0x39) /输入0-9的数字 if(flag = 0) add0 = (add0*10)+(keycode-0x30); /整体十进制左移,新数字进入个位 ShowNumber(add0); /运算结果显示到数码管elseadd1 = (add1*10)+(keycode-0x30); /整体十进制左移,新数字进入个位 ShowNumber(add1); /运算结果显示到数码管 else if (keycode = 0x26) /向上键用作加号,执行加法或连加运算 sign0 = sign1; /保存前一次的运算符号 si

18、gn1 = 0; /保存当前运算符号flag = 1;tx = 1;switch(sign0) /用于连加case 0:add0= add0+add1;break;case 1:add0= add0-add1;break;case 2:add0= add0*add1;break;case 3:add0= add0/add1;break;default : break; ShowNumber(add0); /运算结果显示到数码管add1=0; /清零add1; else if (keycode = 0x28) /向下键用作减号,执行减法sign0 = sign1; /保存前一次的运算符号 sig

19、n1 = 1; /保存当前运算符号flag = 1;tx = 2;switch(sign0)case 0:add0= add0+add1;break;case 1:add0= add0-add1;break;case 2:add0= add0*add1;break;case 3:add0= add0/add1;break;default : break;ShowNumber(add0); /运算结果显示到数码管add1=0; /清零add1;else if (keycode = 0x25) /向下键用作乘号,执行乘法sign0 = sign1; /保存前一次的运算符号 sign1 = 2; /

20、保存当前运算符号flag = 1;tx = 3;switch(sign0)case 0:add0= add0+add1;break;case 1:add0= add0-add1;break;case 2:add0= add0*add1;break;case 3:add0= add0/add1;break;default : break;ShowNumber(add0); /运算结果显示到数码管add1=0; /清零add1;else if (keycode = 0x27) /向下键用作除号,执行除法sign0 = sign1; /保存前一次的运算符号 sign1 = 3; /保存当前运算符号f

21、lag = 1;tx = 4 ;switch(sign0)case 0:add0= add0+add1;break;case 1:add0= add0-add1;break;case 2:add0= add0*add1;break;case 3:add0= add0/add1;break;default : break;ShowNumber(add0); /运算结果显示到数码管add1=0; /清零add1; else if (keycode = 0x0D) /等号键,执行运算 switch(sign1)case 0: result = add0+add1; /进行加法运算 ShowNumbe

22、r(result); /运算结果显示到数码管 break;case 1: result = add0-add1; /进行减法运算 ShowNumber(result); /运算结果显示到数码管 break;case 2: result = add0*add1; /进行乘法运算 ShowNumber(result); /运算结果显示到数码管 break;case 3: result = add0/add1; /进行除法运算 ShowNumber(result); /运算结果显示到数码管 break;default : break; tx = 5 ;flag = 0;add0 = 0;add1 =

23、 0;sign0=0;sign1=0; else if (keycode = 0x1B) /Esc键,清零结果 add0 = 0;add1 = 0;sign0=0;sign1=0;flag = 0; result = 0;tx = 0 ; ShowNumber(result); /清零后的加数显示到数码管 /* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */void KeyDriver() unsigned char i, j; static unsigned char backup44 = /按键值备份,保存前一次的值 1, 1, 1, 1, 1, 1, 1, 1, 1

24、, 1, 1, 1, 1, 1, 1, 1 ; for (i=0; i4; i+) /循环检测4*4的矩阵按键 for (j=0; j4; j+) if (backupij != KeyStaij) /检测按键动作 if (backupij != 0) /按键按下时执行动作 KeyAction(KeyCodeMapij); /调用按键动作函数 backupij = KeyStaij; /刷新前一次的备份值 /* 按键扫描函数,需在定时中断中调用,调用间隔1ms */void KeyScan() unsigned char i; static unsigned char keyout = 0;

25、/矩阵按键扫描输出索引 static unsigned char keybuf44 = /矩阵按键扫描缓冲区 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ; /将一行的4个按键值移入缓冲区 keybufkeyout0 = (keybufkeyout0 1) | KEY_IN_1; keybufkeyout1 = (keybufkeyout1 1) | KEY_IN_2; keybufkeyout2 = (keybufkeyout2 1) | KEY_

26、IN_3; keybufkeyout3 = (keybufkeyout3 1) | KEY_IN_4; /消抖后更新按键状态 for (i=0; i 8); /16位重载值分解为高低两个字节 T1RL = (unsigned char)reload; TH1 = 0xFF; /设定一个接近溢出的初值,以使定时器马上投入工作 TL1 = 0xFE; ET1 = 1; /使能T0中断 TR1 = 1; /启动T0/* 蜂鸣器停止函数*/void StopBuzz() ET1 = 0; /禁用T0中断 TR1 = 0; /停止T0 /*延时函数 */void Delay()unsigned int

27、i=0;for(i=10000;i0;i-);/*蜂鸣器*/void Buzz(unsigned int frequ)OpenBuzz(frequ);Delay();StopBuzz(); /*LED矩阵显示运算符号*/void ShowPhoto(unsigned int a)static unsigned char i = 0; ENLED = 0; /使能U4,选择LED点阵 ADDR3 = 0;P0 = 0xFF; /显示消隐 switch (i) case 0: ADDR2=0; ADDR1=0; ADDR0=0; i+; P0=imagea0; break; case 1: ADD

28、R2=0; ADDR1=0; ADDR0=1; i+; P0=imagea1; break; case 2: ADDR2=0; ADDR1=1; ADDR0=0; i+; P0=imagea2; break; case 3: ADDR2=0; ADDR1=1; ADDR0=1; i+; P0=imagea3; break; case 4: ADDR2=1; ADDR1=0; ADDR0=0; i+; P0=imagea4; break; case 5: ADDR2=1; ADDR1=0; ADDR0=1; i+; P0=imagea5; break; case 6: ADDR2=1; ADDR

29、1=1; ADDR0=0; i+; P0=imagea6; break; case 7: ADDR2=1; ADDR1=1; ADDR0=1; i=0; P0=imagea7; break; default: break; #endif五、实践收获和体会 在这一次的电子设计的过程中,通过我们两个人的合作完成了这次的蜂鸣计算器的设计,通过对每个模块的例程的理解,最后把各个模块组合在一起。过程中,遇到了很多问题,比如数码管刷新和LED显示刷新需要用到同一个口,这时候需要再每次调用函数的时候先对控制位置位以免相互影响;同时在逻辑计算设计上面,我们一开始只能做一步的运算,后来我们对程序进行优化的时候,通过添加符号标记和存数据,然后进行处理,最后可以实现连续计算。最后我们成功的完成了本次设计,不但让我们的了解到了单片机的程序设计,对下学期的学习有了初步了解;而且对我们语言编程的逻辑思想有了进一步的提升,增强了对本专业的兴趣。专心-专注-专业

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 教案示例

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com