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

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

音乐播放器:

按键 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];

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/522629.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

再次“重新定义” 华为争做数据基础设施领航者

戳蓝字“CSDN云计算”关注我们哦&#xff01;数字经济是随着信息技术革命发展而产生的一种新的经济形态。近年来&#xff0c;随着我国开始更多从经济视角观察数字化问题&#xff0c;数字经济开始升温。7月31日&#xff0c;国家统计局发布2018年我国经济发展新动能指数。测算结果…

《阿里巴巴Android开发手册》正式发布,献给移动开发者的新年礼物

春节余味尚未消&#xff0c;我们为移动开发者准备了一份迟到的新年礼物——《阿里巴巴Android开发手册》&#xff0c;继《阿里巴巴Java开发手册》之后&#xff0c;阿里巴巴开发规范家族又添一丁&#xff0c;「阿里巴巴Android开发规范」认证考试也同步上线。 手册免费下载&…

搜索引擎背后的原理和中文日志检索

摘要&#xff1a; 日志服务支持的两种搜索方式 通过设置分词字符(通常是标点符号)&#xff0c;把一段文本划分成不同的单词。分词字符只能是单字节ascii字符这种方式适合于切分英文单词。这种方式对于中文日志&#xff0c;必须要搜索中文语句整体。 点此查看原文&#xff1a;ht…

解决在已办任务菜单中都会抛出异常,由于definitionId=undefined导致的问题

任务办理完了&#xff0c;在已办任务(历史)菜单中&#xff0c;查看一下任务办理的节点信息不为过吧&#xff0c; 其实&#xff0c;也是那个definitionIdundefined导致的&#xff0c;也是由于获取的对象不对&#xff0c;这里我直接修改程序。 解决方案&#xff1a; //修改后…

华为高通5G华山论剑,一文看懂5G芯片背后的明争暗斗

戳蓝字“CSDN云计算”关注我们哦&#xff01;来源&#xff1a;鲜枣课堂作者&#xff1a;小枣君 6月6日工信部正式发放5G商用牌照之后&#xff0c;国内5G网络建设的步伐大幅加快了。越来越多的城市出现了5G基站和5G信号&#xff0c;5G离我们的距离更近了。面对激动人心的5G&…

c语言正确理解以下名词及其含义,C程序作业答案.doc

C程序作业答案.doc什么是程序及程序设计 程序(program)是为实现特定目标或解决特定问题而用计算机语言编写的命令序列的集合。为实现预期目的而进行 操作的一系列语句和指令。一般分为系统程序和应用程序两大类。程序设计Programming是指设计、编制、调试程 序的方法和过程。它…

阿里云NAS备份服务

摘要&#xff1a; 阿里云NAS&#xff08;Network Attached Storage&#xff09;是一款高可靠高可用高性能的分布式存储产品&#xff0c;应用场景包括ECS、HPC、Docker等共享存储。目前已经有大量的客户使用NAS作为他们的数据存储&#xff0c;其中包括今日头条、Ofo这样的大型互…

win10默认壁纸_仅4M!微软出品的壁纸软件,让桌面每天都不一样!

有一张好看的壁纸&#xff0c;看起来都非常的舒服&#xff0c;不管是手机还是电脑。现在市面上的壁纸软件非常多&#xff0c;小助手用了几款都觉得很一般&#xff0c;所以都没有大家推荐。但上个月&#xff0c;微软官方出品了一款电脑壁纸软件「Bing Wallpaper」&#xff0c;简…

第8篇:Flowable快速工作流脚手架Jsite_请假实战_查看历史任务

节点流转结束了&#xff0c;jsite发起流程的执行人&#xff0c;查看一下历史任务应该吧。 先追踪一下流程详情 很明显又是这个问题&#xff0c;大家应该知道怎末改了吧&#xff0c; 再次测试

AMD 发布第二代EPYC处理器,重新定义数据中心新标准

2019 年8 月7 日&#xff0c;旧金山讯——AMD 公司今日召开发布会&#xff0c;在空前壮大的数据中心产业链合作伙伴和客户的见证下&#xff0c;正式发布了第二代 AMD EPYC&#xff08;霄龙&#xff09;系列处理器&#xff0c;为众多企业级、云和高性能计算(HPC)工作负载带来领先…

