想用蜂鸣器模拟出音乐,就需要先把乐谱转换为十六进制数,简单看来音乐就是高低不一,长短不一声的音间隔不同时间的排列组合,所以乐谱改编成十六进制就是三个要素:音符即DO,RE,MI,FA,SO,LA,SI这七个不同音符,音高即高中低三种音,节拍即音符之间的间隔时长.

所以基本思路是用根据这三要素定时器产生音频脉冲,不同音符对应频率如下表:

音符

DO (C)

262

523

1046

RE (D)

294

587

1175

MI (E)

330

659

1318

FA (F)

349

698

1397

SO (G)

392

784

1568

LA (A)

440

880

1760

SI (B)

494

988

1967

每个音符使用1个字节,字节的高4位代表音符的高低,低4位代表音符的节拍,下表为节拍码的对照。但如果1拍为0.4秒,1/4拍是0.1秒,只要设定延迟时间就可求得节拍的时间。假设1/4节拍为1DELAY,则1拍应为4DELAY,以此类推。所以只要求得1/4拍的DELAY时间,其余的节拍就是它的倍数,如下表为1/4和1/8节拍的时间设定。

曲调

1/4拍的延迟时间

1/8拍的延迟时间

4/4

125ms

62ms

3/4

187ms

94ms

2/4

250ms

125ms

下面直接用程序举例(世上只有妈妈好,两只老虎)介绍下基本的编程方法:

#include <reg52.h>

#define uchar unsigned char

sbit      beep=P3^6;   //定义蜂鸣器输出端口

sbit  s1 = P3^5; //定义一个按键以免刚烧写程序就开始响,可以不用

uchar timer0h,timer0l,time;

//  数据表  (音符,音高,节拍)以

code uchar sszymmh[]={

//   世上只有妈妈好 6,2,3,     5,2,1,      3,2,2,    5,2,2,    1,3,2,    6,2,1,  5,2,1,

//                  6,2,4,     3,2,2,      5,2,1,    6,2,1,    5,2,2,    3,2,2,    1,2,1,

//                  6,1,1,     5,2,1,      3,2,1,    2,2,4,    2,2,3,    3,2,1,    5,2,2,

//                  5,2,1,     6,2,1,      3,2,2,    2,2,2,    1,2,4,    5,2,3,    3,2,1,

//                  2,2,1,     1,2,1,      6,1,1,    1,2,1,    5,1,6,    0,0,0

//以免刚开始看不清楚,可以用简谱对比看下

// 两只老虎

1,2,2,2,2,2,3,2,2,1,2,2,

1,2,2,2,2,2,3,2,2,1,2,2,

3,2,2,4,2,2,5,2,4,

3,2,2,4,2,2,5,2,4,

5,2,1,6,2,1,5,2,1,4,2,1,3,2,2,1,2,2,

5,2,1,6,2,1,5,2,1,4,2,1,3,2,2,1,2,2,

2,2,2,5,1,2,1,2,4,

2,2,2,5,1,2,1,2,4

};

/*音符频率计算: T = 65536 - 1/Fr/2/MC

T:  要算得的定时器初值

Fr:  各音阶对应的频率

MC: 一个机器周期所需的时间 ,11.0592MHz的晶振对应的机器周期为1.085μs

EX:低音Do对应的频率为262,则T = 65536 - 1/2/1.085/262*(10^6)=63777,对应十六进制数为0xF921,分别写进TH0,和TL0

*/

// 音阶频率表 高八位(计时器初值)

code uchar FREQH[]={0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8,

0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,

0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,

0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,} ;

// 音阶频率表 低八位(计时器初值)

code uchar FREQL[]={0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,

0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,

0x8F,0xEE,0x44, 0x6B,0xB4,0xF4,0x2D,

0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16,};

void delay(uchar t)   // 延时函数  t = 1表示四分之一拍,如果要用到八分之一拍可以改为 t2<2000,类推

{

uchar t1;

unsigned long t2;

for(t1=0;t1<t;t1++)

{

for(t2=0;t2<4000;t2++);

}

TR0=0;

}

void song()  //  音乐处理函数

{

TH0=timer0h;

TL0=timer0l;

TR0=1;

delay(time);

}

void main(void)

{

uchar k,i;

TMOD=1; //置CT0定时工作方式1

EA=1; //中断全开

ET0=1; //IE=0x82 //CPU开中断,CT0开中断

while(1)

{

i=0;

while(i<100)   //音乐数组长度 ,唱完从头再来

{

k=sszymmh[i]+7*sszymmh[i+1]-1;

timer0h=FREQH[k];

timer0l=FREQL[k];

time=sszymmh[i+2];

i=i+3;

if(s1 == 0)

{

song();

}

}

}

}

void t0int() interrupt 1 //定时器0中断函数

{

TR0=0;

beep=!beep;

TH0=timer0h;

TL0=timer0l;

TR0=1;

}

