/*************************************************************

音乐播放器:

按键 0 - 9 对应最多10首乐曲,当一首乐曲播放完毕后,

响应按键的动作去播放相应的音乐,另外,右、下这两个按键

对应着下一首,左上这两个按键对应着上一首。

作者:宁静致远

*************************************************************/

#include

#include

#define RldTmr(fr) 65536 - (11059200 / 12) / ((fr) <

#define FuDian(n) ((n) <

typedef unsigned char uchar;

typedef unsigned int uint;

typedef unsigned long ulong;

typedef struct music {

char * pNote;

char * pDur;

} Music;

sbit BUZZ = P1^6;

sbit KEY_OUT_3 = P2^0;

sbit KEY_OUT_2 = P2^1;

sbit KEY_OUT_1 = P2^2;

sbit KEY_OUT_0 = P2^3;

sbit KEY_IN_0 = P2^4;

sbit KEY_IN_1 = P2^5;

sbit KEY_IN_2 = P2^6;

sbit KEY_IN_3 = P2^7;

uint code noteFreq[] = {    //中音 1-7 和高音 1-7对应的频率列表 低音

523, 587, 659, 698, 784, 880, 988,

1047, 1175, 1319, 1397, 1568, 1760, 1976,

//261, 293, 329, 349, 392, 440, 494

};

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

RldTmr(523), RldTmr(587), RldTmr(659), RldTmr(698), RldTmr(784), RldTmr(880), RldTmr(988),

RldTmr(1047), RldTmr(1175), RldTmr(1319), RldTmr(1397), RldTmr(1568), RldTmr(1760), RldTmr(1976),

//RldTmr(261), RldTmr(293), RldTmr(329), RldTmr(349), RldTmr(392), RldTmr(440), RldTmr(494)

};

uchar code keyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表

{0x31, 0x32, 0x33, 0x26}, //数字键1、数字键2、数字键3、向上键

{0x34, 0x35, 0x36, 0x25}, //数字键4、数字键5、数字键6、向左键

{0x37, 0x38, 0x39, 0x28}, //数字键7、数字键8、数字键9、向下键

{0x30, 0x1B, 0x0D, 0x27}  //数字键0、ESC键、  回车键、 向右键

};

uchar keyState[4][4] = {  //全部矩阵按键的当前状态

{1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}

};

bit enable = 1, tmrFlg = 0;

uchar T0RH = 0XFF, T0RL = 0X00;

uchar T1RH, T1RL;

uchar musicIdx = 0;

uchar musicSpeed = 72;

uchar nowMusic = 0;

//bit enKey = 1;

uchar code twoTigerNote[] = {      //音名

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,

'\0'

};

uchar code twoTigerDuration[] = {       //音名对应的时值,4表示4分音符,8表示8分音符,16表示16分音符

4, 4, 4, 4,

4, 4, 4, 4,

4, 4, 2,

4, 4, 2,

FuDian(8), 16, FuDian(8), 16, 4, 4,

FuDian(8), 16, FuDian(8), 16, 4, 4,

4, 4, 2,

4, 4, 2,

'\0'

};

uchar code baheNote[] = {

5, 1, 2, 3, 4,

5, 1, 1,

6, 4, 5, 6, 7,

8, 1, 1,

4, 5, 4, 3, 2,

3, 4, 3, 2, 1,

7, 1, 2, 3, 1,

3, 2,

5, 1, 2, 3, 4,

5, 1, 1,

6, 4, 5, 6, 7,

8, 1, 1,

4, 5, 4, 3, 2,

3, 4, 3, 2, 1,

2, 3, 2, 1, 7,

1,

'\0'

};

uchar code baheDur[] = {

4, 8, 8, 8, 8,

4, 4, 4,

4, 8 ,8 ,8, 8,

4, 4, 4,

4, 8, 8, 8, 8,

4, 8, 8, 8, 8,

4, 8, 8, 8, 8,

4, 2,

4, 8, 8, 8, 8,

4, 4, 4,

4, 8 ,8 ,8, 8,

4, 4, 4,

4, 8, 8, 8, 8,

4, 8, 8, 8, 8,

4, 8, 8, 8, 8,

4,

'\0'

};

uchar musicLen[10];

Music musicSet[] = {

{twoTigerNote, twoTigerDuration},

{baheNote, baheDur},

};

uchar musicNum = sizeof(musicSet) / sizeof(Music);

void delay(uint n);

void playMusic(uchar musicIdx, uchar speed);    //固定标准为4分音符的速度:例如speed = 108 表示一分钟扫过108个4分音符

void setTmr1(uint ms);

void keyScan();

void keyAction();

void keyDriver();

void initMusicInfo();

