"作者在上次离职后闲来无事学习了下电路相关的内容,简单了解了下单片机做出的一个小作品\n\n# 理论准备\n\n无源蜂鸣器发声原理:无源蜂鸣器内部不带内部震荡源,因此需要对51单片机发出的方波信号进行放大才能将无源蜂鸣器进行驱动。\n发出固定频率声音的方法:上述提到需要使用方波进行驱动,因此只需要51单片机能产生出对应的方波信号即可。已知标准音A = 440HZ,通过12平均律的计算方法F(y) = x * (y-x的音数)*1.059463。可以计算出一组有效的,满足12平均律的频率。\n\n\n| C | D | E | F | G | A | B | C |\n| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |\n| 2093 | 2349 | 2636 | 2793 | 3135 | 3519 | 3951 | 4185 |\n\n

十二平均律的对应频率
\n\n频率是指在1s内震动的次数,公式为f = 1/T,T为震动一次的时间。使用51单片机控制频率的关键是在T时间内保持为高电平或者是低电平,然后T结束后立刻反转电平,达到震荡的目的。\n\n根据频率计算公式得出f和T的关系\n\n\n| 音名 | C | D | E | F | G | A | B | C |\n| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |\n| f | 2093 | 2349 | 2636 | 2793 | 3135 | 3519 | 3951 | 4185 |\n| T | 477 | 425 | 379 | 357 | 318 | 284 | 253 | 238 |\n\ntext\n -------- -------\n | T | | T |\n | | | |\n | | T | | T\n ------------------------------------------------>\n\n\n# 具体实现\n\nc\n#include \"reg52.h\"\n// 对数据类型重定义\ntypedef unsigned char u8;\ntypedef unsigned int u16;\n\n// 已知51开发板的蜂鸣器输出端口连接的是p15\nsbit beep= P1^5;\n\n/**\n * 震动一次需要花费的时间,单位us\n * 这个地方与表中的数据少10倍的原因是一次i--的指令执行需要花费10us,不能再更精细了,所以\n * 直接转换除以10避免无意义的计算。\n * 0 C D E F G A B C\n */\nint T[] = {0,48,43,38,36,32,28,25};\n\n/**\n * 延迟函数,执行一次t--的时间花费约为10us\n * 例如 t=10,则delay(10)将会延迟大约100us\n */\nvoid delay(u16 t) {\n while(t--);\n}\n/**\n * 发声函数\n * v 音调,对应T[],如果v = 1,则表示需要发C音\n * t 音的持续时间\n * 如果一个音要发500ms,得计算出该音频率下要进行多少次高低电平翻转\n * 反转次数 = 500000us / T, 函数中的计算做了单位转换防止u16溢出\n * 然后对电平进行控制,使得在一段时间内(通过延时函数保证)输出一样的电平\n * 之后立刻进行电平反转\n */\nvoid play(u8 v,u16 time) {\n u16 t= time / T[v] * 100;\n\twhile(t--) { // 控制反转次数\n\t beep=~beep; // 电平反转\n\t delay(T[v]); // 维护电平输出时长\n\t}\n}\n\n/**\n * 小星星的简谱:\n * 4/4 \n * C C G G | A A G - | F F E E | D D C -\n * G G F F | E E D - | G G F F | E E D -\n * C C G G | A A G - | F F E E | D D C -\n */\n\n/**\n * 播放A段 C C G G | A A G - | F F E E | D D C -\n */\nvoid playA() { \n \tplay(1,500);\n\tplay(1,500);\n\tplay(5,500);\n\tplay(5,500);\n\tplay(6,500);\n play(6,500);\n\tplay(5,1000);\n // FFEEDDC\n \tplay(4,500);\n\tplay(4,500);\n\tplay(3,500);\n\tplay(3,500);\n\tplay(2,500);\n play(2,500);\n\tplay(1,1000);\n}\n\n/**\n * 播放B段 G G F F | E E D - | G G F F | E E D -\n */\nvoid playB() {\n int i=0;\n\t//GGFFEED\n\tfor(i=0;i<2;i++) {\n\t\tplay(5,500);\n\t\tplay(5,500);\n\t\tplay(4,500);\n\t\tplay(4,500);\n\t\tplay(3,500);\n\t play(3,500);\n\t\tplay(2,1000);\n\t}\n}\n\n/**\n * 主函数,进行小星星播放\n */\nvoid main() {\n while(1) {\n\tplayA();\n\tplayB();\n\tplayA();\n\tbreak;\n }\n}\n\n\n仓库地址: 51播放小星星\n\n# 效果展示\n\n<iframe src="https://player.bilibili.com/player.html?aid=840568858&bvid=BV1p54y1X7Q8&cid=186998634&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> \n\n或者跳转到这里https://www.bilibili.com/video/BV1p54y1X7Q8?share_source=copy_web\n"