程序设计目标及程序运行效果说明
程序设计目标:通过按下按键key1来控制音乐播放以及数码管的歌词显示。
程序运行效果说明:按下按键key1,此时播放音乐《I can say ABC》并显示歌词;再次按下key1键可以暂停播放音乐。

程序相关电路及原理说明
1.原理说明
本实验板采用的是无源蜂鸣器,相比与有源蜂鸣器,无源蜂鸣器的优点在于价格便宜,可以通过控制其振动频率来改变发出的声音,因此,无源蜂鸣器可以用于音乐的播放。而有源蜂鸣器的优点在于使用简单,不需要编写“乐谱”。本实验板使用的无源蜂鸣器是电磁式蜂鸣器,电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。接通电源后,接收到的音频信号电流通过电磁线圈,使电磁线圈产生磁场。振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。

本程序中,数组music[]即是要播放的音乐,格式为音符,节拍,音符,节拍,如此循环下去。音符为要发出的音调,而节拍则是声音的持续时间。如图,在数组music[]中,音符表示的格式为:十位代表是低八度,中八度还是高八度,1代表高八度,2代表中八度,3代表高八度,个位代表简谱的音符,例如,0x15代表低八度的S0,如图即是低5S0,0x21代表中八度的DO,如图即是中1 D0。音符中,0x00代表结束符,表示整首歌曲演唱完毕,而0xff代表休止符,表示要休止100ms。遇到这两种情况,都应该重新执行循环中的第一步。其余情况则是正常播放。程序烧入单片机后,需要按下按键key1才会进行演奏。相比基础篇则添加了歌词数码管同步显示功能。

注:因使用数码管显示歌词着实有些勉强,有些字母很难在数码管上面显示,如“M”等,这个实验主要的学习重点在于歌词的同步显示和歌曲的数字编排(即由简谱变成音乐代码)。 ABC英文歌字母数码管显示对应符号表(A-Z)已另外做成文档,请见文档“ABC英文歌字母数码管显示对应符号表(A-Z)”。

2.程序相关电路
(1)无源蜂鸣器电路原理图

(2)按键控制电路

芯片相关引脚:Beep——P3^4;

代码如下:

#include "STC15F2K60S2.H"
#define uint unsigned int                 //宏定义
#define uchar unsigned char
sbit led_sel=P2^3;                      //数码管与发光二极管选通引脚
sbit sel0=P2^0;                             //SEL0、SEL1、SEL2组合为位选信息,0-7
sbit sel1=P2^1;
sbit sel2=P2^2;
sbit beep=P3^4;                             //蜂鸣器引脚
sbit key1=P3^2;                             //定义按键1
sbit key2=P3^3;                             //定义按键2
uchar timeh,timel;        //定义定时器的重装值
uchar flag;               //所选择点亮的数码管0-7标志位
bit zanting;              //播放或暂停标志位
uchar jindu=0;           //music数组中指向的位置
uchar geci[]={0x77,0x7f,0x39,0x00,0x6f,0x7b};                   //显示开机画面的数码管段码 ABC ge
uchar geci1[]={0x77,0x7f,0x39,0x3f,0x79,0x71,0x3d,0x40};        //显示A-G的数码管段码 ABCDEFG-
uchar geci2[]={0x76,0x06,0x1e,0xf6,0x38,0x4f,0x37,0x40};       //显示H-N的数码管段码  HIJKLMN-
uchar geci3[]={0x3f,0x73,0xbf,0x40,0xf7,0x6d,0x07,0x40};       //显示O-T的数码管段码  OPQ-RST-
uchar geci4[]={0x62,0x3e,0xf9,0x40,0xf6,0xe6,0xdb,0x40};       //显示U-Z的数码管段码  UVW-XYZ-
uchar geci5[]={0xf6,0xe6,0xdb,0x80,0x37,0x3f,0xf9,0x00};        //XYZ,Now
uchar geci51[]={0xe6,0x3f,0x62,0x00,0x6d,0x79,0x79,0x00};      //you see
uchar geci6[]={0x0f,0x39,0x77,0x37,0x00,0x6d,0x77,0xe6};        //I can say
uchar geci61[]={0x77,0x7f,0x39,0x00,0x00,0x00,0x00,0x00};       // ABC
uchar weixuan[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};     //位选码
uchar code music[] ={    //音乐代码,歌曲为《I can say ABC》,格式为: 音符, 节拍, 音符, 节拍,
0x11,0x10,0x21,0x10,     //音符的十位代表是低八度,中八度还是高八度,1代表低八度,2代表中八度,3代表高八度
0x25,0x10,0x25,0x10,     //个位代表简谱的音符,例如0x15代表低八度的S0,0x21代表中八度的DO。
0x26,0x10,0x26,0x10,     //节拍则是代表音长,例如:0x10代表一拍,0x20代表两拍,0x05代表1/2拍
0x25,0x10,0x25,0x10,  //16
0x24,0x10,0x14,0x10,
0x23,0x10,0x13,0x10,
0x22,0x10,0x22,0x10,
0x21,0x10,0x21,0x10,  //32
0x25,0x10,0x25,0x10,
0x24,0x10,0x24,0x20,
0x23,0x10,0x23,0x10,
0x22,0x10,0x22,0x10,  //48
0x25,0x10,0x25,0x10,
0x24,0x10,0x24,0x20,
0x23,0x10,0x23,0x10,
0x22,0x10,0x22,0x10,  //64
0x21,0x10,0x21,0x10,
0x25,0x10,0x25,0x10,  //72
0x26,0x10,0x26,0x10,
0x25,0x10,0x25,0x10,  //80
0x24,0x10,0x24,0x10,
0x23,0x10,0x23,0x10,  //88
0x22,0x10,0x22,0x10,
0x21,0x10,0x21,0x20,  //96
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)
{uint i,j;                         for(i=xms;i>0;i--)for(j=124;j>0;j--);
}
//功能描述:在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数组中基址为0qudiao=0;else if(qudiao==2)             //当曲调值为2时,即是中八度,中八度在quzi数组中基址为14qudiao=14;else if(qudiao==3)           //当曲调值为3时,即是高八度,高八度在quzi数组中,基址为28qudiao=28;weizhi=qudiao+(jp-1)*2;          //通过基址加上音符作为偏移量,即可定位此音符在quzi数组中的位置return weizhi;                 //返回这一个位置值
}
void playmusic()//播放音乐
{uchar p,m,tem;   //m为节拍   while(1)   {   if(zanting==1)          //播放或暂停控制{p=music[jindu];if(p==0x00)         //如果碰到结束符,延时1秒,回到开始再来一遍 {jindu=0;delay(1000);break;}        else if(p==0xff)   //若碰到休止符,延时100ms,继续取下一音符{jindu++;           delay(100);TR0=0;          //关定时器0break;}      else               //正常情况下取音符和节拍 {tem=quyin(music[jindu]);     //取出当前音符在quzi数组中的位置值timeh=quzi[tem];           //把音符相应的计时器重装载值赋予timeh和timeltimel=quzi[tem+1];jindu++;TH0=timeh;                   //把timeh和timel赋予计时器TL0=timel;m=music[jindu];                   //取得节拍jindu++;}             TR0=1;                    //开定时器0    delay(m*180);             //等待节拍完成, 通过P3^4口输出音频    TR0=0;                    //关定时器0   beep=0;                        //将beep置0,以保护蜂鸣器        }}
}
//系统初始化,功能是配置IO口
void init_sys()
{P0M0=0xff;                    //设置推挽模式P0M1=0x00;P2M0=0x08;P2M1=0x00;P3M0=0x10;P3M1=0x00;
}
//定时器初始化
void init()
{TMOD=0x01;                     //设置定时器0,工作方式1,16位手动重装初值;设置定时器1,工作方式0,16位自动重装初值TH0=0xD8;                    //设置定时器0初值TL0=0xEF;TH1=(65536-1000)/256;      //设置定时器1初值TL1=(65536-1000)%256;EA=1;                      //打开总中断ET0=1;                      //打开定时器0中断ET1=1;                       //打开定时器1中断TR0=0;                       //定时器0暂时不启动TR1=1;                      //启动定时器1   EX0=1;                      //启动外部中断0                       zanting=0;                     //播放或暂停标志位赋初值beep=0;                       //将beep置0,以保护蜂鸣器
}
void main()
{init_sys();                              //系统初始化init();P0=0x00;                             key1=1;flag=0;while(1)playmusic();           //进入播放音乐函数
}
//定时器0中断处理,重新装值,并把beep值取反,产生方波
void tim1()interrupt 1                      //计时器控制频率
{TH0=timeh;                                //中断后重赋初值TL0=timel;beep=~beep;                            //中断beep翻转产生方波,使得蜂鸣器发声
}
//按下按键1的外部中断,对标志位取反,功能是暂停和播放音乐
void exint0()interrupt 0
{if(key1==0){     delay(10);if(key1==0)zanting=~zanting;}
}
//定时器1中断处理,用作数码管显示歌词。
void timer1()interrupt 3                   //把显示程序提到定时器1中断服务程序
{flag++;if(flag==8)flag=0;P0=0;P2=weixuan[flag];if(jindu==0)                        //通过判断播放时的jindu进而控制此时的歌词显示{                                     //此时为零时,显示“ABC ge”switch(flag){case 0:P0=geci[0];break;case 1:P0=geci[1];break;case 2:P0=geci[2];break;case 4:P0=geci[4];break;case 5:P0=geci[5];break;default:P0=geci[3];break;}}else if(jindu<16){                    //此时进度为0-15之间,显示“ABCDEFG-”switch(flag){case 0:P0=geci1[0];break;case 1:P0=geci1[1];break;case 2:P0=geci1[2];break;case 3:P0=geci1[3];break;case 4:P0=geci1[4];break;case 5:P0=geci1[5];break;case 6:P0=geci1[6];break;default:P0=geci1[7];break;}}else if(jindu<32){                   //此时进度为16-31之间,显示“HIJKLMN-”switch(flag){case 0:P0=geci2[0];break; case 1:P0=geci2[1];break; case 2:P0=geci2[2];break; case 3:P0=geci2[3];break; case 4:P0=geci2[4];break; case 5:P0=geci2[5];break; case 6:P0=geci2[6];break; default:P0=geci2[7];break; }}else if(jindu<48){                     //此时进度为32-47之间,显示“OPQ- RST-”switch(flag){case 0:P0=geci3[0];break; case 1:P0=geci3[1];break; case 2:P0=geci3[2];break;case 3:P0=geci3[3];break;case 4:P0=geci3[4];break;case 5:P0=geci3[5];break;case 6:P0=geci3[6];break;default:P0=geci3[7];break;}}else if(jindu<64){                      //此时进度为48-63之间,显示“UVW- XYZ-”switch(flag){case 0:P0=geci4[0];break; case 1:P0=geci4[1];break; case 2:P0=geci4[2];break; case 3:P0=geci4[3];break; case 4:P0=geci4[4];break; case 5:P0=geci4[5];break; case 6:P0=geci4[6];break; default:P0=geci4[7];break; }}else if(jindu<72){                   //此时进度为64-71之间,显示“XYZ- NOW”switch(flag){case 0:P0=geci5[0];break;case 1:P0=geci5[1];break;case 2:P0=geci5[2];break;case 3:P0=geci5[3];break;case 4:P0=geci5[4];break;case 5:P0=geci5[5];break;case 6:P0=geci5[6];break;default:P0=geci5[7];break;}}else if(jindu<80){                    //此时进度为72-79之间,显示“YOU SEE ”switch(flag){case 0:P0=geci51[0];break; case 1:P0=geci51[1];break; case 2:P0=geci51[2];break; case 3:P0=geci51[3];break; case 4:P0=geci51[4];break; case 5:P0=geci51[5];break; case 6:P0=geci51[6];break; default:P0=geci51[7];break; }}else if(jindu<88){                 //此时进度为80-87之间,显示“ICAN SAY”switch(flag){case 0:P0=geci6[0];break;case 1:P0=geci6[1];break;case 2:P0=geci6[2];break;case 3:P0=geci6[3];break;case 4:P0=geci6[4];break;case 5:P0=geci6[5];break;case 6:P0=geci6[6];break;default:P0=geci6[7];break;}}else if(jindu<96){                 //此时进度为88-95之间,显示“ABC”switch(flag){case 0:P0=geci61[0];break; case 1:P0=geci61[1];break; case 2:P0=geci61[2];break; case 3:P0=geci61[3];break; case 4:P0=geci61[4];break; case 5:P0=geci61[5];break; case 6:P0=geci61[6];break; default:P0=geci61[7];break; }}
}