获取当前系统时间c语言,使用C语言获取当前系统的时间

要想使用C语言来获取当前系统的时间&#xff0c;办法如下&#xff1a;需要提前准备的工作&#xff1a;1 #include 2 #include 3 #include 45 intmain()6 {7 time_t rawtime; //时间类型&#xff0c;由time.h中定义8 struct tm *timeinfo; //关于时间的结构体类型&#xff0c;在…

苹果手机悬浮窗怎么打开_怎么通过悬浮窗录音?再也不用担心文本被遮挡

怎么通过悬浮窗录音&#xff1f;在录音的时候经常遇到这种情况&#xff0c;打开了录音软件&#xff0c;录音软件就遮挡了要录制的文本&#xff0c;将文本缩小看起来又很不方便。在生活中&#xff0c;这种情况其实很普遍&#xff0c;主要是因为录音软件没有选择好。在浏览器搜索…

AliOS Things SIG BLE Mesh网络的介绍和搭建

摘要&#xff1a;在最新的版本(1.2.1)中&#xff0c;AliOS Things 开始支持SIG BLE mesh。本文对SIG BLE mesh及如何使用AliOS Things搭建BLE mesh网络进行了详细的说明。点此查看原文&#xff1a;http://click.aliyun.com/m/42946/在最新的版本(1.2.1)中&#xff0c;AliOS Thi…

联想ThinkPad笔记本Fn键关闭与启用方法

最快捷的方法&#xff0c;按FnEsc键启用Fn功能键

android图标错误的是什么意思啊,Android错误:找不到与给定名称匹配的资源(在icon处,值为@drawable/icon) - Android - srcmini...

本文概述将旧版本的项目导入Android Studio时, 似乎会导致此错误, 然后Android Studio会将gradle版本更新为最新版本, 从而导致该错误。对于具有旧版本gradle的Cordova项目, 这似乎也发生了, 当你使用cordova平台删除旧的android平台时, 请删除android, 然后使用cordova平台重新…

02年六代雅阁的整备质量_2020年宝安第八批更新计划:联投地产5.4万㎡“工改”项目...

今日(10月22日)&#xff0c;宝安区更新整备局发布关于《2020年深圳市宝安区城市更新单元第八批计划》(草案)&#xff0c;共2个工改项目&#xff0c;即大田洋工业区东方三队、四队片区更新项目、沙民马安山工业区更新项目&#xff0c;合计拆除用地面积112446㎡。龙华区更新整备局…

被吹得天花乱坠的无服务器架构,究竟是什么?

戳蓝字“CSDN云计算”关注我们哦&#xff01;无服务器计算&#xff08;Severless computing&#xff0c;简称 Serverless&#xff09;现在是软件架构圈中的热门话题&#xff0c;国外三大云计算供应商&#xff08;Amazon、Google 和 Microsoft&#xff09;都在大力投入这个领域&…

idea配置的导入导出

摘要&#xff1a;每当更新了工具&#xff0c;或者其他电脑想使用idea工具&#xff0c;配置不可能重新配置&#xff0c;这时只要把已配置好的导出来&#xff0c;打开新的idea时&#xff0c;直接导入即可。 文章目录一、导出配置二、导入配置一、导出配置 打开工具&#xff0c;找…

基于阿里云移动推送的移动应用推送模式最佳实践

摘要&#xff1a;### 一、概念 以下概念对应系统设计时的语义&#xff0c;对于如何合理使用移动推送有借鉴意义 #### 1.1 设备 安装并使用开发者移动应用的装置 #### 1.2 设备ID 阿里云移动推送为设备分配的唯一ID&#xff0c;可以通过阿里云移动推送SDK端提供的接口获取 点此阅…

android 底部滑动效果怎么做,Android实现简单底部导航栏 Android仿微信滑动切换效果...

android仿微信滑动切换最终实现效果&#xff1a;大体思路&#xff1a;1. 主要使用两个自定义view配合实现; 底部图标加文字为一个自定义view,底部导航栏为一个载体,根据需要来添加底部图标;2. 底部导航栏的设置方法类似于tablayout的关联,view需要创建关联方法,用来关联viewpag…