zl程序教程

您现在的位置是:首页 >  工具

当前栏目

《51单片机应用开发从入门到精通》——2.12 电子琴

2023-09-11 14:17:30 时间

本节书摘来自异步社区《51单片机应用开发从入门到精通》一书中的第2章,第2.12节,作者 张华杰,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.12 电子琴

本实例是采用44矩阵式键盘设计出16个音符,随意弹奏。

2.12.1 硬件设计

电子琴电路设计如图2-19所示。


screenshot

单片机P3为输入端口,接有44矩阵式键盘,键盘上标出16个音符。键盘的4条行线的一端与单片机P3端口的P3.0、P3.1、P3.2和P3.3口相接,另一端通过上拉电阻接到 + 5V上;4条列线的一端与P3端口的P3.4、P3.5、P3.6和P3.7口相接。单片机的P2.4端口为输出端,通过限流电阻R1与三极管基极相接,三极管的集电极接有蜂鸣器。

2.12.2 程序设计

电子琴程序设计的思路是:设计16个音符,与44矩阵式键盘16个按键一一对应。音符通过定时器T0产生,然后通过键盘扫描法,将按下的键转换成相对应的音符。

1.流程图

程序设计流程如图2-20所示。


screenshot

2.程序

汇编语言编写的电子琴源程序JP04.ASM代码如下:

01: ORG 00H ;主程序起始地址

02: JMP START ;跳转至主程序

03: ORG 0BH ;T0中断起始地址

04: JMP TIM0 ;跳转至T0中断子程序 

05:START: MOV TMOD, #00000001B ;设T0在MODE1

06: MOV IE, #10000010B ;开通中断

07: SETB TR0 ;启动定时器T0 

08:L1: ACALL KEY ;调用KEY,判断是否有键按下 

09: CLR EA ;中断屏蔽

10: JB F0, L1 ;没按下则F0 = 1,否则F0 = 0

11: MOV A,22H ;将取码指针暂存地址载入A

12: RL A ;左移1位

13: MOV DPTR, #TABLE ;存表

14: MOVC A, @A + DPTR ;到至TABLE取码,取T的值

15: MOV TH0, A ;取到的高位字节存入TH0

16: MOV 21H, A ;取到的高位字节存入21H

17: MOV A, 22H ;载入取码指针值

18: RL A ;向左移1位

19: INC A ;加1

20: MOVC A, @A + DPTR ;到表TABLE取低位字节计数值

21: MOV TL0, A ;取到的低位字节存入TL0 

22: MOV 20H, A ;取低位字节存入20H 

23:L2: ACALL KEY ;调用KEY,判断有无键按下

24: SETB EA ;开通中断

25: JB F0, L1 ;是否有键按下

26: JMP L2 ;有则跳转至L2 

27:KEY: SETB F0 ;设F0 = 1

28: MOV R3, #0F7H ;扫描初值(P3.3 = 0)

29: MOV R1, #00H ;取码指针初值

30:L3: MOV A, R3 ;载入扫描指针

31: MOV P3, A ;输出至P3,开始扫描

32: MOV A, P3 ;读入P3 

33: SETB C ;令C = 1

34: MOV R5, #04H ;检测P3.7~P3.4

35: L4: RLC A ;左移1位

36: JNC KEYIN ;检测行C = 0,表示被按下

37: INC R1 ;无键按下则取码指针加1

38: DJNZ R5, L4 ;4列检测完毕?

39: MOV A, R3 ;载入扫描指针

40: SETB C ;令C = 1

41: RRC A ;扫描下一行

42: MOV R3, A ;存回R3扫描指针寄存器

43: JC L3 ;C = 0,表示行扫描完毕

44: RET ;子程序返回 

45: KEYIN: MOV 22H, R1 ;取码指针存入地址22H

46: CLR F0 ;令F0 = 0 

47: RET ;子程序返回 

48: TIM0: PUSH ACC ;将A的值暂存于堆栈

49: PUSH PSW ;将PSW的值暂存于堆栈

50: MOV TL0, 20H ;重设计数值

51: MOV TH0, 21H 

52: CPL P2.4 ;将P2.4位反相

53: POP PSW ;从堆栈取回PSW的值

54: POP ACC ;从堆栈取回A的值

55: RETI ;返回到主程序 

56: TABLE: DW 64021,64103,64260,64400 ;编码表