51单片机模拟音乐详解相关推荐

  1. 51单片机步进电机角度控制详解(免费提供代码+仿真)

    51单片机步进电机控制详解 目录 51单片机步进电机控制详解 一.步进电机基本介绍 1. 步进电机结构 2. 步进电机驱动 二.硬件&仿真设计 0.设计要求 1. 硬件设计 显示模块 输入模块 ...

  2. 学习笔记之-51单片机IO口详解

    前言 对单片机的控制,其实就是对I/O口的控制,无论单片机对外界进行何种控制,或接受外部的何种控制,都是通过I/O口进行的.51单片机每个IO端口结构都有差异,都各有各的特点.在平时的应用中,特别是设 ...

  3. 51单片机串口通讯详解

    串口,作为单片机程序开发中最常用.最方便,也是应用最广泛的程序调试方法:无论是作为调试工具,打印出调试信息,还是对功能模块进行通信,串口是每个单片机开发人员最常用的单片机外设. 由于大部分51单片机不 ...

  4. 51单片机矩阵按键详解,两位数码管显示(普中HC6800ESV2.0)

    一.简述 本人是一名在校生,这个学期刚好在学单片机,自己也挺有兴趣,前面在写数码管.时钟啥的程序时都没什么大问题,但是做到矩阵按键时碰到了一些问题,不过已经解决,下面我会把碰到的问题和解决方法都写出来 ...

  5. 51单片机auxr寄存器_MCS-51单片机特殊功能寄存器详解

    1.      定时器/计数器的方式寄存器TMOD TMOD是一个8位的特殊功能寄存器,对应的地址是89H,不可位寻址. A      主要完成三个功能: *确定选择定时器还是计数器: *选择何种工作 ...

  6. 51单片机PWM程序详解

    #include<reg51.h> //程序是基于KEIL-C51编写,引入8051头文件 sbit P10=P1^0; sbit P11=P1^1; unsigned int scale ...

  7. 51单片机数码管详解

    一.数码管基础知识 LED数码管是由多个发光二极管封装在一起组成"8"字型的器件,引线已在内部连接完成,只需引出它们的各个笔划,公共电极.LED数码管常用的段数一般为7段,有的另加 ...

  8. 51单片机DS18B20温度传感器详解

    DS18B20是一种单总线数字温度传感器,测试温度范围-55℃-125℃,具有体积小,硬件开销低,抗干扰能力强,精度高的特点.单总线,意味着没有时钟线,只有一根通信线.单总线读写数据是靠控制起始时间和 ...

  9. 51单片机“密码锁”代码详解

    注:此代码一经过验证,读者不必怀疑其正确性,如果烧录进去没有反应,请自行检查引脚端口配置,以及仔细分析代码实现原理.倘若能静下心来分析代码,一定能受益匪浅. 废话不多说,,直接上代码.如有问题,请下方 ...

最新文章

  1. activemqcpp编译及可能的错误处理
  2. Java数组常见操作
  3. Python之 sklearn:sklearn.preprocessing中的StandardScaler函数的简介及使用方法之详细攻略
  4. 任务调度与上下文切换时间测试
  5. 定义一个包含增强方法的javaBean(最终增强)
  6. 在部署 C#项目时转换 App.config 配置文件
  7. 为你整理了一份 Mysql 的学习笔记,建议收藏学习!
  8. Spcomm使用属性及用法详解
  9. 20172331 《Java程序设计》第3周学习总结
  10. mac命令行配置网络
  11. ubuntu下搭建erlang编程环境
  12. IE7下用ajax动态填充select框的一个问题
  13. 基于Java+Swing实现坦克大战游戏
  14. EXCEL_20211117_filter平替
  15. android url后缀名,Android获取URL中文件的扩展名的方法
  16. 苹果开发者账号申请的一些事
  17. pppo服务器光信号亮红灯,光纤猫光信号闪红灯不能上网怎么办
  18. 练习-Java循环综合练习四之日历打印
  19. 计算机excel二进制,在Excel中实现二进制、八进制、十进制、十六进制之间的转换函数介绍...
  20. 在测试tensorBroad中在运行mnist_with_summaries.py时URLError:urlopen error [WinError 10060] 由于连接方在一段时间后没有正确答

热门文章

  1. 双向buck-boost变换器,采用电压外环,电流内环控制,平均电流控制
  2. java web编写的在线测试(调查)系统 完整源码 附详细设计文档
  3. 计算机存储,数据类型,常量和变量
  4. qq里面cap字符_特殊符号大全
  5. 证券基础知识---股票
  6. 数据库实验报告【太原理工大学】
  7. 2022.3.17内容总结
  8. python彩票预测与分析_303期黄欢福彩3D预测奖号:奖号和值分析
  9. 关于问题“应用程序未安装或安装时出现「INSTALL_FAILED_CONTAINER_ERROR」”的解决方案方面的事情
  10. 数据结构与算法 - 链表(java)