keil编程实例音乐
单片机源程序如下:
- /**********************
- 基于STC15F2K60S2系列单片机C语言编程实现
- 使用如下头文件,不用另外再包含"REG51.H"
- ***********************/
- #include <STC15F2K60S2.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit beep=P3^4; //蜂鸣器
- sbit key1=P3^2; //按键1
- sbit key2=P3^3; //按键2
- sbit key3=P1^7; //按键3
- sbit Sel0=P2^0;
- sbit Sel1=P2^1;
- sbit Sel2=P2^2;//位选的三个引脚控制位
- uchar pinlv;
- uchar pinlv_flag;//改变数码管滚动频率
- uchar show_w1;
- uchar show_w2;
- uchar show_w3;
- uchar show_w4;
- uchar show_w5;
- uchar show_w6;
- uchar show_w7;
- uchar show_w8;//show_wi,分别对应从左到右的每个数码管上的数字
- uchar duanxuan[]={0x73,0x38,0x79,0x77,0x6d,0x79,0x00,0x79,0x37,0x1e,0x3f,0x6e,0x40,0x40,0x0f,0x39,0x38,0x6e,0x00,0x00};//段选,显示PLEASE ENJOY--XLY
- uchar weixuan[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}; //位选,选择是0-7中的一个数码管
- uchar flag0,count;//数码管扫描快慢分频作用
- uchar timeh,timel,jindu=0,gequ=0; //定义定时器的重装值
- bit flag; //播放标志位
- uchar code music1[] ={ //音乐代码,歌曲为《同一首歌》,格式为: 音符, 节拍, 音符, 节拍,
- 0x15,0x20,0x21,0x10, //音符的十位代表是低八度,中八度还是高八度,1代表低八度,2代表中八度,3代表高八度
- 0x22,0x10,0x23,0x15, //个位代表简谱的音符,例如0x15代表低八度的S0,0x21代表中八度的DO。
- 0x24,0x05,0x23,0x10, //节拍则是代表音长,例如:0x10代表一拍,0x20代表两拍,0x05代表1/2拍
- 0x21,0x10,0x22,0x20,
- 0x21,0x10,0x16,0x10,
- 0x21,0x40,0x15,0x20,
- 0x21,0x10,0x22,0x10,
- 0x23,0x10,0x23,0x05,
- 0x24,0x05,0x25,0x10,
- 0x21,0x10,0x24,0x15,
- 0x23,0x05,0x25,0x10,
- 0x22,0x05,0x23,0x05,
- 0x23,0x05,0x22,0x05,
- 0x22,0x30,0x23,0x20,
- 0x25,0x10,0x31,0x10,
- 0x27,0x15,0x26,0x05,
- 0x26,0x20,0x25,0x10,
- 0x25,0x05,0x26,0x05,
- 0x27,0x10,0x26,0x05,
- 0x25,0x05,0x23,0x40,
- 0x24,0x15,0x24,0x05,
- 0x25,0x10,0x26,0x10,
- 0x25,0x10,0x24,0x05,
- 0x23,0x05,0x22,0x20,
- 0x17,0x10,0x17,0x05,
- 0x16,0x05,0x15,0x10,
- 0x16,0x10,0x21,0x40,
- 0x00,0x00
- };
- uchar code music2[] ={ //歌曲为小星星
- 0x21,0x10,0x21,0x10,
- 0x25,0x10,0x25,0x10,
- 0x26,0x10,0x26,0x10,
- 0x25,0x20,0x24,0x10,
- 0x24,0x10,0x23,0x10,
- 0x23,0x10,0x22,0x10,
- 0x22,0x10,0x21,0x20,
- 0x25,0x10,0x25,0x10,
- 0x24,0x10,0x24,0x10,
- 0x23,0x10,0x23,0x10,
- 0x22,0x20,
- 0x25,0x10,0x25,0x10,
- 0x24,0x10,0x24,0x10,
- 0x23,0x10,0x23,0x10,
- 0x22,0x20,
- 0x21,0x10,0x21,0x10,
- 0x25,0x10,0x25,0x10,
- 0x26,0x10,0x26,0x10,
- 0x25,0x20,0x24,0x10,
- 0x24,0x10,0x23,0x10,
- 0x23,0x10,0x22,0x10,
- 0x22,0x10,0x21,0x20,
- 0x00,0x00
- };
- uchar code music3[] ={ //歌曲为天空之城
- 0x16,0x05,0x17,0x05,
- 0x21,0x15,0x17,0x05,
- 0x21,0x10,0x23,0x10,
- 0x17,0x30,0x23,0x10,
- 0x16,0x15,0x15,0x05,
- 0x16,0x10,0x21,0x10,
- 0x15,0x30,0x13,0x10,
- 0x14,0x15,0x13,0x05,
- 0x14,0x05,0x21,0x05,
- 0x21,0x10,0x13,0x30,
- 0x21,0x10,0x17,0x10,
- 0x14,0x05,0x14,0x10,
- 0x17,0x10,0x17,0x20,
- 0xff,
- 0x16,0x05,0x17,0x05,
- 0x21,0x15,0x17,0x05,
- 0x21,0x10,0x23,0x10,
- 0x17,0x30,0x13,0x05,
- 0x13,0x05,0x16,0x15,
- 0x15,0x05,0x16,0x10,
- 0x21,0x10,0x15,0x30,
- 0x13,0x10,0x14,0x10,
- 0x21,0x05,0x17,0x05,
- 0x17,0x10,0x21,0x10,
- 0x22,0x10,0x23,0x05,
- 0x21,0x20,0xff,
- 0x21,0x05,0x17,0x05,
- 0x16,0x10,0x17,0x10,
- 0x15,0x10,0x16,0x20,
- 0xff,
- 0x21,0x05,0x22,0x05,
- 0x23,0x15,0x22,0x10,
- 0x23,0x10,0x24,0x10,
- 0x25,0x05,0x22,0x30,
- 0x15,0x10,0x22,0x03,
- 0x21,0x03,0x17,0x03,
- 0x21,0x03,0x21,0x10,
- 0x21,0x05,0x22,0x10,
- 0x23,0x05,0x23,0x40,
- 0x16,0x05,0x17,0x05,
- 0x21,0x10,0x17,0x05,
- 0x21,0x05,0x22,0x10,
- 0x21,0x15,0x15,0x05,
- 0x15,0x20,0x24,0x10,
- 0x23,0x10,0x22,0x10,
- 0x21,0x10,0x23,0x30,
- 0x16,0x05,0x17,0x05,
- 0x21,0x15,0x17,0x05,
- 0x21,0x10,0x23,0x10,
- 0x17,0x30,0x13,0x10,
- 0x16,0x15,0x15,0x05,
- 0x16,0x10,0x21,0x10,
- 0x15,0x30,0x13,0x10,
- 0x14,0x10,0x21,0x05,
- 0x17,0x05,0x17,0x10,
- 0x21,0x10,0x22,0x10,
- 0x23,0x05,0x21,0x05,
- 0x21,0x20,0x21,0x05,
- 0x17,0x05,0x16,0x10,
- 0x17,0x10,0x15,0x10,
- 0x16,0x40,0x00,0x00
- };
- uchar code quzi[] ={ //此数组数据为各个音符在定时器中的重装值,第一列是高位,第二列是低位 //时间
- 0xf8,0x8c, //低八度,低1
- 0xf9,0x5b,
- 0xfa,0x15, //低3
- 0xfa,0x67,
- 0xfb,0x04, //低5
- 0xfb,0x90,
- 0xfc,0x0c, //低7
- 0xfc,0x44, //中央C调
- 0xfc,0xac, //中2
- 0xfd,0x09,
- 0xfd,0x34, //中4
- 0xfd,0x82,
- 0xfd,0xc8, //中6
- 0xfe,0x06,
- 0xfe,0x22, //高八度,高1
- 0xfe,0x56,
- 0xfe,0x6e, //高3
- 0xfe,0x9a,
- 0xfe,0xc1, //高5
- 0xfe,0xe4,
- 0xff,0x03 //高7
- };
- /**********************
- 函数名称:void delay(unsigned int xms)
- 功能描述:延时
- 入口参数:xms:输入需要延时的毫秒值
- 出口参数:无
- 备注:
- ***********************/
- void delay(unsigned int xms)
- {
- uint i,j;
- for(i=xms;i>0;i--)
- for(j=124;j>0;j--);
- }
- /**********************
- 函数名称:uchar quyin(uchar tem)
- 功能描述:在quzi数组中,找到music数组定义的简谱音符的重装值,并返回其在quzi数组中的位置
- 入口参数:tem:music数组中定义的简谱音符
- 出口参数:返回的是tem音符在quzi数组中的位置值
- 备注:
- ***********************/
- uchar quyin(uchar tem)
- {
- uchar qudiao,jp,weizhi; //定义曲调,音符和位置
- qudiao=tem/16; //高4位是曲调值
- jp=tem%16; //低4位是音符
- if(qudiao==1) //当曲调值为1时,即是低八度,低八度在quzi数组中基址为0
- qudiao=0;
- else if(qudiao==2) //当曲调值为2时,即是中八度,中八度在quzi数组中基址为14
- qudiao=14;
- else if(qudiao==3) //当曲调值为3时,即是高八度,高八度在quzi数组中,基址为28
- qudiao=28;
- weizhi=qudiao+(jp-1)*2; //通过基址加上音符作为偏移量,即可定位此音符在quzi数组中的位置
- return weizhi; //返回这一个位置值
- }
- /**********************
- 函数名称:void playmusic()
- 功能描述:播放音乐
- 入口参数:无
- 出口参数:无
- 备注:
- ***********************/
- void playmusic()
- {
- uchar p,m,tem; //m为节拍
- while(1)
- {
- if(flag==1) //若播放的标志位为1则播放音乐
- {
- if(gequ==0) //歌曲选择位为0,则播放第一首歌
- {
- p=music1[jindu];
- if(p==0x00) //如果碰到结束符,延时1秒,回到开始再来一遍
- {
- jindu=0;
- delay(1000);
- break;
- }
- else if(p==0xff) //若碰到休止符,延时100ms,继续取下一音符
- {
- jindu=jindu+1;
- delay(100);
- TR0=0;
- break;
- }
- else //正常情况下取音符和节拍
- {
- tem=quyin(music1[jindu]); //取出当前音符在quzi数组中的位置值
- timeh=quzi[tem]; //把音符相应的计时器重装载值赋予timeh和timel
- timel=quzi[tem+1];
- jindu++;
- TH0=timeh; //把timeh和timel赋予计时器
- TL0=timel;
- m=music1[jindu]; //取得节拍
- jindu++;
- }
- TR0=1; //开定时器0
- delay(m*180); //等待节拍完成, 通过P3^4口输出音频
- TR0=0; //关定时器0
- beep=0; //使beep端口置0,起保护蜂鸣器作用
- }
- else if(gequ==1) //歌曲选择位为1,则播放小星星
- {
- p=music2[jindu];
- if(p==0x00) //如果碰到结束符,延时1秒,回到开始再来一遍
- {
- jindu=0;
- delay(1000);
- break;
- }
- else if(p==0xff) //若碰到休止符,延时100ms,继续取下一音符
- {
- jindu=jindu+1;
- delay(100);
- TR0=0;
- break;
- }
- else //正常情况下取音符和节拍
- {
- tem=quyin(music2[jindu]); //取出当前音符在quzi数组中的位置值
- timeh=quzi[tem]; //把音符相应的计时器重装载值赋予timeh和timel
- timel=quzi[tem+1];
- jindu++;
- TH0=timeh; //把timeh和timel赋予计时器
- TL0=timel;
- m=music2[jindu]; //取得节拍
- jindu++;
- }
- TR0=1; //开定时器1
- delay(m*300); //等待节拍完成, 通过P3^4口输出音频
- TR0=0; //关定时器1
- beep=0; //使beep端口置0,起保护蜂鸣器作用
- }
- else if(gequ==2) //歌曲选择位为2,则播放天空之城
- {
- p=music3[jindu];
- if(p==0x00) //如果碰到结束符,延时1秒,回到开始再来一遍
- {
- jindu=0;
- delay(1000);
- break;
- }
- else if(p==0xff) //若碰到休止符,延时100ms,继续取下一音符
- {
- jindu=jindu+1;
- delay(100);
- TR0=0;
- break;
- }
- else //正常情况下取音符和节拍
- {
- tem=quyin(music3[jindu]); //取出当前音符在quzi数组中的位置值
- timeh=quzi[tem]; //把音符相应的计时器重装载值赋予timeh和timel
- timel=quzi[tem+1];
- jindu++;
- TH0=timeh; //把timeh和timel赋予计时器
- TL0=timel;
- m=music3[jindu]; //取得节拍
- jindu++;
- }
- TR0=1; //开定时器1
- delay(m*200); //等待节拍完成, 通过P3^4口输出音频
- TR0=0; //关定时器1
- beep=0; //使beep端口置0,起保护蜂鸣器作用
- }
- }
- else //播放标志位不为1时,暂停播放音乐
- while(flag!=1);
- }
- }
- /**********************
- 函数名称:void init_sys()
- 功能描述:系统初始化,功能是配置IO口
- 入口参数:无
- 出口参数:无
- 备注:
- ***********************/
- void init_sys()
- {
- P0M0=0xff; //设置推挽模式
- P0M1=0x00;
- P2M0=0x08;
- P2M1=0x00;
- P3M0=0x10;
- P3M1=0x00;
- P4M0=0x00;
- P4M1=0x00;
- P5M0=0x00;
- P5M1=0x00;
- }
- /**********************
- 函数名称:void init()
- 功能描述:定时器和外部中断的初始化
- 入口参数:无
- 出口参数:无
- 备注:
- ***********************/
- void init()
- {
- TMOD=0x01; //设置定时器0,定时方式1,16位手动重装模式(TH0和TL0全用)
- TH0=0xD8; //设置定时初值
- TL0=0xEF;
- IE=0x8f; // 1000 1111 EA=1(打开总的终中断),ET1=1(定时器1中断使能),EX0=1(外部中断0使能),ET0=1(定时器0中断使能),EX1=0(外部中断1使能);
- IP=0x02; // 0000 0010 PT0=1; 定时器0优先级高
- TR0=0; //定时器0停止工作,初始化
- beep=0; //使beep端口置0,起保护蜂鸣器作用
-
- flag0=0;
- count=0;
-
- show_w1=0;
- show_w2=1;
- show_w3=2;
- show_w4=3;
- show_w5=4;
- show_w6=5;
- show_w7=6;
- show_w8=7;//赋初值,为接下来取模做准备
- }
- void main()
- {
- init_sys(); //系统初始化
- init();
- P0=0x00; //P0口初始化
- key1=1; //三个按键设为输入状态,检测中断
- key2=1;
- key3=1;
- flag=0; //播放标志位清零
-
- TMOD=0x90;//定时器1,方式1
- ET1=1;//开启定时器1中断
- pinlv_flag=0;
- pinlv=100;
- TH1=(65535-1000)/256;//定时器1的高八位设置
- TL1=(65535-1000)%256;//定时器1的低八位设置,这里总体就是设置定时器0的初始值是1ms
- TR1=1;//启动定时器1
- EA=1;//打开总的中断
-
- while(1)
- {
- playmusic(); //播放音乐函数
- }
- }
- /**********************
- 函数名称:void tim1() interrupt 1
- 功能描述:定时器0中断处理,重新装值,并把beep值取反,产生方波
- 入口参数:无
- 出口参数:无
- 备注:
- ***********************/
- void tim1() interrupt 1 //计时器控制频率
- {
- TH0=timeh; //赋初值
- TL0=timel;
- beep=~beep; //中断使得beep翻转产生方波
- }
- /**********************
- 函数名称:void ex1() interrupt 0
- 功能描述:按下按键1的外部中断,对标志位取反,功能是暂停和播放音乐
- 入口参数:无
- 出口参数:无
- 备注:
- ***********************/
- void ex1() interrupt 0
- {
- delay(5);
- if(key1==0) //判断key1是否按下
- {
- delay(5); //按键消抖
- if(key1==0)
- {
- while(!key1);
- flag=~flag; //播放中断位取反,播放或者暂停
- }
- }
- }
- /**********************
- 函数名称:void ex2() interrupt 2
- 功能描述:按下按键2的外部中断,作用为切换歌曲
- 入口参数:无
- 出口参数:无
- 备注:
- ***********************/
- void ex2() interrupt 2
- {
- delay(5);
- if(key2==0) //按键key2按下,切换歌曲
- {
- jindu=0; //歌曲的进度清零,从头开始演唱
- gequ++; //下一曲
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
final_4.rar
(46.47 KB, 下载次数: 97)
|