用蜂鸣器来首月光奏鸣曲第三乐章怎么样

最近买了块pybase的板子,主要为了学习micropython,最后选择了01studio家的,不是我打广告,我博客也没人看,没有必要打广告哈哈,主要是他家的教程确实是全网最细的,昨天自学到蜂鸣器,DAC这一章了,突然反应过来,家里的热水器什么的那种自带音乐芯片的会不会也是这个玩意?自己也懂些乐器,所以干脆自己编个曲子得了,为了显示出硬核,来首贝多芬的月光奏鸣曲第三乐章好了。
先找到了音符与hz间的联系,乐理上大概是每半音相差1.06倍,也就是一个八度刚好差2倍,找了张图:
在这里插入图片描述然后就是撸代码!


'''
实验名称:DAC-蜂鸣器-演奏月光奏鸣曲
版本:v1.0
日期:2021.1
作者:jd3096
说明:通过USER按键播放
'''

#导入相关模块
from pyb import DAC,Switch,Pin,ExtInt,LED
from machine import Pin,I2C
from ssd1306 import SSD1306_I2C
import time

#初始化相关模块
i2c = I2C(sda=Pin("Y8"), scl=Pin("Y6"))
oled = SSD1306_I2C(128, 64, i2c, addr=0x3c)
dac = DAC(1)     #定义DAC对象名字为dac,输出引脚为X5

#事先写好的谱子,把音符转化为HZ
play1=[138, 208, 278, 330, 416, 278, 330, 416, 554, 330, 416, 554, 660, 416, 554, 660, 830, 554, 660, 830, 1108, 660, 830, 1108, 1318, 830, 1108, 1318, 1662, 1, 1662, 1]
play2=[131,208,262,311,415,262,311,415,523,311,415,523,622,415,523,622,831,523,622,831,1047,622,831,1047,1245,831,1047,1245,1662,1,1662,1]
play3=[123,227,349,415,554,349,415,554,698,415,554,698,831,554,698,831,1108,698,831,1108,1397,831,1108,1397,1661,1108,1397,1661,2218,1,2218,1]
play4=[110,277,370,440,554,554,740,880,1109,1109,1480,1760,2217,1,2217,1,110,277,330,392,554,554,659,784,1109,1109,1319,1568,2218,1,2218,1]
play5=[2094,1,831,1661,831,1661,923,1661,1047,1661,1109,1661,1245,1661,1109,1661,1245,1661,1109,1661,1480,1661,1319,1661,1245,1661,1109,1661,1047,1661,880,1568]
play6=[831,1661,831,1661,831,1661,923,1661,1047,1661,1109,1661,1245,1661,1109,1661,1245,1661,1109,1661,1480,1661,1319,1661,1245,1661,1109,1661,1047,1661,880,1568]
play7=[831,1661,880,1568,831,1661,880,1568,831,1661,880,1568,831,1661,880,1568,1661,1661,1661,1661,831,831,831,831,831,831,831,831,831,831,831,831,1]
playlist=play1+play2+play3+play4+play5+play6+play7
# 定义8位精度下方波的值。0、255分别对应输出0V、3.3V。需要定义成字节数组。
buf = bytearray(2)
buf[0]=0
buf[1]=255

tempo=0.1
# 定义了速度,0.1秒演奏一个音

def playstart():
    oled.fill(0)  # 清屏显示黑色背景
    oled.text('Moonlight Sonata', 0, 0)  
    oled.text('3rd', 0, 15)
    oled.text('Beethoven', 0, 30)  
    oled.text('Playing...', 0, 45)  
    oled.show()
    for num in playlist:
        pl(num)

def pl(hz):
    dac.write_timed(buf, hz*len(buf), mode=DAC.CIRCULAR)
    time.sleep(tempo)

##############################################
#  OLED初始显示
##############################################
oled.fill(0)  # 清屏显示黑色背景
oled.text('Moonlight Sonata', 0, 0)  
oled.text('3rd', 0, 15)
oled.text('Beethoven', 0, 30)  
oled.text('Press USER', 0, 45)  
oled.show()

callback=lambda e:playstart()  #中断用法
ext=ExtInt(Pin('Y1'),ExtInt.IRQ_FALLING,Pin.PULL_UP,callback)

嗯,因为这个乐曲还是挺难的,平时听的这种音乐芯片都是什么兰花草、东方红啥的,有的还有明显的错误,这次费了我俩小时时间,把音符转换为HZ,最后整完了一听,很有电子那味儿嘛,就像网易云音乐评论里面说的,贝多芬放到现在绝壁是个金属摇滚大师!

下面是一段用汇编语言实现的模拟琴键的代码,使用数字键1~8模拟琴键1~1(高音),并通过PC扬声器发出相应的音调: ``` .MODEL SMALL .STACK 100H .DATA NOTE1 DB 0C9H ;音调1的频率值 NOTE2 DB 0D1H ;音调2的频率值 NOTE3 DB 0D9H ;音调3的频率值 NOTE4 DB 0E1H ;音调4的频率值 NOTE5 DB 0E9H ;音调5的频率值 NOTE6 DB 0F1H ;音调6的频率值 NOTE7 DB 0F9H ;音调7的频率值 NOTE8 DB 101H ;音调8的频率值 .CODE MAIN PROC MOV AX, @DATA MOV DS, AX ;初始化数据段寄存器 MOV DX, 61H MOV AL, 0B6H OUT DX, AL ;初始化PC扬声器控制寄存器 WAIT: IN AL, 60H CMP AL, 31H JE PLAY1 CMP AL, 32H JE PLAY2 CMP AL, 33H JE PLAY3 CMP AL, 34H JE PLAY4 CMP AL, 35H JE PLAY5 CMP AL, 36H JE PLAY6 CMP AL, 37H JE PLAY7 CMP AL, 38H JE PLAY8 JMP WAIT PLAY1: MOV AL, NOTE1 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT PLAY2: MOV AL, NOTE2 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT PLAY3: MOV AL, NOTE3 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT PLAY4: MOV AL, NOTE4 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT PLAY5: MOV AL, NOTE5 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT PLAY6: MOV AL, NOTE6 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT PLAY7: MOV AL, NOTE7 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT PLAY8: MOV AL, NOTE8 OUT 42H, AL MOV AL, AH OUT 42H, AL MOV AL, 0B6H OUT DX, AL JMP WAIT MAIN ENDP END MAIN ``` 在这段代码中,我们使用了8254芯片控制PC扬声器的工作频率,通过按下数字键1~8来选择不同的音调,同时使用了循环来不断等待键盘输入。注意,这段代码只能在实模式下运行,而且需要在DOS或类DOS操作系统下运行。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值