【51单片机】用51单片机定时器/计数器产生音乐的练习(实验报告)

1、8051单片机晶振频率为6MHz,利用T0中断产生周期20ms定时的方波,从P1.0输出点亮LED,并连接一个模拟示波器,编写C语言程序并画出Proteus仿真电路进行仿真。

#include<reg52.h>
sbit L1=P1^0;
timer0() interrupt 1 using 2{
	TH0=0xEC;
	TL0=0x78;
	L1=~L1;

}
void main(){
	TMOD=0x01;//定时器0,方式1
	TH0=0xEC;
	TL0=0x78;
	IE=0x82;
	TR0=1;
	while(1); 
}

Tips:由于要产生的是方波,所以计算初值的时候周期要除以2
在这里插入图片描述

2、利用定时器产生生日快乐歌

声音的频谱范围约在几十到几千赫兹,利用单片机定时器的定时中断功能,可以从一个I/O口线上形成一定频率的脉冲,经过滤波和功率放大,接上喇叭就能发出一定频率的声音,若再利用延时程序控制输出脉冲的频率来改变音调,即可实现音乐发生器功能。

要让单片机产生音频脉冲,只要计算出某一音频的周期,在将此周期除以2得到半周期,利用定时器对此半周期进行定时,每当定时时间到,将某个I/O口线上的电平取反,从而在I/O口线上得到所需要的音频脉冲。

例如中音DO的频率为523Hz,若单片机工作频率为12MHz,定时器T0设置为工作方式1,按公式计算得定时器初值为64580;高音DO的频率为1047Hz,计算得定时器初值为65058。

例如一段延时程序DELAY为1/4拍,则1拍只要调用4次DELAY程序,依此类推。

编写音乐程序时,先把乐谱的音符找出,按表建立对应的简谱码及定时器初值表,按表建立节拍码表。每个音符使用1个字节,字节的高4位存放音符的高低,低4位存放音符的节拍。“生日快乐”乐谱如下:
|5.5 6 5|1 7 -||5.5 6 5|2 1 -|5.5 5 3|1 7 6|4.4 3 1|2 1 -|
请设计乐谱对应的音符节拍码表和音符对应的定时器的初值表。

按照上述原理编写出“生日快乐”乐曲的C语言程序。
使用Proteus仿真电路进行仿真,点击Play按钮执行程序,从计算机的音箱中听到“生日快乐”乐曲。

#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char 
#define uint unsigned int
sbit BEEP=P1^0;						//定义喇叭输出端口
uchar tick,tl,th;					//定义节拍和TO初值变量
uchar TABLE[]={						//音符节拍码表
	0x82, 0x01, 0x81, 0x94, 0x84, 0xB4, 0xA4, 0x04,
	0x82, 0x01, 0x81, 0x94, 0x84, 0xC4, 0xB4, 0x04,
	0x82, 0x01, 0x81, 0xF4, 0xD4, 0xB4, 0xA4, 0x94,
	0xE2, 0x01, 0xE1, 0xD4, 0xB4, 0xC4, 0xB4, 0x04,
	0x82, 0x01, 0x81, 0x94, 0x84, 0xB4, 0xA4, 0x04,
	0x82, 0x01, 0x81, 0x94, 0x84, 0xC4, 0xB4, 0x04,
	0x82, 0x01, 0x81, 0xF4, 0xD4, 0xB4, 0xA4,0x94,
	0xE2, 0x01, 0xE1, 0xD4, 0xB4, 0xC4, 0xB4, 0x04,
	0x00};
uchar TABLE1[]={					//音符对应的定时器初值表
	0xfb, 0x04, 0xfb, 0x90, 0xfc, 0x09, 0xfc,0x44,
	0xfc, 0xac, 0xfd, 0x09, 0xfd, 0x34,0xfd, 0x82,
	0xfd, 0xc8, 0xfe, 0x06, 0xfe, 0x22,0xfe, 0x56,
	0xfe, 0x85, 0xfe, 0x9a, 0xfe, 0xc1};
					/*TO中断服务函数*/
timer0 ()interrupt 1 using 1{ 				//重装定时初值
	TL0=tl; TH0=th;
	BEEP=~ BEEP;}							//喇叭输出端口电平取反
	
void delay1 () {
	uint i;
	for(i=0;i<20000;i++);
	}
	void delay(tt) {
	uchar i;
	for(i=0;i<=tt;i++) delay1();
	}
						/*主函数*/
	void main(){
	uchar t,t1,k=0;							//定义临时变量
	while(1) {
	TMOD=0x01; IE=0x82;						//定义T0工作方式,开中断
	while (TABLE[k]!=0) {					//判断取得的音符节拍码是否为结束码
		tick= (TABLE[k]) &0x0f;				//不是,则取节拍码0[81-8阅)
		t=(_crol_(TABLE[k],4))&0x0f; 		//取音符码
	if(t!=0){								//判断取得的音符码是否为0
		t1=--t*2+1;							//不是,则根据取得的音符码计算TO初值
		t=t*2;
		tl=TL0=TABLE1[t1];
		th=TH0=TABLE1[t];
		TR0=1;								//启动T0
		}
	else TR0=0;								//取得的音符码为0,则停止TO 
	delay(tick);							//根据则取得的节拍码延时
	k++;
			}
	TR0=0;									//取得结束码,则停止TO
		}
	}

在这里插入图片描述

  • 8
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沅_Yuan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值