57: DW 64524,64580,64684,64777

58: DW 64820,64898,64968,65030

59: DW 65058,65110,65157,65178 

60: END ;程序结束
2.12.3 代码详解

1.程序分析解释

01~04:设置程序开始地址和中断T0起始地址。

05~07:设置T0工作在模式1下;开通中断并启动T0工作。

08:调用扫描子程序KEY开始扫描,判断是否有键按下。

09~22:存表(第13行语句),取码(第14和第20行语句),向定时器装初始值(第15和第21行语句)。与此同时,还将取到的高位字节和低位字节分别存入地址21H(第16行语句)和20H(第22行语句)处,以便在中断子程序中对定时器重装初始值用。地址22H用于暂存取码指针。整个过程由于已将中断关闭,所以定时器不能产生中断信号,输出端P2.4没有输出。

第10行语句是判断F0是0还是1。F0是状态字寄存器PSW的一个自由使用的标志位。程序规定F0 = 1表示没有键按下,F0 = 0表示有键按下。

23~26:再调用扫描程序,确认是否有键按下。当有键按下时,由于此时已经开通了中断,定时器会产生中断信号,使程序进入到中断服务子程序运行,于是输出端P2.4便有输出。

27~44:扫描子程序。

45~47:有键按下后,将取码指针存入地址22H,并令F0 = 0,用来标志有键按下。

48~55:中断服务子程序。其中第48~49行为进栈保护现场,第53~54行为出栈恢复现场。50~51行重装定时器初始值。第52行语句是输出语句。第55行语句是中断服务子程序返回主程序的指令。

56~59:编码表。表中的16个数是定时器发出16个音的定时器初始值。

60:程序结束。

2.至本章用过的指令归类

数据传送类指令:MOV、MOVC、PUSH、POP。 算术运算类指令:INC、DIV。 逻辑运算及位移类指令:RL、RR、RLC、RRC、CLR、ANL、ORL、XRL。 控制转移类指令:JMP、DJNZ、ACALL、RET、CJNE、RETI、JZ。 位操作类指令:CPL、CLR、SETB、JB、JNB、JBC、JNC、JC。 伪指令:END、DB、ORG。 2.12.4 模拟仿真

1.模拟仿真前注意事项

在第30行语句与31行语句之间,增加一条模拟按键按下的语句。

MOV A,#11100111B

在第24行语句与25行语句之间,增加一条模拟中断溢出的语句,使程序能进入到中断服务程序里运行。

SETB TF0

2.模拟仿真中注意事项

(1)注意观察程序运行路线。当第一次扫描检测到有键按下时,由于第09行语句将中断屏蔽,所以程序运行不能进入到中断服务子程序,输出端P2.4没有输出。

在第二次扫描再次确认有键按下时,由于第24行语句将中断开启,所以定时器T0将产生中断信号,通过程序标号TIM0进入中断服务子程序,使P2.4端口产生输出。

(2)去掉模拟按键和模拟中断溢出语句,观察程序运行情况,由于没有按键按下,所以P2.4没有输出。

2.12.5 实例测试

将写入程序的单片机插入实验板插座内,并检查实验板上的蜂鸣器接口是否与程序中声音输出端口一致,当检查无误后接通电源,即可按图2-19所示进行音乐弹奏。

2.12.6 经验总结

电子琴程序从功能设计上可分为两大部分。

利用单片机内定时器T0产生16个音符,16个音符代码在表中的排列顺序与16个按键上所标出的音符是对应的。 通过对键盘不断进行扫描,当确定有按键操作后,将所按下的键转换成相对应的音符,并通过输出端口使蜂鸣器发出相对应的声音,声音的长短由按键的时间决定。
《51单片机应用开发从入门到精通》——导读 随着微处理器技术和SoC技术的发展,从较早的4位机到8位机,一直发展到现在的32位机,单片机的应用逐渐渗透到生产、生活的各个领域。本书主要针对MCS-51体系单片机,从硬件、软件两个方面的基础知识开始进行介绍。
异步社区 异步社区(www.epubit.com)是人民邮电出版社旗下IT专业图书旗舰社区,也是国内领先的IT专业图书社区,致力于优质学习内容的出版和分享,实现了纸书电子书的同步上架,于2015年8月上线运营。公众号【异步图书】,每日赠送异步新书。