A40基于51单片机汇编语言电子琴Proteus设计
作者:单片机仿真   类别:51单片机仿真    日期:2026-10-23 09:02:33    阅读:10 次   消耗积分:10 分

image.png

A40基于51单片机汇编语言电子琴Proteus设计

用51单片机汇编语言做一个16键电子琴:4×4键盘每个键对应一个音,按下就用定时器0溢出翻转P1.0发出对应频率的方波,松手立刻停,P0口同步显示当前键号。音准全靠一张16项的重装值表,改表就能改调。

一、设计实现功能

本设计功能简介:使用51单片机和汇编语言设计一个简易电子琴的proteus仿真,要求以下功能:

1、使用汇编语言编写程序。

2、4×4矩阵键盘共16个琴键,对应E4到F6两个八度多的音阶。

3、按下琴键发出对应频率的方波,松手立即停止发声。

4、P0口数码管显示当前按下的键号0~F。

二、资源汇总

1、仿真文件:Proteus工程,7.8和8.6两个版本都能直接打开。

2、程序文件:main.asm汇编源码,以及编译好的cx.hex。

3、修改日期小工具:购买资料后赠送,用于修改文件创建日期,下载地址在文章最后。

三、设计介绍

拿到压缩包之后先解压,没有解压软件的直接搜"压缩",下载解压软件后先解压文件,再运行仿真和程序。

图1 Proteus仿真总览

仿真原理图

接线很简单:键盘接P3(高4位行、低4位列),扬声器接P1.0,数码管接P0,定时器0工作在方式1。

发声原理是定时器溢出中断里翻转引脚。要发440Hz,方波周期是1/440秒≈2273微秒,半个周期1136微秒,所以定时器每1136微秒溢出一次:

项目计算结果
半周期1 ÷ (2 × 频率)440Hz → 1136微秒
重装值65536 - 半周期微秒数65536-1136=64400
存入TABLE2里两个字节0FB90H

16个音的重装值全部算好写进表里,注意是DW定义的16位字,查表时要把键值乘2得到字节偏移:

`asm
MOV DPTR,#TABLE2
MOV B,#2
MUL AB ;键值×2
MOV R1,A
MOVC A,@A+DPTR ;取高字节
MOV TH0,A
INC R1
MOV A,R1
MOVC A,@A+DPTR ;取低字节
MOV TL0,A
MOV IE,#82H ;开T0中断
SETB TR0
`

表里16个值换算成频率是这些:

键号重装值频率音名
064021330HzE4
164103349HzF4
264260392HzG4
364400440HzA4
464524494HzB4
564580523HzC5
664684587HzD5
764777659HzE5
864820698HzF5
964898784HzG5
1064968880HzA5
1165030988HzB5
12650581046HzC6
13651101174HzD6
14651571319HzE6
15651781397HzF6

从E4到F6,跨了两个八度不到,能弹绝大部分流行歌的主旋律。

中断服务程序里必须把重装值再写一遍——方式1不会自动重装,忘了这一步声音会越弹越跑调:

`asm
INT_T0: MOV DPTR,#TABLE2
MOV A,VAL
MOV B,#2
MUL AB
MOV R1,A
MOVC A,@A+DPTR
MOV TH0,A
INC R1
MOV A,R1
MOVC A,@A+DPTR
MOV TL0,A
CPL P1.0 ;翻转引脚,输出方波
RETI
`

松手检测在主循环的W0、W1两段:P3读回0FH或F0H都算松开,此时CLR TR0停振、MOV P0,#00H熄灭显示。所以这个琴是"按着响、松开停",没有包络、没有余音。

特别注意: 声音频率整体偏高或偏低,先确认晶振频率,表里的值是按12MHz算的,用11.0592MHz会整体偏低约8%;按下去只有"咔"一声,是P1.0接了有源蜂鸣器,电子琴必须用无源扬声器;音与音之间切换有杂音,是切换瞬间定时器没停,按下新键前应先CLR TR0再改重装值;数码管显示键号但没声音,检查SETB TR0和IE有没有置位;想要更宽的音域,把TABLE2继续往下加值就行,键位不够可以只取8个键弹一个八度。

四、日期修改

资料中提供修改日期的小工具,购买资料赠送修改文件创建日期的小工具,三个下载地址都在文章最后。

五、资料下载

付费后获取下载链接,直接下载到电脑上,然后解压即可!每个链接前面都配了二维码,手机扫码可以直接跳转。

/

版权所有,转载本站文章请注明出处:proteus单片机
上一篇:A39基于51单片机汇编语言交通灯Proteus设计
下一篇:A41基于51单片机汇编语言汽车转向灯Proteus设计
${comment['nickname']}   ${comment['createtime']}
  
       
${comment.content}
${reply.nickname} 回复 ${comment.nickname}    ${reply.createtime}
     
  
回复内容:${reply.content}