通过蜂鸣器实现播放三首音乐,三个按键分别控制上一首,下一首,暂停与播放,lcd显示播放音乐名称,同时led点阵根据音乐闪烁(爱心形状)
制作出来的实物图如下:
单片机源程序如下:
- #include <REGX52.H>
- #include "LCD1602.h"
- #include <intrins.h>
- sbit Buzzer = P2^5;
- sbit KEY_PREV = P3^0; // 上一曲
- sbit KEY_NEXT = P3^1; // 下一曲
- sbit KEY_PAUSE = P3^2; // 暂停/继续
- sbit SCK=P3^6;
- sbit RCK=P3^5;
- sbit SER=P3^4;
- unsigned char Index = 1;
- bit updateLED=0;
- bit pause = 0; // 初始开始状态
- unsigned int FreqSelect;
- //--定义要使用的IO口--//
- #define Led_Port P0
- //--列选通控制--//
- unsigned char code TAB[8] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
- void Delay(unsigned int xms) {
- while(xms--) {
- unsigned char i = 2, j = 239;
- do { while (--j); } while (--i);
- }
- }
- void _74HC595_WriteByte(unsigned char Byte)
- {
- unsigned char i;
- for(i=0;i<8;i++)
- {
- SER=Byte&(0x80>>i); // 取出每一位数据
- SCK=1; // 下移一位
- SCK=0;
- }
- RCK=1; //传输数据
- RCK=0;
- }
- void MatrixLED_ShowColumn(unsigned char Column,Data)
- {
- _74HC595_WriteByte(Data);
- Led_Port=~(0x80>>Column); // 将数据显示在相应的列上
- Delay(1); // 消隐操作
- Led_Port=0xFF;
- }
- void love_display()
- {
- SCK=0;
- RCK=0;
- MatrixLED_ShowColumn(0,0x30);
- MatrixLED_ShowColumn(1,0x78);
- MatrixLED_ShowColumn(2,0x7C);
- MatrixLED_ShowColumn(3,0x3E);
- MatrixLED_ShowColumn(4,0x7C);
- MatrixLED_ShowColumn(5,0x78);
- MatrixLED_ShowColumn(6,0x30);
- MatrixLED_ShowColumn(7,0x00);
-
- }
- #define P0 0 //休止符
- #define L1 1 //低音L
- #define L1_ 2 //'_'表示升半音
- #define L2 3
- #define L2_ 4
- #define L3 5
- #define L4 6
- #define L4_ 7
- #define L5 8
- #define L5_ 9
- #define L6 10
- #define L6_ 11
- #define L7 12
- #define M1 13 //中音M
- #define M1_ 14
- #define M2 15
- #define M2_ 16
- #define M3 17
- #define M4 18
- #define M4_ 19
- #define M5 20
- #define M5_ 21
- #define M6 22
- #define M6_ 23
- #define M7 24
- #define H1 25 //高音H
- #define H1_ 26
- #define H2 27
- #define H2_ 28
- #define H3 29
- #define H4 30
- #define H4_ 31
- #define H5 32
- #define H5_ 33
- #define H6 34
- #define H6_ 35
- #define H7 36
- #define SPEED 500 //宏定义四分音符时常为500ms
- unsigned int code AutoFreq[]={//基于C大调
- 0,//休止符
- 63628,63731,63835,63928,64021,64103,64185,64260,64331,64400,64463,64528,//低音
- 64582,64633,64686,64732,64778,64820,64860,64898,64934,64968,65000,65032,//中音
- 65059,65085,65111,65134,65157,65178,65198,65217,65235,65252,65268,65284 //高音
- };
- //小星星乐谱
- unsigned char code Music1[] = {
- //S1
- M1, 4,
- M1, 4,
- M5, 4,
- M5, 4,
- //S2
- M6, 4,
- M6, 4,
- M5, 4+4,
- //S3
- M4, 4,
- M4, 4,
- M3, 4,
- M3, 4,
- //S4
- M2, 4,
- M2, 4,
- M1, 4+4,
- //S5
- M5, 4,
- M5, 4,
- M4, 4,
- M4, 4,
- //S6
- M3, 4,
- M3, 4,
- M2, 4+4,
- //S7
- M5, 4,
- M5, 4,
- M4, 4,
- M4, 4,
- //S8
- M3, 4,
- M3, 4,
- M2, 4+4,
- //S9
- M1, 4,
- M1, 4,
- M5, 4,
- M5, 4,
- //S10
- M6, 4,
- M6, 4,
- M5, 4+4,
- //S11
- M4, 4,
- M4, 4,
- M3, 4,
- M3, 4,
- //S12
- M2, 4,
- M2, 4,
- M1, 4+4,
- //终止符
- 0xFF
- };
- //Music1《天空之城》
- unsigned char code Music2[]={ //(音高,时长)
- //1
- P0,4,P0,4,P0,4,M6,2,M7,2, //每一行为一小节,
- H1,4+2,M7,2,H1,4,H3,4,
- M7,4+4+4,M3,2,M3,2,
- //2
- M6,4+2,M5,2,M6,4,H1,4,
- M5,4+4+4,M3,4,
- M4,4+2,M3,2,M4,4,H1,4,
- //3
- M3,4+4,P0,2,H1,2,H1,2,H1,2,
- M7,4+2,M4_,2,M4_,4,M7,4,
- M7,4+4,P0,4,M6,2,M7,2,
- //4
- H1,4+2,M7,2,H1,4,H3,4,
- M7,4+4+4,M3,2,M3,2,
- M6,4+2,M5,2,M6,4,H1,6,
- //5
- M5,4+4+4,M2,2,M3,2,
- M4,4,H1,2,M7,2+2,H1,2+4,
- H2,2,H2,2,H3,2,H1,2+4+4,
- //6
- H1,2,M7,2,M6,2,M6,2,M7,4,M5_,4,
- M6,4+4+4,H1,2,H2,2,
- H3,4+2,H2,2,H3,4,H5,4,
- //7
- H2,4+4+4,M5,2,M5,2,
- H1,4+2,M7,2,H1,4,H3,4,
- H3,4+4+4,
- //8
- M6,2,M7,2,H1,4,M7,4,H2,2,H2,2,
- H1,4+2,M5,2+4+4,
- H4,4,H3,4,H2,4,H1,4,
- //9
- H3,4+4+4,H3,4,
- H6,4+4,H5,4,H5,4,
- H3,2,H2,2,H1,4+4,P0,2,H1,2,
- //10
- H2,4,H1,2,H2,2,H2,4,H5,4,
- H3,4+4+4,H3,4,
- H6,4+4,H5,4+4,
- //11
- H3,2,H2,2,H1,4+4,P0,2,H1,2,
- H2,4,H1,2,H2,2+4,M7,4,
- M6,4+4+4,M6,2,M7,2,
-
- 0xff //结束
- };
- //Music2
- unsigned char code Music3[]={ //(音高,时长)
- //1
- M1,2,M2,2,L6,2,L5,2,M5,6,M6,2,//每一行为一小节,
- M3,2,M5,2,H1,2,M6,2,M5,8,
- M5,4,M6,2,M5,2,M3,2,M2,2,M3,4,
- M5,2,M3,2,L6,2,M1,2,M2,8,
- //2
- M2,2,M5,2,M3,2,M1,2,L6,4,L5,2,L6,2,
- M2,2,M6,2,M5,2,M6,2,M3,6,M2,2,
- M1,2,M2,1,M2,1,M3,2,M5,1,M5,1,H1,2,M6,2,M5,4,
- //3
- M5,2,L6,2,M1,2,M2,2,M4,6,M6,1,M6,1,
- M5,3,M6,1,M3,2,M2,2,M1,8,
- M1,8,P0,4,M5,2,M5,2,
- H1,8,H2,6,H1,2,
- M6,2,H1,2,M5,2,M7,2,M6,8,
- //4
- M5,4,M3,4,H1,4,M6,3,M6,1,
- M5,2,M6,2,M1,2,M2,2,M3,8,
- M3,4,M3,2,M5,2,M6,4,M6,2,H1,2,
- H2,4,H3,2,H1,2,H2,4+2,H1,2,
- //5
- H2,2,M3,2,M5,2,M6,2,M7,2,H2,1,H2,1,M6,2,M7,2,
- M5,16,
- H2,2,M7,2,M6,2,M5,2,M3,2,M5,1,M5,1,M6,2,H2,2,
- H1,16,
-
- 0xff //结束
- };
- void Key_Proc() {
- static bit key_flag = 0;
- static unsigned char MusicSelect = 0;
- // 下一曲检测
- if (!KEY_NEXT) {
- Delay(10); // 消抖
- if (!KEY_NEXT && !key_flag) {
- key_flag = 1;
- if (++Index > 3) Index = 1;
- MusicSelect = 0;
- }
- } else if (KEY_NEXT) {
- key_flag = 0;
- }
- // 上一曲检测
- if (!KEY_PREV) {
- Delay(10); // 消抖
- if (!KEY_PREV && !key_flag) {
- key_flag = 1;
- if (--Index < 1) Index = 3;
- MusicSelect = 0;
- }
- } else if (KEY_PREV) {
- key_flag = 0;
- }
- // 暂停/继续检测
- if (!KEY_PAUSE) {
- Delay(10); // 消抖
- if (!KEY_PAUSE) {
- pause = !pause;
- if (pause) {
- TR0 = 0;
- Buzzer = 0; // 关闭蜂鸣器
- } else {
- TR0 = 1;
- }
- }
- while (!KEY_PAUSE); // 等待按键释放
- }
- }
- void Autoplay() {
- static unsigned char MusicSelect = 0;
- static unsigned char lastIndex = 0; // 新增索引跟踪
- const unsigned char *currentMusic=0;
- // 歌曲切换时重置播放位置
- if(Index != lastIndex) {
- MusicSelect = 0;
- lastIndex = Index;
- }
- // 选择当前歌曲
- switch(Index) {
- case 1: currentMusic = Music1; break;
- case 2: currentMusic = Music2; break;
- case 3: currentMusic = Music3; break;
- default: return;
- }
- if(!pause) {
- if(currentMusic[MusicSelect] != 0xff) {
- FreqSelect = currentMusic[MusicSelect];
- MusicSelect++;
- Delay(SPEED/4 * currentMusic[MusicSelect]);
- MusicSelect++;
-
- // 音符间隔处理
- TR0 = 0;
- Delay(5);
- TR0 = 1;
- } else {
- MusicSelect = 0; // 循环播放
- }
- } else
- {
- TR0 = 0;
- Buzzer = 0;
- }
- }
- void Display() {
- static unsigned char lastIndex = 0;
- static bit lastPause = 0;
- static unsigned int refreshCnt = 0;
- if (++refreshCnt >= 1000||pause != lastPause || Index != lastIndex) {
- refreshCnt = 0;
- EA=0;
- LCD1602_Clear(); // 清屏(已优化延时)
- Delay(5);
- if (pause) {
- LCD1602_DispString(1, 1, "Paused "); // 填充至16字符
- } else {
- switch(Index) {
- case 1:
- // 第1行:"Twinkle Twinkle"(16字符)
- LCD1602_DispString(1, 1, "Twinkle Twinkle");
- // 第2行:"Little Star "(16字符,2个空格)
- LCD1602_DispString(2, 1, "Little Star ");
- break;
- case 2:
- // 第1行:"Castle in the Sky"(16字符,修正空格)
- LCD1602_DispString(1, 1, "Castle in theSky");
- // 第2行留空
- LCD1602_DispString(2, 1, " ");
- break;
- case 3:
- // 第1行:"My Motherland "(16字符,2个空格)
- LCD1602_DispString(1, 1, "My Motherland ");
- // 第2行留空
- LCD1602_DispString(2, 1, " ");
- break;
- }
- }
- EA=1;
- lastIndex = Index;
- lastPause = pause;
- }
- }
- void Timer0Init(void)
- {
- TMOD &= 0xF0;
- TMOD |= 0x01;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
Keil5程序51hei附件下载:
大实验.rar
(62.76 KB, 下载次数: 0)
|