按键控制蜂鸣器演奏音乐
下载:
单片机演奏音乐.rar
(44.26 KB, 下载次数: 94)
- #include<reg52.h>
- sbit spek=P3^7; //声音输出端
- sbit set=P3^2; //设定及退出键,按奇数次为设定功能;偶数次为退出功能
- sbit up=P3^1; //上一曲
- sbit down=P3^0; //下一曲
- bit flag1,flag2; //按键扫描标志位,新键值标志位
- unsigned char f_t,n,i,key,k_max; //音符频率对应的二分之一周期值,节拍常数值,查表用计数器,键值,最大键值
- unsigned char *p_music; //指向音乐数据数组的指针
- void timer_ms(unsigned char tim); //毫秒级延时函数声明
- void timer_us(unsigned char t); //微秒级延时函数
- void key_scan(void); //按键扫描函数
- void key_manage(); //键值处理函数
- //格式为:频率常数,节拍常数,频率常数,节拍常数
- unsigned char code music_table1[]={
- 0x18,0x30,0x1c,0x10,0x20,0x40,0x1c,0x10,0x18,
- 0x10,0x20,0x10,0x1c,0x10,0x18,0x40,0x1c,0x20,
- 0x20,0x20,0x1c,0x20,0x18,0x20,0x20,0x80,0xff,
- 0x20,0x30,0x1c,0x10,0x18,0x20,0x15,0x20,0x1c,
- 0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2b,0x20,
- 0x26,0x20,0x20,0x20,0x30,0x80,0xff,0x20,0x20,
- 0x1c,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2b,
- 0x20,0x30,0x20,0x2b,0x40,0x20,0x20,0x1c,0x10,
- 0x18,0x10,0x20,0x20,0x26,0x20,0x2b,0x20,0x30,
- 0x20,0x2b,0x40,0x20,0x30,0x1c,0x10,0x18,0x20,
- 0x15,0x20,0x1c,0x20,0x20,0x20,0x26,0x40,0x20,
- 0x20,0x2b,0x20,0x26,0x20,0x20,0x20,0x30,0x80,
- 0x20,0x30,0x1c,0x10,0x20,0x10,0x1c,0x10,0x20,
- 0x20,0x26,0x20,0x2b,0x20,0x30,0x20,0x2b,0x40,
- 0x20,0x15,0x1f,0x05,0x20,0x10,0x1c,0x10,0x20,
- 0x20,0x26,0x20,0x2b,0x20,0x30,0x20,0x2b,0x40,
- 0x20,0x30,0x1c,0x10,0x18,0x20,0x15,0x20,0x1c,
- 0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2b,0x20,
- 0x26,0x20,0x20,0x20,0x30,0x30,0x20,0x30,0x1c,
- 0x10,0x18,0x40,0x1c,0x20,0x20,0x20,0x26,0x40,
- 0x13,0x60,0x18,0x20,0x15,0x40,0x13,0x40,0x18,
- 0x80,0x00}; //八月桂花香
- unsigned char code music_table2[]={
- 0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,
- 0x10,0x20,0x80,0x26,0x20,0x30,0x20,0x30,0x20,
- 0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x20,0x20,
- 0x20,0x20,0x20,0x1c,0x20,0x20,0x80,0x2b,0x20,
- 0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,
- 0x80,0x26,0x20,0x30,0x20,0x30,0x20,0x39,0x10,
- 0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,
- 0x20,0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,
- 0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10,0x2b,
- 0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,
- 0x2b,0x20,0x2b,0x40,0x40,0x20,0x20,0x10,0x20,
- 0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,
- 0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x40,0x26,
- 0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,
- 0x20,0x20,0x20,0x80,0x1c,0x20,0x1c,0x20,0x1c,
- 0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10,
- 0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,
- 0x10,0x26,0x10,0x2b,0x10,0x2b,0x80,0x18,0x20,
- 0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x60,0x26,
- 0x10,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,
- 0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,
- 0x10,0x30,0x20,0x39,0x20,0x26,0x10,0x2b,0x10,
- 0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,
- 0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,
- 0x00}; //祝你平安
- unsigned char code music_table3[]={
- 0x20,40,0x26,20,0x20,20,0x17,80,0x1c,40,0x17,40,
- 0x20,80,0x20, 40,0x2f,20,0x2a,20,0x26,40,0x2a,20,
- 0x2f,20,0x2a,80,0xff,0x20,40,0x26,20,0x20,20,0x17,60,
- 0x19,20, 0x1c,40,0x17,40,0x20,80,0x20,40,0x2a,20,
- 0x26,20,0x24,60,0x32,20,0x2f,80,0xff,0x1c,40,0x17,40,
- 0x17, 80,0x19,40,0x1c,20,0x19,20,0x17,80,0x1c,20,
- 0x19,20,0x17,20,0x1c,20,0x1c,20,0x20,20,0x26,20,0x2f,20,
- 0x2a,80,0xff,0x20,40,0x26,20,0x20,20,0x17,60,0x19,20,
- 0x1c,40,0x17,40,0x20,80,0x20,40,0x2a,20,0x26, 20,
- 0x24,60,0x32,20,0x2f,80,0xff,0x20,40,0x26,20,0x20,20,
- 0x17,80,0x1c,40,0x17,40,0x20,80,0x20,40, 0x2f,20,0x2a,20,
- 0x26,40,0x2a,20,0x2f,20,0x2a,80,0xff,0x20,40,0x26,20,
- 0x20,20,0x17,60,0x19,20,0x1c, 40,0x17,40,0x20,80,0x20,40,
- 0x2a,20,0x26,20,0x24,60,0x32,20,0x2f,80,0}; //送别
- main()
- {
- spek=0;
- P3=0x7f;
- TMOD=0x01; //T0工作于方式1,即16位定时器模式
- IE=0x82; //开总中断,T0中断
- flag2=0; //
- flag1=0;
- key=1;
- k_max=3; //最大键值(取值范围1~254)
- n=0;
- i=0;
- p_music=music_table1; //指针赋初值
- while (1)
- {
- switch (p_music[i])
- {
- case 0x00: i=0; //歌曲完,则停止0.5S后重新开始
- timer_ms(250); //延时0.25ms
- timer_ms(250);
- break;
- case 0xff: i++; //遇到休止符则停止100us
- timer_ms(250);
- timer_ms(250);
- break;
- default: f_t=p_music[i++];
- n=p_music[i++];
- spek=1;
- TR0=1;
- while (n!=0)
- {
- spek=~spek;
- timer_us(4*f_t); //改变f_t前面的系数可以调整音符频率的高低
- }
- TR0=0;
- spek=0;
- if(set==0)
- {
- key_scan();
- key_manage();
- }
- }
- }
- }
- /**************************************************************
- 函数名称: 定时器0的中断处理程序 函数功能: 完成10毫秒定时 入口参数:
- 出口参数: 其 它: **************************************************************/
- void timer0() interrupt 1 using 2
- {
- TH0=(65536-10000)/256; //定时10毫秒
- TL0=(65536-10000)%256;
- n--; }
- /**************************************************************
- 函数名称: 延时程序 函数功能: 完成微秒级的延时 入口参数:
- t为需延时的时间(取值范围1~255;延时时间5~1275us) 出口参数:
- 其 它: **************************************************************/
- void timer_us(unsigned char t)
- {
- while (--t); //本语句执行一次需5us的时间
- }
- /**************************************************************
- 函数名称: 按键扫描函数 函数功能: 完成按键扫描处理 入口参数:
- 应为在中断函数中被调用,所以不能有参数传递 出口参数: 其 它:
- **************************************************************/
- void key_scan(void)
- {
- timer_ms(10); //延时10ms等待按键状态稳定
- if (set==0) //再次确认
- {
- while (set==0); //等待按键松开
- flag1=1; //该位为1,表示进入按键扫描处理;为0,表示本次按键扫描处理完成
- while (flag1)
- {
- if (up==0) //加一键
- {
- timer_ms(10);
- if (up==0)
- {
- while (!up);
- key++;
- if (key>k_max) key=1;
- }
- }
- if (down==0) //减一键
- {
- timer_ms(10);
- if (down==0)
- {
- while (!down);
- key--;
- if (key<1) key=k_max;
- }
- }
- if (set==0) //退出键
- {
- timer_ms(10);
- if (set==0)
- {
- while (set==0);
- flag1=0; //表示本次按键扫描处理完成
- flag2=1; //该位置1,表示有新键值要处理
- }
- }//以上键值处理的范围为1到254个键值
- }
- }
- }
- /**************************************************************
- 函数名称: 键值处理函数 函数功能: 完成按键键值的处理
- 入口参数: 应为在中断函数中被调用,所以不能有参数传递
- 出口参数: 其 它:
- **************************************************************/
- void key_manage()
- {
- flag2=0;
- switch (key)
- {
- case 1: p_music=music_table1; //键值为1 播放第一首乐曲
- goto kh1;
- case 2: p_music=&music_table2[0]; //键值为2 播放第2首乐曲
- goto kh1;
- case 3: p_music=&music_table3[0]; //键值为3 播放第3首乐曲
- goto kh1;
- default: key=1;
- p_music=music_table1;
- kh1: TH0=(65536-10000)/256;
- TL0=(65536-10000)%256;
- break;
- }
- n=0;
- i=0;
- }
- /*----------------------------------------------------------------------------------------------------
- 函数名称: timer_ms 函数说明: 1ms延时子程序 入口参数: tim为接收主调传来需延时的毫秒数,取值范围1~256,定时时间1~256ms
- 出口参数: 其 它: ----------------------------------------------------------------------------------------------------*/
- void timer_ms(unsigned char tim)
- {
- unsigned char j;
- while(tim--)
- {
- for(j=0;j<200;j++); //延时1ms
- }
- }
复制代码
|