void main() {

initMusicInfo();

EA = 1;

TMOD = 0x01;

TH0 = T0RH;

TL0 = T0RL;

ET0 = 1;

PT0 = 1;  //重要!!!设置T0抢占优先级

//TR0 = 1;

setTmr1(10);

TH1 = T1RH;

TL1 = T1RL;

ET1 = 1;

TR0 = 1;

TR1 = 1;

while (1) {

//TR0 = 1;

playMusic(musicIdx, musicSpeed);

delay(40000u);

}

}

void initMusicInfo() {

uchar i;

for (i = 0; i

musicLen[i] = strlen(musicSet[i].pNote);

}

}

void delay(uint n) {

//uint i;

//TR1 = 1;

while (n--) {

keyDriver();

}

//TR1 = 0;

}

void playMusic(uchar musicIdx, uchar speed) {

uchar i;

uchar idx;

uint cnt = 0;

uint durationCnt = 0;   //当前音符的时值对应的定时器计数

uint soundCnt = 0;      //当前音符的发声时值对应的计数值

char * musicNote = musicSet[musicIdx].pNote;

char * noteDuration = musicSet[musicIdx].pDur;

for (i = 0; i

while (!tmrFlg) ;

tmrFlg = 0;

//keyDriver(); //递归实现音乐的嵌套

if (cnt == 0) {

idx = musicNote[i] - 1;

T0RH = tmrRld[idx] >> 8;

T0RL = tmrRld[idx];

durationCnt = (ulong)240 * (ulong)noteFreq[idx] / ((ulong)noteDuration[i] * (ulong)speed);

soundCnt = durationCnt - (durationCnt >> 2);  //当前音符时值的前3/4发声,后1/4静音

enable = 1;

cnt++;

}

else {

if (cnt == durationCnt) {

cnt = 0;

i++;

}

else {

cnt++;

if (cnt == soundCnt) {

enable = 0;

}

}

}

}

}

void interruptTmr0() interrupt 1 {

TH0 = T0RH;

TL0 = T0RL;

tmrFlg = 1;

if (enable)

BUZZ = ~BUZZ;

else

BUZZ = 1;

}

void setTmr1(uint ms) {

ulong tmp;

tmp = 11059326 / 12;

tmp = tmp * ms / 1000;

tmp = 65536 - tmp;

tmp += 28;

T1RL = tmp;

T1RH = tmp >> 8;

}

void interruptTmr1() interrupt 3 {

TH1 = T1RH;

TL1 = T1RL;

//if (enKey)

keyScan();

}

