找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6588|回复: 3
打印 上一主题 下一主题
收起左侧

用51单片机 汇编语言 做简单的电子琴

[复制链接]
跳转到指定楼层
楼主


源程序

SPEAKE BIT P3.0;接到蜂鸣器
MAINLED BIT P3.1
AUTOSING BIT P2.0
SINGLED BIT P3.2
AUTOSTOP BIT P2.1
PLAYSING BIT P2.2
PLAYLED BIT P3.3
PLAYSTOP BIT P2.3
FAST BIT P2.4
FASTLED BIT P3.4
FASTFLAG BIT 00H

ORG 0000H
LJMP MAIN

ORG 000BH
LJMP TIM0;TIMER0的中断服务程序

ORG 1000H
MAIN:
MOV SP,#60H;初始化堆栈
MOV TMOD,#01H;计数器工作在MODE1,16位计数器
SETB ET0;开定时/计数器0允许
SETB EA;允许单片机总中断
MOV P3,#0FCH;让除了MAIN以外的灯灭
MOV 40H,#83;设置初始速度
MOV 30H,#00H;初始化偏移量

START0:
JB AUTOSING,PLAY1/*若按下p2.0,表示想要自动播放歌曲*/
SETB MAINLED
CLR SINGLED
JMP SONG1
PLAY1:
JB PLAYSING,START0/*若按下PLAYSING表示想要弹琴*/
SETB MAINLED
CLR PLAYLED
LJMP PLAY2

;播放歌曲的程序段
SONG1:
MOV A,30H;将偏移量传入A
MOV DPTR,#SONG;取得歌曲表的首地址
MOVC A,@A+DPTR;取得相应音符
JZ OVER;若8位全为0表示播放歌曲结束
MOV R2,A
ANL A,#0FH;从低4位取出节拍
MOV R5,A;存入R5,用于定时器的中断服务程序
MOV A,R2;再导入R2
SWAP A
ANL A,#0FH;取出频率向量
JNZ SING;若为0表示无声
CLR TR0 ;不记数
JMP D1
;取出频率(计数值)的程序段
SING:
DEC A;减1,因为要从0位置开始
RL A;在计数值表中以字存储,乘2才得到正确位置
MOV 22H,A;将位置暂存
MOV DPTR,#TAB1;计数值表
MOVC A,@A+DPTR
MOV TH0,A;取到的高位放入TH0
MOV 21H,A;暂存到21H,用于中断程序
MOV A,22H
INC A;取低位地址
MOVC A,@A+DPTR
MOV TL0,A;放入TL0
MOV 20H,A;暂存到20H,用于中断程序
SETB TR0;计数器开始计数
D1:
ACALL DELAY
INC 30H;播放完一个音符后将偏移量加1
JMP SONG1
OVER:
SETB SINGLED
CLR MAINLED
LJMP MAIN
;以下是电子琴的程序段
PLAY2:
MOV A,#0FH  ;先给p1的高4位置1,低4位置0,判断是哪行
MOV P1,A
MOV R3,#00H
MOV R4,#00H
PLAY3:
ACALL DELAY20;加上这个就不会有串音的现象了
JB PLAYSTOP,PL0;若按下退出电子琴键则跳回
SETB PLAYLED
CLR MAINLED
LJMP START0
;以下是判断矩阵键盘的按键
;判断是哪行按下
PL0:
MOV A,P1
JB ACC.0,PL1
MOV R3,#0
SJMP LINE
PL1:
JB ACC.1,PL2
MOV R3,#1
SJMP LINE
PL2:
JB ACC.2,PL3
MOV R3,#2
SJMP LINE
PL3:
JB ACC.3,PLAY3
MOV R3,#3
;判断是哪列
LINE:
MOV A,#0F0H;这次给低位置1,高位置0
MOV P1,A
MOV A,P1
LINE4:
JB ACC.4,LINE5
MOV R4,#0
SJMP PLAY4
LINE5:
JB ACC.5,LINE6
MOV R4,#4
SJMP PLAY4
LINE6:
JB ACC.6,LINE7
MOV R4,#8
SJMP PLAY4
LINE7:
JB ACC.7,PLAY3
MOV R4,#12
;这样就可以用R4+R3得出是哪个键被按下
PLAY4:
MOV A,R3
ADD A,R4
ACALL YOUPLAY;得出按键后就调出频率发声就行了
LOOP:;将这个地方做做修改
MOV A,P1
ORL A,#0FH
CPL A
JZ OFF
JMP LOOP
OFF:CLR TR0
LJMP PLAY2

;定时计数器0中断服务程序
TIM0:
PUSH ACC
PUSH PSW
MOV TL0,20H;将暂存的计数值再放进去
MOV TH0,21H
CPL SPEAKE;取反
POP PSW
POP ACC
RETI

;弹琴的子程序
YOUPLAY:
RL A
MOV 22H,A;将位置暂存
MOV DPTR,#TAB1
MOVC A,@A+DPTR
MOV 21H,A
INC 22H
MOV A,22H
MOVC A,@A+DPTR
MOV 20H,A
MOV TH0,21H
MOV TL0,20H
SETB TR0
RET