STC学习:可同步显示歌词的ABC英文歌相关推荐

  1. android 歌词同步 换行,HTML5音乐播放器同步显示歌词

    歌词文件的格式 实现之前,当然得了解一下歌词文件的格式了.常规歌词文件的格式基本是一句一行,每行由两部分组成,前面是中括号括起来的时间轴,后面紧跟歌词,像下面这样:[ti:记兰生襄铃] [ar:HIT ...

  2. 让Windows Media Player和MP3播放器一样可以显示歌词

    为了让女儿能通过唱英文歌曲来达到提高语感的目的, 咱下载了一些儿童MP3歌曲, 但是通过Media Player播放时, 却没法与MP3播放器一样可以显示歌词, 找了半下, 终于从网上找到一文章介绍如 ...

  3. 网页中LRC歌词同步显示

    <html><head> <title>音乐歌词同步测试</title> <style> <!-- .div { width:460p ...

  4. Jplayer歌词同步显示插件

    http://blog.csdn.net/wk313753744/article/details/38758317 1.该插件是一个jquery的编写的跟jplayer实现歌词同步的插件,最终效果如图 ...

  5. Jplayer歌词同步显示插件(在以前别人基础上修改)

    1.该插件是一个jquery的编写的跟jplayer实现歌词同步的插件,最终效果如图: 2.首先引入jplayer的相关的js库和样式文件. <meta http-equiv="Con ...

  6. Android 实现歌曲播放时歌词同步显示

    我们需要读取以上歌词文件的每一行转换成成一个个歌词实体: public class LyricObject { public int begintime; // 开始时间 public int end ...

  7. android 歌词解析 依赖,Android实现歌曲播放时歌词同步显示具体思路

    我们需要读取以上歌词文件的每一行转换成成一个个歌词实体: 代码如下: public class LyricObject { public int begintime; // 开始时间 public i ...

  8. ffplay.c学习-6-⾳视频同步基础

    ffplay.c学习-6-⾳视频同步基础 目录 ⾳视频同步策略 ⾳视频同步概念 FFmpeg中的时间单位 ⾳视频时间换算的问题 不同结构体的time_base/duration分析 不同结构体的PTS ...

  9. iPhone上的lrc播放器可以在播放mp3文件时显示歌词

    https://apps.apple.com/cn/app/%E6%96%B0lrc%E6%92%AD%E6%94%BE%E5%99%A82/id1535214306 长久以来,在iPhone上播放l ...

  10. python播放音乐同步歌词范晓萱_范晓萱同步的歌词

    你是不是在找范玮琪的这首同步的歌词?下面是学习啦!小编帮你整理了这首歌词的相关的资料希望对你有用! 同步的歌词 同步-(电影<陪安东尼度过漫长岁月>主题曲)-范晓萱 相隔两地的时空 默契对 ...

最新文章

  1. java 多线程下载器_Java多线程的下载器(1)
  2. 如何遍历维数和各维上限未定的多维数组
  3. PaperWeekly 第28期 | 图像语义分割之特征整合和结构预测
  4. Oracle数据库中表格的级联删除问题
  5. undefined reference to `clock_gettime'
  6. Node.js怎么处理数据库中日期类型
  7. 在线HTML5,CSS3,VueJS,jQuery运行测试练习工具
  8. 关于逻辑或的一个小小应用注意点
  9. 9.运输层(3)---TCP
  10. c语言冒泡排序法程序填空_五种数组的排序方法(C语言)Part1
  11. java.lang.UnsupportedOperationException WebView is not allowed in privileged processes
  12. docker 删除镜像
  13. BAT大厂面试精选的62道高频面试题【笔试+算法+代码+逻辑题等】
  14. 谈谈PRNU 光响应非均匀性
  15. 瑞星客户端卸载操作手册
  16. chrome更新后,再次使用selenium打开chrome却发现闪退了?全网最详细教程,肯定能帮到你!
  17. sql_update
  18. Python自动化运维 - day9 - 进程与线程
  19. 《宣州谢眺楼饯别校书叔云》 李白诗两首
  20. live555直播startplaying

热门文章

  1. Nagios中NSClient++监控Windows主机
  2. Bash之正则表达式
  3. 2月中国万网域名总量净增2.1万个 份额突破24%
  4. 浅谈管道模型(Pipeline)
  5. 华为主题锁屏壁纸换不掉_华为手机中的这些默认设置一定要改,不然会导致手机卡顿加快耗电...
  6. SpringBoot Security 整合 thymeleaf 模板自定义登录页面,按需提示错误信息
  7. ARM开发6.3.1 基础实训( 1 ) 单个数码 LED 的显示输出系统设计( 1)--LPC21XX
  8. 程序转换实验程序流程图_智能化实验室 | # 自动智能化实验室的5大系统 #
  9. mac 搭建mysql环境_Mac下MySQL环境搭建的步骤详解
  10. abb外部轴零位校准_【ABB】ABB机器人外部轴参数(KpKvTi)调试