C51蜂鸣器演奏两只老虎

/*两只老虎**/

#include<reg52.h> sbit Buzz = P1^6; //声明绑定蜂鸣器

unsigned int code NoteFrequ[]={   523,587,659,698,784,880,988,    //中音对应的1-7  

  1047,1175,1319,1397,1568,1760,1976   //高音对应的1-7

};

unsigned int code NoteReload[]={ //中音1-7和高音1-7对应的定时器重载值

   65536 - (11059200/12) /(523*2),//中音1-7  

  65536 - (11059200/12) /(587*2),  

  65536 - (11059200/12) /(659*2),

  65536 - (11059200/12) /(698*2),

  65536 - (11059200/12) /(784*2),  

  65536 - (11059200/12) /(880*2),

  65536 - (11059200/12) /(988*2),

  65536 - (11059200/12) /(1047*2),//高音1-7  

  65536 - (11059200/12) /(1175*2),  

  65536 - (11059200/12) /(1319*2),  

  65536 - (11059200/12) /(1397*2),

  65536 - (11059200/12) /(1568*2),

  65536 - (11059200/12) /(1760*2),

  65536 - (11059200/12) /(1970*2)};

bit enable = 1; //发声使能标志

bit tmrflay = 0; //定时器 中断完成标志

unsigned char T0RH = 0xff; //T0重载值高字节

unsigned char T0RL = 0x00; //T0重载值低字节

void PlayTwoTiger(); void main(){   

  unsigned int i;

   EA = 1;

   TMOD =0x01;  //模式1

   TH0 = T0RH;

   TL0 = T0RL;  

  ET0 = 1;  //使能T0中断

    TR0 = 1;  //启动

   while(1){  

   PlayTwoTiger();

    for(i=0;i<40000;i++); 

   }

}

/**音乐函数**/

 void PlayTwoTiger(){

  unsigned char beat;    //节拍索引

 unsigned char note;    //节拍对应音符

 unsigned int time=0;   //节拍计时

 unsigned int beattime=0;  //总时间计时

 unsigned int soundtime=0; //没拍发声时间

 unsigned char code PlayTwoTigerNote[]={ //音符表

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

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

 };  

unsigned char code PlayTwoBeat[]={  //节拍表,4表示一拍,1表示1/4拍,8表示两拍   

    4,4,4,4, 4,4,4,4, 4,4,8, 4,4,8,   

    3,1,3,1,4,4, 3,1,3,1,4,4, 4,4,8, 4,4,8,  

 };   

for(beat=0; beat<sizeof(PlayTwoTigerNote);){ //节拍索引循环变量   

 while(!tmrflay);   //每次定时器中断完成 节拍处理  

   tmrflay = 0;       

 if(time == 0){       //节拍播放完成重启

    note = PlayTwoTigerNote[beat]-1;

    T0RH = NoteReload[note]>>8;

    T0RL = NoteReload[note];     //计算总时间,右移2位等于除4,移位代替除法加快速度

    beattime = (PlayTwoBeat[beat]*NoteFrequ[note])>>2;   //计算发声时间,为总时间的0.75s

    soundtime =beattime - (beattime>>2);  

   enable = 1;  //开始发声  

   time++;   

    }else{    //节拍播放未结束则继续处理

      if(time >= beattime){ //当前时间清零  

        time = 0;     //准备重新启动

       beat++;   

    }else{       //累加时间

     time++;   

   if(time == soundtime){    //发声时间到达,关闭蜂鸣器

        enable =0;      //用以区分连续两个节拍  

      }

     }  

  }

   }

 }  

void InterRupt() interrupt 1{//中断服务

 TH0 =T0RH;

 TL0 =T0RL;

 tmrflay = 1;

 if(enable){  

   Buzz=~Buzz;

   }else{   

    Buzz=1;

   }

 }

 

转载于:https://www.cnblogs.com/robotes/p/7795860.html