;延时20ms,用于防抖
DELAY20:
mov r1,#50h
del0:mov r2,#7dh
del1:djnz r2,del1
djnz r1,del0
RET

;节拍延时函数,用于产生每个音符的节拍,延时187ms
DELAY:
MOV R7,#02
D2:MOV R4,#187
D3:MOV R3,40H
TEST:
JB FAST,TEST1;若没有按下快进键直接去检测是否按下暂停键
JB FASTFLAG,FASTSTOP;FAST为0表示可以快进,FAST为1表示已经在快进状态
SETB FASTFLAG
CLR FASTLED
MOV 40H,#30;用30使播放速度变快
LJMP DELAY
FASTSTOP:
CLR FASTFLAG
SETB FASTLED
MOV 40H,#83
LJMP DELAY
TEST1:
JB AUTOSTOP,GO_ON
CLR TR0
SETB SINGLED
CLR MAINLED
LJMP START0
GO_ON:
DJNZ R3,TEST
DJNZ R4,D3
DJNZ R7,D2
DJNZ R5,DELAY
RET
;计数表
TAB1:
DW 64580,64684,64777,64820
DW 64898,64968,65030,65058
DW 64260,64400,64524,65217
DW 65252,65283,65300,65330
;歌曲表,高位是频率,低位是节拍
SONG:
;洋娃娃和小熊跳舞
/*
DB 12H,22H,32H,42H,52H,52H,51H,41H,32H
DB 42H,42H,41H,31H,22H,12H,32H,54H
DB 12H,22H,32H,42H,52H,52H,51H,41H,32H
DB 42H,42H,41H,31H,22H,12H,32H,14H
DB 62H,62H,61H,51H,42H,52H,52H,51H,41H,32H
DB 42H,42H,41H,31H,22H,12H,32H,54H
DB 62H,62H,61H,51H,42H,52H,52H,51H,41H,32H
DB 42H,42H,41H,31H,22H,12H,32H,14H,00H
*/
/*
;东风破
;一个小节是一行;9,A,B
DB 22H,12H,22H,33H,21H,22H,12H
DB 22H,12H,12H,0A2H,28H
DB 02H,22H,12H,22H,33H,21H,21H,11H,12H
DB 22H,12H,11H,0A1H,0A1H,91H,98H
DB 02H,52H,52H,52H,32H,32H,32H,42H
DB 53H,41H,42H,4AH
DB 02H,22H,22H,32H,21H,11H,12H,0A2H,12H
DB 62H,62H,62H,52H,58H
;反复记号后面
DB 02H,32H,32H,32H,33H,21H,22H,12H
DB 22H,32H,22H,12H,26H,32H
DB 02H,22H,0A2H,12H,23H,11H,12H,22H
DB 32H,52H,52H,32H,58H
DB 02H,52H,52H,52H,63H,51H,32H,42H
DB 54H,62H,4AH
DB 02H,22H,22H,12H,32H,22H,12H,0A2H
DB 22H,12H,22H,1AH
;括号里面的
DB 61H,31H,51H,21H,31H,21H,11H,0A1H,91H,0A1H,11H,21H,31H,51H,61H,81H
*/
;括号后面的反复记号
DB 02H,52H,52H,52H,63H,71H,62H,52H
DB 32H,32H,32H,22H,24H
DB 02H,52H,52H,52H,32H,22H,22H,12H
DB 22H,12H,22H,32H,34H
DB 02H,0B2H,12H,22H,32H,22H,32H,52H
DB 32H,22H,12H,22H,0A4H,04H
DB 02H,12H,12H,22H,32H,22H,32H,52H
DB 62H,52H,52H,32H,32H,32H,32H,22H
;重复
DB 02H,52H,52H,52H,63H,71H,62H,52H
DB 32H,32H,32H,22H,24H
DB 02H,52H,52H,52H,32H,22H,22H,12H
DB 22H,12H,22H,32H,34H
DB 02H,0B2H,12H,22H,32H,22H,32H,52H
DB 62H,52H,52H,32H,54H
DB 02H,62H,62H,52H,33H,51H,32H,22H
DB 02H,22H,22H,12H,32H,22H,12H,0A2H
DB 22H,1EH
;第二个括号里面
DB 3AH,22H,32H,0A2H
DB 16H,21H,31H,54H
DB 02H,32H,32H,32H,32H,61H,51H,33H,21H
DB 32H,51H,3DH
DB 6AH,32H,23H,31H
DB 21H,11H,0A6H,0A6H,21H,31H
DB 24H,22H,11H,0A1H,92H,0A1H,11H,14H,14H
DB 00H
END



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:362684 发表于 2018-7-2 09:54 | 只看该作者
有文件吗
回复

使用道具 举报

板凳
ID:561414 发表于 2019-6-14 00:46 | 只看该作者
啊啊啊啊,太感谢了谢谢大佬,热泪盈眶QAQ
回复

使用道具 举报

地板
ID:566264 发表于 2019-6-28 22:25 来自手机 | 只看该作者
大佬,做成电路板蜂鸣器为啥不出歌
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表