void keyScan() {

static uchar i = 0;

static uchar keyBuf[4][4] = {

{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},

{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}

};

uchar j;

keyBuf[i][0] = (keyBuf[i][0] <

keyBuf[i][1] = (keyBuf[i][1] <

keyBuf[i][2] = (keyBuf[i][2] <

keyBuf[i][3] = (keyBuf[i][3] <

for (j=0; j<4; j++) {

if (keyBuf[i][j] == 0x00)

keyState[i][j] = 0;

else if (keyBuf[i][j] == 0xFF)

keyState[i][j] = 1;

}

switch (i) {

case 0: KEY_OUT_0 = 1; KEY_OUT_1 = 0; break;

case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;

case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;

case 3: KEY_OUT_3 = 1; KEY_OUT_0 = 0; break;

default : break;

}

i = ++i & 0x03;

}

void keyAction(uchar keyCode) {

if (keyCode >= 0x30 && keyCode <= 0x39) {

nowMusic = keyCode - 0x30;

if (nowMusic

//TR1 = 0;

playMusic(nowMusic, musicSpeed);

}

}

else if (keyCode == 0x27 || keyCode == 0x28) {

if (nowMusic

nowMusic++;

else

nowMusic = 0;

//TR1 = 0;

playMusic(nowMusic, musicSpeed);

}

else if (keyCode == 0x25 || keyCode == 0x26) {

if (nowMusic > 0)

nowMusic--;

else

nowMusic = musicNum - 1;

//TR1 = 0;

playMusic(nowMusic, musicSpeed);

}

}

void keyDriver() {

uchar i, j;

static uchar backup[4][4] = {

{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}

};

//if (enKey)

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

for (j=0; j<4; j++)

if (keyState[i][j] != backup[i][j]) {

if (keyState[i][j] == 0) {

keyAction(keyCodeMap[i][j]);

//enKey = 0;

}

backup[i][j] = keyState[i][j];

}

}

51单片机音乐播放器c语言,51单片机之简单的音乐播放器相关推荐

  1. 51单片机4位数乘法C语言,51单片机实现4位数以内的加减法

    中南民族大学,电子信息工程学院,开设了一门课程,叫<嵌入式电路设计>,由舒老师带头,旨在引导低年级的学生入门嵌入式,其内容比较多,包括模电.数电.C语言.单片机.EDA技术等.最近有位师弟 ...

  2. 单片机波特率不加倍c语言,51单片机硬件系统设计时,为什么用11.0592MHz的晶振而不用12MHz晶振的原因及串口波特率误...

    在设计51系列的单片机系统时,一般选用11.0592MHz的晶振而不选用12MHz的晶振,为什么?12M的晶振,振荡频率明显高于11.0592M的,按理说12MHz的晶振可以提高单片机的性能,那么我们 ...

  3. linux添加音乐的代码,C语言实现linux系统下的MP3播放器源代码

    [实例简介] 能识别本地的MP3歌曲文件,能根据路径添加入播放器中. 能识别本地的播放列表信息. 具有播放列表功能,能根据用户的需求随意创建.删除播放列表. 用户能往指定的播放列表中添加.删除 ...

  4. 基于单片机的倒车雷达系统设计c语言,基于单片机的倒车雷达设计.doc

    基于单片机的倒车雷达设计 毕业设计(论文) 题 目: 基于单片机的倒车雷达设计 系(院): 工业与信息化学院 专业: 电气自动化技术 姓 名: 学号: 校内指导教师: 职称: 讲 师 摘 要 随着社会 ...

  5. 单片机用python还是c语言_单片机为什么一直用C语言,不用其他编程语言?

    单片机为什么还在用C语言编程?答案是:C语言是最适合单片机编程的高级语言. 这个问题的意思应该是:现在有很多很好用的高级语言,如java,python,VC等等,为什么这些语言不能用来编写单片机程序呢 ...

  6. 单片机原理及应用c语言编程,单片机原理及应用(C语言版)

    目录 模块1单片微型计算机 项目1:认识单片微型计算机 任务11:认识单片机 任务12:相关知识 项目2:认识单片机应用 任务21:了解单片机应用 任务22:相关知识 项目3:认识仿真软件Pr ...

  7. 基于单片机的数字电压表设计c语言,基于单片机的数字电压表设计(.doc

    基于单片机的数字电压表设计( 成绩 西南科技大学城市学院 City College of Southwest University Of Science and Technology 基于单片机的数字 ...

  8. 51单片机生日快乐歌c语言,51单片机演奏音乐“祝你生日快乐”

    原标题:51单片机演奏音乐"祝你生日快乐" ; ORG 0000H LJMP START ORG 000BH INC 20H ;中断服务,中断计数器加1 MOV TH0,#0bbH ...

  9. 51单片机生日快乐歌c语言,51单片机实现生日快乐歌

    for(j=0;j<115;j++); } //生日快乐歌的音符频率表,不同频率由不同的延时来决定 u8 code SONG_TONE[]={212,212,190,212,159,169,21 ...

最新文章

  1. 读取csv绘制直方图_[python]用tushare接口绘制Bollinger Bands
  2. 笔记6 | 从源码理解分析mScrollX和mScrollY,scrollTo()和scrollBy(),smoothScrollTo和smoothScrollBy...
  3. bootstrap.yml与application.properties区别?
  4. Python开发基础--- 进程间通信、进程池、协程
  5. wps java转换成doc_WPS能转PDF吗?WPS转换不能错过的一款软件!
  6. mysql中的extra是什么意思_1130mysql explain中的type列含义和extra列的含义
  7. php 当前页面停留时间,PHP 记录页面停留时间
  8. 1亿中国人已被AI批改过作业
  9. OUTLOOK新邮件到达提醒设置以及outlook最小化到托盘设置
  10. 1月2日 Ubuntu14.04安装和配置ROS Indigo(一)
  11. python学习之课后习题
  12. css3 水纹效果(仿写阿里云)
  13. 实验一:JDK下载与安装、 Eclipse下载与使用
  14. Hive窗口函数保姆级教程
  15. Java 图标logo的由来
  16. hbase0.95 官方文档
  17. 〖Python自动化办公篇㉑〗- python实现邮件自动化 - 定时发送邮件
  18. cairo填充_Cairo学习笔记
  19. CHIP-seq流程学习笔记(3)-比对软件 bowtie2
  20. TensorFlow及深度学习相关资料积累汇总【不定期更新】

热门文章

  1. Storm tick 功能
  2. ros(2) 发布者publisher的编程实现
  3. 阿里云视频云「 vPaaS 」演绎了怎样的音视频应用开发「未来图景」
  4. 6万人同时离场,竟然一点都不挤?原来用了这个神器
  5. 数据仓库介绍与实时数仓案例
  6. 开源SQL-on-Hadoop系统一览
  7. 重磅!阿里巴巴工程师获得 containerd 社区席位,与社区共建云时代容器标准 1
  8. 阿里云移动研发平台EMAS,是如何连续5年安全护航双11的?
  9. 德勤发布2021年度企业AI应用现状报告,AI驱动已成竞争必需品
  10. Cloud一分钟 | 误删生产数据库血案,顺丰高级工程师被开除;阿里巴巴暂停美国云计算扩张?阿里云总裁正式回应:“不会减少投入”...