本目录下提供的是《手把手教你学51单片机(C语言版)》教材中所有例程与作业习题的源代码。 请将整个目录复制到电脑硬盘上使用,如直接在光盘路径下打开工程可能会导致软件报错。 运行目录下的Clean.bat可以清理程序编译过程中产生的中间文件和临时文件。 lesson2 (第2章): 点亮一个LED示例,所在章节2.4 lesson3 (第3章): LED闪烁示例,所在章节3.5 lesson4 (第4章): 4_1:用P0口控制LED的示例,所在章节4.8 4_2:用P0口控制实现流水灯效果,所在章节4.8 4_t4:作业题4,逐次右移的流水灯效果,所在章节4.9 4_t5:作业题5,左右往复移动的流水灯效果,所在章节4.9 lesson5 (第5章): 5_1:基于定时器查询模式的LED闪烁,所在章节5.2.3 5_2:静态点亮数码管的某几段,所在章节5.3.2 5_3:数码管静态显示一位字符,所在章节5.3.3 5_t3:作业题3,定时器查询模式实现左右移动的流水灯,所在章节5.4 5_t5:作业题5,变更lesson5_3的正计数为倒计数,所在章节5.4 lesson6 (第6章): 6_1:数码管动态显示原理示例(if...else if...语句示例),所在章节6.4 6_2:数码管动态显示原理示例(switch...case...语句示例),所在章节6.4 6_3:基于中断带消隐的数码管动态显示示例,所在章节6.5 6_t4:作业题4,在lesson6_3多位数字显示的基础上不显示高位的0,所在章节6.6 6_t5:作业题5,变更lesson6_3的正计数为倒计数,所在章节6.6 lesson7 (第7章): 7_1:基于数码管计时程序的静态变量演示,所在章节7.2 7_2:点亮LED点阵上的一个点,所在章节7.3 7_3:点亮LED点阵上的一行,所在章节7.3 7_4:点亮LED点阵上的全部点,所在章节7.3 7_5:LED点阵显示静态图形,所在章节7.4 7_6:LED点阵显示纵向移动的动画,所在章节7.5.1 7_6_h:LED点阵显示横向移动的动画(掉转板子方向的取巧方式),所在章节7.5.2 7_7:LED点阵显示横向移动的动画,所在章节7.5.2 7_t3:作业题3,lesson7_6的向上移动改为向下移动,所在章节7.6 7_t4:作业题4,lesson7_7的向左移动改为向右移动,所在章节7.6 7_t5:作业题5,基于LED点阵的9~0倒计数,所在章节7.6 7_t6:作业题6,独立LED、数码管、点阵LED同时全亮,所在章节7.6 lesson8 (第8章): 8_1:基于数码管计时程序的函数调用演示,所在章节8.2 8_2:按键基本原理演示例程,所在章节8.4.3 8_3:独立按键扫描原理演示例程,所在章节8.4.3 8_4:独立按键消抖原理演示例程,所在章节8.4.4 8_5:独立按键扫描并消抖的演示例程,所在章节8.4.4 8_6:矩阵按键扫描并消抖的演示例程,所在章节8.4.5 8_7:基于矩阵按键和数码管实现的简易加法计算器,所在章节8.5 8_t4:作业题4,变更lesson8_5的递增计数为递减计数,所在章节8.6 8_t5:作业题5,在lesson8_7基础上实现简易加减计算器,所在章节8.6 lesson9 (第9章): 9_1:步进电机驱动的基础示例,所在章节9.3.3 9_2:步进电机转动任意角度的示例,所在章节9.3.4 9_3:实用的步进电机驱动示例,所在章节9.3.5 9_4:按键控制步进电机转动的示例,所在章节9.3.6 9_5:蜂鸣器驱动的基础示例,所在章节9.4 9_6:蜂鸣器演奏简单乐谱——“两只老虎”,所在章节9.4 lesson10 (第10章): 10_1:基于数码管显示的数字秒表,所在章节10.1 10_2:基于PWM方式控制LED的亮度,所在章节10.2 10_3:基于PWM方式控制LED实现呼吸灯效果,所在章节10.2 10_4:交通信号灯示例,所在章节10.3 10_5:长短按键/连续按键功能实现示例,所在章节10.5 10_t3:作业题3,数码管计时与流水灯同时运行的示例,所在章节10.6 lesson11 (第11章): 11_1:普通IO口模拟实现串口通信的示例,所在章节11.4 11_2:单片机硬件UART查询方式实现串口通信的示例,所在章节11.5.3 11_3:单片机硬件UART中断方式实现串口通信的示例,所在章节11.5.3 11_4:UART串口通信及控制数码管显示的示例,所在章节11.6 11_t5:作业题5,UART串口控制流水灯流动和停止,所在章节11.7 11_t6:作业题6,UART串口控制蜂鸣器的开关,所在章节11.7 lesson12 (第12章): 12_1:指针作为函数参数的示例,所在章节12.1 12_2:指向变量的指针与变量关系的示例,所在章节12.2 12_3:指针、字符串、字符数组、ASCII码演示示例,所在章节12.3 12_4:1602液晶基本操作演示示例,所在章节12.4 lesson13 (第13章): 13_1:1602液晶显示两行字符串,并实现整屏的重复左移,所在章节13.2 13_2:多c文件示例,1602液晶显示两行字符串,并实现整屏的重复左移,所在章节13.3 13_3:整型数为操作数的简易+-*/计算器,所在章节13.4 13_4:基于帧模式的实用串口程序示例,所在章节13.5 13_t2:作业题2,1602液晶显示两行字符串,并实现整屏的重复右移,所在章节13.6 lesson14 (第14章): 14_1:寻址I2C总线上存在的和不存在的地址,将应答状态显示到液晶上,所在章节14.2 14_2:用单字节读写模式访问EEPROM,每次+1后写回,所在章节14.3.1 14_3:用多字节读写模式访问EEPROM,依次+1,+2,+3...后写回,所在章节14.3.2 14_4:用连续读与分页写模式访问EEPROM,依次+1,+2,+3...后写回,所在章节14.3.3 14_5:读取EEPROM中的数据显示到液晶,并可通过UART修改EEPROM中的数据,所在章节14.4 14_t3:作业题3,以lesson10_4为基础实现可通过UART设定时间的交通灯示例,所在章节14.5 14_t4:作业题4,基于液晶、按键、EEPROM的密码锁示例,所在章节14.5 lesson15 (第15章): 15_1:用单次读写模式访问DS1302,并将日期时间显示在液晶上,所在章节15.3.4 15_2:用突发读写模式访问DS1302,并将日期时间显示在液晶上,所在章节15.3.5 15_3:DS1302实现简易电子钟,通过按键校时,所在章节15.5 lesson16 (第16章): 16_1:接收NEC协议的红外编码并将用户码和键码显示到数码管上,所在章节16.3 16_2:控制DS18B20测量温度并将温度值显示到液晶上,所在章节16.4 16_t2:作业题2,用遥控器控制步进电机正反转,所在章节16.5 16_t4:作业题4,带温度显示的电子钟,所在章节16.5 lesson17 (第17章): 17_1:将模拟输入通道0、1、3的电压值显示到液晶上,所在章节17.4 17_2:由按键控制DA输出可调电压值,所在章节17.6 17_3:由按键控制DA输出可变化的波形,所在章节17.7 17_t3:作业题3,可调频率的信号发生器,所在章节17.8 lesson18 (第18章): 18_1:RS485基本示例,接收任意数据帧并添加回车换行后送回,所在章节18.1 18_2:基于RS485的Modbus通信示例,支持寄存器读写操作,所在章节18.3 18_t3:作业题3,基于Modbus协议实现电子钟校时,所在章节18.4 lesson19 (第19章): 19_1:多功能电子钟例程,所在章节19.4
以下是C51控制蜂鸣器播放两只老虎的代码: ```c #include <reg52.h> #define uint unsigned int #define uchar unsigned char sbit beep=P1^5; //定义P1.5为蜂鸣器引脚 uchar code music[]={ 0x09,0x09,0x0a,0x0a,0x0c,0x0c,0x0a,0, //两只老虎 0x09,0x09,0x0a,0x0a,0x0c,0x0c,0x0a,0, //两只老虎 0x0c,0x0c,0x0d,0x0d,0x0f,0x0f,0x0c,0, //小星星 0x0c,0x0c,0x0d,0x0d,0x0f,0x0f,0x0c,0 //小星星 }; uchar beat[]={ //每个音符的节拍 10,10,20,20,20,20,40,40, 10,10,20,20,20,20,40,40, 10,10,20,20,20,20,40,40, 10,10,20,20,20,20,40,40 }; void delay_ms(uint x) //延时函数 { uint i,j; for(i=x;i>0;i--) for(j=110;j>0;j--); } void play_music() //播放音乐函数 { uchar i; for(i=0;i<32;i++) //循环32次 { beep=1; //蜂鸣器响 delay_ms(beat[i]); //延时 beep=0; //蜂鸣器停 delay_ms(5); //停顿一下 } } void main() { uchar i; while(1) { for(i=0;i<4;i++) //循环4次 { TMOD=0x01; //设置计时器0为模式1 TH0=(65536-50000)/256; //设置计时器初值 TL0=(65536-50000)%256; TR0=1; //启动计时器 while(!TF0); //等待计时器溢出 TF0=0; //清除溢出标志位 TH0=(65536-50000)/256; TL0=(65536-50000)%256; TR0=1; while(!TF0); TF0=0; } for(i=0;i<8;i++) //循环8次 { TMOD=0x01; //设置计时器0为模式1 TH0=(65536-10000)/256; //设置计时器初值 TL0=(65536-10000)%256; TR0=1; //启动计时器 while(!TF0); //等待计时器溢出 TF0=0; //清除溢出标志位 TH0=(65536-10000)/256; TL0=(65536-10000)%256; TR0=1; while(!TF0); TF0=0; } play_music(); //播放音乐 } } ``` 需要说明的是,上述代码是使用定时器产生PWM波的方式来控制蜂鸣器发声的,其中`music[]`数组存储了两只老虎和小星星的音符,`beat[]`数组存储了每个音符的节拍。在`main()`函数中,通过循环控制蜂鸣器的发声次数和停顿时间,从而实现播放两只老虎的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值