51单片机蜂鸣器乐谱放不完

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51单片机蜂鸣器乐谱放不完相关的知识,希望对你有一定的参考价值。

参考技术A 首先要有蜂鸣器乐谱,就是用频率和持续时间表示一个音符的乐谱,至于如何获取蜂鸣器乐谱可以看我上一篇文章。由于单片机的运行速度很慢,如果在单片机里计算循环次数会浪费很多时间,导致输出的音乐断断续续的,所以我尽量在电脑上完成计算,单片机直接读取循环次数就行了

已知单片机使用的晶振频率(我用的11059200Hz),机器主频是晶振频率的12分频,所以一个机器周期是 1/(晶振频率/12) 1 / (晶振频率 / 12)1/(晶振频率/12) 秒。还要知道for循环一次需要多少个机器周期,我是在keil仿真调试时开启定时器测出来的,是38个周期。一次循环时间就是 机器周期∗1000∗每次循环机器周期数 机器周期 * 1000 * 每次循环机器周期数机器周期∗1000∗每次循环机器周期数 毫秒,然后可以算出发出相应频率的方波需要几次循环

下面是把蜂鸣器乐谱转成循环次数的Python脚本:

import json

# 晶振频率(Hz)
CRYSTAL_FREQUENCY = 11059200
# 计数周期(机器周期)(s)
COUNT_PERIOD = 1 / (CRYSTAL_FREQUENCY / 12)
# 一次循环几个机器周期,通过定时器实验得到
COUNT_PER_LOOP = 38
# 一次循环时间(ms)
MS_PER_LOOP = COUNT_PERIOD * 1000 * COUNT_PER_LOOP

def tone_to_loop_count(notes, output_path):
res = []
for frequency, duration in notes:
if frequency == 0:
# 延时
loop_count = 65535
period_count = round(duration / MS_PER_LOOP)
else:
period = 1000 / frequency
loop_count = round(period / 2 / MS_PER_LOOP)
period_count = round(duration / period)
# 最低频率0.185,loop_count = 65534
assert 0 <= loop_count <= 65535, f'frequency = frequency, loop_count = loop_count,不在unsigned int范围内'
# 把一个时间过长的音符拆成多个音符
while period_count > 65535:
res.append((loop_count, 65535))
period_count -= 65535
res.append((loop_count, period_count))

with open(output_path + '.h', 'w') as f:
f.write(f"""#define DELAY_COUNT 65535
#define NOTES_LEN len(res)
extern const unsigned int code notes[][2];
""")

with open(output_path + '.c', 'w') as f:
f.write('const unsigned int code notes[][2] = n')
for i in range(0, len(res), 6):
f.write('t')
for loop_count, period_count in res[i: i + 6]:
f.write(f'loop_count, period_count, ')
f.write('n')
f.write(';n')

def main():
with open('beep.json') as f:
notes = json.load(f)
tone_to_loop_count(notes, '../beep/music_data')

if __name__ == '__main__':
main()

单片机代码
单片机代码就很简单了,读取循环次数然后循环发出方波

#include

#include "music_data.h"

// 引脚定义
#define beepOut P1_0

int main()
beepOut = 0;
while (1)
unsigned int i, j, k;
for (i = 0; i < NOTES_LEN; ++i)
if (notes[i][0] == DELAY_COUNT) // 延时
for (j = 0; j < notes[i][1]; ++j);
else
for (j = 0; j < notes[i][1]; ++j)
for (k = 0; k < notes[i][0]; ++k);
beepOut = 1;
for (k = 0; k < notes[i][0]; ++k);
beepOut = 0;




return 0;

atmega328p 单片机里面有自带蜂鸣器吗

参考技术A 目前没有哪个单片机是带蜂鸣器的

以上是关于51单片机蜂鸣器乐谱放不完的主要内容,如果未能解决你的问题,请参考以下文章

51单片机 外部中断1触发蜂鸣器+Proteus仿真

蜂鸣器设置到所求频率单片机

51单片机 外部中断0触发蜂鸣器+Proteus仿真

51单片机学习笔记4 -- 蜂鸣器控制

51单片机学习笔记4 -- 蜂鸣器控制

如何让无源蜂鸣器在不加单片机的情况下发出嘀嘀嘀的间断声?