单片机音乐盒完整代码

单片机音乐盒完整代码

该设计是使用C51单片机制作的音乐盒制作的一个音乐盒,可以实现进行歌曲的切换,暂停/播放。此外还增加了随机点歌,获取大气温湿度等功能。使用LCD1602显示器进行歌曲名称和大气温湿度的显示。将完整代码帖在下面,有需要的可以自己获取。完整代码可以在我的博客下面,我的资源下面进行下载使用。

由于我上传的资源需要积分,所以我重新更新了代码,现在以将完整代码贴出,有需要的可以自己看一下,如果遇到有什么问题的可以问一下我。如果觉得还行的请帮我点个赞,谢谢大家。

如果下面贴出的代码,大家不能看懂的,或者使用有麻烦的可以给我私信。

下面是一些实物图片

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

部分代码如下

main.c

#include "main.h"
#include "delay.h"
#include "beep.h"

uchar RH,RL,TH,TL;//定义变量用来存储温湿度变量的值

extern uchar timer1h, timer1l,time,K_Value,Singin_interface,Start,Stop;
extern char Number;



extern uchar code Player_Number1[9];


uchar KEY;//定义变量保存键值信息


//自定义1602显示心形字符
uchar code table1[]=
{   0x03,0x07,0x0f,0x1f,0x1f,0x1f,0x1f,0x1f,
    0x18,0x1E,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
    0x07,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
    0x10,0x18,0x1c,0x1E,0x1E,0x1E,0x1E,0x1E,
    0x0f,0x07,0x03,0x01,0x00,0x00,0x00,0x00,
    0x1f,0x1f,0x1f,0x1f,0x1f,0x0f,0x07,0x01,
    0x1f,0x1f,0x1f,0x1f,0x1f,0x1c,0x18,0x00,
    0x1c,0x18,0x10,0x00,0x00,0x00,0x00,0x00,//心图案
};

//定义流水灯断码
uchar code LED1[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40};
	


//定时器初始化函数
void  timer_init()
{
    TMOD=0x11;//定时器0和1都工作再方式一
	  TH0=(65536-30000)/256;
	  TL0=(65536-30000)%256;
	  EA=1;//开总中断
	  //开定时器中断
	  ET0=1;
    ET1=1;
    TR1=0;//首先关闭定时器T1
	  TR0=1;//开启定时器T0
	  PT1=1;
    PT0=0;

}


void  main()
{
    uchar i;
	  uchar flag1=0;
	  Player=1;
    Last_Song=1;
    Next_Song=1;
	  Choose_Song=1;//点歌按钮
    Confirmation=1;//确定按钮
   
	  P0=0xff;
    timer_init();
    lcd_init ();
    delay (50);
    
	
	  //向1602写入自定义字符
    Write_CGRAM(0x40,table1);
	
	  //再1602上显示自定义字符
	  //显示字符的前四位
    lcd_pos (0x0c);
    for(i=0; i<4; i++)
    {
        lcd_wdat(i);
    }
		//显示自定义字符的后四位
    lcd_pos (0x4c);
    for(i=4; i<8; i++)
    {
        lcd_wdat(i);
    }
		
		//在1602上显示自定义布局
		lcd_pos(0x00);
		lcd_word("T:");
		//温度
		lcd_pos(0x04);
		lcd_wdat(0xdF);
		lcd_wdat('C');
		//湿度
		lcd_pos(0x07);
		lcd_word("H:");
		lcd_pos(0x0b);
		lcd_wdat('%');
		
		
    lcd_pos (0x40);
    lcd_word("Sg:");

    lcd_word(Player_Number1);
    while(1)
    {	
					  Song(Number);  

		}			
        
}



void t0int() interrupt 1
{
	
	 static uchar Num0=0,Num1=0,i=0;
	
	 TH0=(65536-30000)/256;
	 TL0=(65536-30000)%256;
	 Num1++;	 
	//表示没有处于点个界面中,则进行数据刷新
	 if(Singin_interface==0)
	 {
	 Num0++;
	 if(Num0==90)//控制定时2.7秒钟,用来刷新数据
	 {		
	   receive();		 
		 //显示温湿度
     lcd_pos(0x02);
     lcd_wdat(TH/10+0x30);
		 lcd_wdat(TL%10+0X30);
		 
		 //显示湿度
		 lcd_pos(0x09);
     lcd_wdat(RH/10+0X30);
		 lcd_wdat(RL%10+0X30);
		 
		 Num0=0;
		
	 }
 }
	 
 
 //表示处于点歌界面中
 else if(Singin_interface==1)
 {
	     if(Start==1&&Stop==0)
			 {
        Number=rand_init();
        lcd_pos(0x48);
	      lcd_wdat(Number+0x30);
			 }
 
 }
	
 if(Num1==5)
	 {
	    P0=LED1[i];
	    i++;
		  if(i==7)
			{
			   i=0;
			}
			Num1=0;
	 }
 
 
}

void t1_int() interrupt 3     //T0中断程序,控制发音的音调         
 {                              
       TR1 = 0;                      //先关闭T0          s
       spaker =!spaker;           //输出方波, 发音                   
       TH1 = timer1h;               //下次的中断时间, 这个时间, 控制音调高低         
       TL1 = timer1l;          
       TR1 = 1;                     //启动T0        
 }  

main.h

#ifndef _main_h
#define _main_h

#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int
	
typedef bit BOOL;




sbit spaker=P1^0;//定义音频输出管脚

sbit Player=P3^2;//播放按钮
sbit Last_Song=P3^3;//上一首按钮
sbit Next_Song=P3^5;//下一首

sbit Choose_Song=P3^6;//点歌按钮
sbit Confirmation=P3^7;//确定按钮


//1602相关函数
void lcd_wcmd (uchar cmd);
void lcd_pos (uchar pos);
void lcd_wdat (uchar dat);
void lcd_init ();
void lcd_word(uchar *word);
void delay (int m);
void Write_CGRAM(uchar *adder,uchar *p);


//DHT11相关函数
void start1();
uchar receive_byte();
void receive();


//音乐发声相关函数
void song();
void key_scan();
void Song(uchar j); 
	

#endif

1602.c

/*
该文件用来编写LCD1602方面的程序

*/
#include "main.h"
#include "delay.h"


#define Dat_1602  P2//1602数据口
sbit rs=P1^7;
sbit rw=P1^6;
sbit ep=P1^5;


void delay (int m)
{
 unsigned char i,j;
 for (i=0;i<m;i++)
 for (j=0;j<253;j++);
}

//判断LCD1602是否处于忙碌状态
BOOL lcd_bz()
{
  BOOL result;
  rs=0;           // 读忙信号
  rw=1;
  ep=1;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  result = (BOOL)(Dat_1602&0x80);
  ep=0;
  return result;
}




//向LCD62写命令
void lcd_wcmd (uchar cmd)
{
  while (lcd_bz());
  rs=0;
  rw=0;
  ep=0;
  _nop_();
  _nop_();
  Dat_1602=cmd ;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  ep=1;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  ep=0;
}


//指定当前LCD1602要显示字符的位置
void lcd_pos (uchar pos)
{
  lcd_wcmd (pos|0x80);
}

void lcd_wdat (uchar dat)
{
   while (lcd_bz());
  rs=1;
  rw=0;
  ep=0;
  _nop_();
  _nop_();
  Dat_1602=dat ;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  ep=1;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  ep=0;
}


//LCD1602初始化
void lcd_init ()
{
  lcd_wcmd (0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口
  delay (1);
  lcd_wcmd (0x0c); //显示模式设置:光标右移,字符不移  
  delay (1);
  lcd_wcmd (0x06); //显示模式设置:光标右移,字符不移  
  delay (1);
  lcd_wcmd (0x01); //清屏幕指令,将以前的显示内容清除 
  delay (1);


}
//向LCD1602发送字符串
void lcd_word(uchar *word)
{
   uchar i=0;
	 while(word[i]!='\0')
	 { 
	   lcd_wdat(word[i]);
		 i++;
	 }

}


//LCD1602自定义字符函数
void Write_CGRAM(uchar *adder,uchar*p)
{

    //uchar LOL=0x40;//操作CGRAM的命令码
    uchar i,j,V=0;
	  for(j=0;j<8;j++)
	{
	  for(i=0;i<8;i++)
	  {
	     lcd_wcmd(adder+i);
			 lcd_wdat(p[V]); 
       V++;			
	  }
		adder+=8;
	}

}


delay.h

#include "main.h"
#include "math.h"
#include "stdio.h"





void delay1(uchar t)
{
 uchar t1;
unsigned long t2;
for(t1=0;t1<t;t1++)
{
for(t2=0;t2<8000;t2++)
{
   ;
}
}
TR0=0;
}





void delay8us()//一个FOR循环大概需要8个机器周期,一个机器周期大约是1us也就是说12MHZ的晶振对此函数的延时
//是8US多 所以此延时函数更精确
{
    unsigned char i;
    for(i = 0; i < 1; i++);

}


//定义延时函数
void delay_WO(unsigned char ms)
{
    unsigned char i;
    while(ms--)
        for(i = 0; i < 100; i++);

}


void delay_player(unsigned char t)    //延时子函数,控制发音的时间长度
{   uchar t1;
    unsigned long t2;
    for(t1 = 0; t1 < t; t1++)          //嵌套循环, 共延时t个半拍
    for(t2 = 0; t2 < 8000; t2++); //延时期间, 可进入T0中断去发音   8
    TR1 = 0;                        //关闭T0, 停止发音

}


void Delay5ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 59;
	j = 90;
	do
	{
		while (--j);
	} while (--i);
}


void Delay100ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 5;
	j = 144;
	k = 71;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}



//随机数产生函数
unsigned char rand_init()
{
    uchar i;
    i=rand()%8;
    return i;
}

dht11.c

#include "main.h"
#include "delay.h"

//DHT11的数据管脚
sbit io=P1^4;

uchar data_byte;

extern uchar RH,RL,TH,TL;




//单片机发送开始信号
void start1()
{
   io=1;
   delay8us();
   io=0;
   delay_WO(25);
   io=1;
   delay8us();
   delay8us();
   delay8us();



}

uchar receive_byte()
{
  unsigned char i,temp;
  for(i=0;i<8;i++)
  {
    while(!io);
	delay8us();
	delay8us();
	delay8us();
	temp=0;
	if(io==1)
	temp=1;
	while(io);
	data_byte<<=1;
	data_byte|=temp;
  }
  return data_byte;
}

void receive()
{
  uchar T_H,T_L,R_H,R_L,check,num_check,i;
	start1();
	io=1;
	if(!io)
	{
	   while(!io);
	   while(io);
	   R_H=receive_byte();
	   R_L=receive_byte();
	   T_H=receive_byte();
	   T_L=receive_byte();
	   check=receive_byte();
	   io=0;
	   for(i=0;i<7;i++)
	   delay8us();
	   io=1;		
	   num_check=R_H+R_L+T_H+T_L;
	   if(num_check==check)
	   {
	   	RH=R_H;
		  RL=R_L;
		  TH=T_H;
		  TL=T_L;
		  check=num_check;	   	   
	   }
	
	}

}

beep.c

#include "main.h"
#include "delay.h"
#include "beep.h"


// 频率-半周期数据表 高八位     本软件共保存了四个八度的28个频率数据
uchar code FREQH[] = {     0xF2, 0xF3, 0xF5, 0xF5, 0xF6, 0xF7, 0xF8,    //低音1234567
                           0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC,//1,2,3,4,5,6,7,i
                           0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE,            //高音 234567
                           0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF
                     };   //超高音 1234567
// 频率-半周期数据表 低八位
uchar code  FREQL[] = {    0x42, 0xC1, 0x17, 0xB6, 0xD0, 0xD1, 0xB6,    //低音1234567
                           0x21, 0xE1, 0x8C, 0xD8, 0x68, 0xE9, 0x5B, 0x8F, //1,2,3,4,5,6,7,i
                           0xEE, 0x44, 0x6B, 0xB4, 0xF4, 0x2D,             //高音 234567
                           0x47, 0x77, 0xA2, 0xB6, 0xDA, 0xFA, 0x16
                      };   //超高音 1234567              //----------------------------------------------------------------------------------------------
// 要想演奏不同的乐曲, 只需要修改这个数据表
uchar code music[8][500] = {

    //乡间小路数据表
    {
        3,1,2, 3,1,1, 3,1,1, 6,0,1, 6,0,1, 1,1,2, 6,0,1, 5,0,1, 6,0,4, 6,0,2, 6,0,1 ,6,0,1, 6,0,2, 6,0,1,
        1,1,1, 2,1,2, 2,1,1, 3,1,1, 2,1,4, 3,1,1, 3,1,1, 3,1,1, 2,1,1, 4,1,2, 4,1,2, 3,1,2, 2,1,1, 1,1,1,
        2,1,4, 7,0,1, 7,0,1, 7,0,1, 6,0,1, 5,0,1, 5,0,1, 6,0,1, 7,0,1, 7,0,1, 6,0,1, 5,0,1, 6,0,4, 6,1,2,
        3,1,1, 6,1,1, 7,1,1, 6,1,1, 5,1,1, 5,1,2, 5,1,1, 2,1,1, 5,1,1, 6,1,1, 5,1,1, 4,1,1, 4,1,2, 4,1,1,
        3,1,1, 2,1,2, 1,1,1, 2,1,1, 3,1,1, 2,1,1, 1,1,1, 2,1,1, 3,1,4, 6,1,2, 3,1,1, 6,1,1, 7,1,1, 6,1,1,
        5,1,1, 5,1,2, 2,1,1, 5,1,1, 6,1,1, 5,1,1, 4,1,1, 4,1,2, 4,1,1, 5,1,1, 6,1,1, 4,1,1, 3,1,1, 2,1,2,
        2,1,2, 5,1,4, 0,0,0
    },

    // 送别数据表
    {   5,1,2, 3,1,3, 5,1,1, 1,2,3, 6,1,2, 1,2,2, 5,1,4,
        5,1,2, 1,1,1, 2,1,1, 3,1,2, 2,1,1, 1,1,1, 2,1,4,
        5,1,2, 3,1,1, 5,1,1, 1,2,2, 7,1,1, 6,1,2,
        1,2,2, 5,1,4, 5,1,2, 2,1,1, 3,1,1, 4,1,2, 7,0,1,
        1,1,4, 6,1,2, 1,2,2, 1,2,4, 7,1,2, 6,1,1, 7,1,1,
        1,2,4, 6,1,1, 7,1,1, 1,2,1, 6,1,1, 6,1,1, 5,1,1,
        3,1,1, 1,1,1, 2,1,8, 5,1,2, 3,1,1, 5,1,1, 1,2,2,
        7,1,1, 6,1,2, 1,2,2, 5,1,4, 5,1,2, 2,1,1, 3,1,1,
        4,1,2, 7,0,2, 1,1,4, 0,0,0
    },

    //一辈子的孤单数据表
    {   5,0,1, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 3,1,1, 2,1,1, 2,1,4,
        5,0,1, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 2,1,1, 1,1,1,
        2,1,1, 3,1,1, 3,1,4, 5,0,1, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 3,1,1, 2,1,1, 2,1,4, 2,1,1, 1,1,1,
        -3,1,1, 2,1,1,
        1,1,1, 2,1,1, 1,1,1, 1,1,8, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 1,1,1, 2,1,1, 2,1,6, 3,1,1, 2,1,2, 1,1,1, 1,1,1,
        -5,0,1, 6,0,1,
        5,0,1, 5,0,6, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 1,1,1, 2,1,1, 2,1,6, 5,0,1, 3,1,1, 2,1,2, 1,1,1, 2,1,2, 3,1,1,
        -3,1,4,
        5,0,1, 3,1,1, 5,1,2, 6,1,1, 3,1,1, 2,1,1, 2,1,6, 5,0,1, 3,1,1, 2,1,2, 1,1,1, 2,1,2, 3,1,1, 3,1,4,
        5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 2,1,1, 2,1,4, 2,1,1, 1,1,1, 3,1,1, 2,1,1, 1,1,1, 2,1,1, 1,1,1,
        -1,1,1, 1,1,6,
        3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 2,1,1, 2,1,6, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 2,1,1, 3,1,1, 3,1,6,
        5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 2,1,1, 2,1,6, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 2,1,1, 3,1,1,
        -3,1,6,0,0,0
    },


    //世上只有妈妈好数据表
    {   6,2,3,      5,2,1,      3,2,2, 5,2,2, 1,3,2, 6,2,1, 5,2,1,
        6,2,4,      3,2,2,      5,2,1, 6,2,1, 5,2,2, 3,2,2, 1,2,1,
        6,1,1,      5,2,1,      3,2,1, 2,2,4, 2,2,3, 3,2,1, 5,2,2,
        5,2,1,      6,2,1,      3,2,2, 2,2,2, 1,2,4, 5,2,3, 3,2,1,
        2,2,1,      1,2,1,      6,1,1, 1,2,1, 5,1,6, 0,0,0

    },


    {   5,1,1, 5,1,1, 6,1,2, 5,1,2, 1,2,2, 7,1,4,
        5,1,1, 5,1,1, 6,1,2, 5,1,2, 2,2,2, 1,2,4,
        5,1,1, 5,1,1, 5,2,2, 3,2,2, 1,2,2, 7,1,2, 6,1,2,
        4,2,1, 4,2,1, 3,2,2, 1,2,2, 2,2,2, 1,2,4
    },

    //发如雪
    {
        5,1,1, 2,2,1, 3,2,2, 2,2,1, 3,2,1, 5,2,1, 6,2,1, 5,2,3, 1,2,1, 2,2,1,
        3,2,1, 6,2,1, 5,2,1, 3,2,1, 5,2,3, 5,2,1, 6,2,1, 1,3,2, 6,2,1, 5,2,1,
        3,2,1, 5,2,1, 3,2,2, 1,2,1, 2,2,1, 3,2,1, 1,2,1, 6,1,1, 3,2,1, 2,2,1,
        5,1,1, 2,2,1, 3,2,2, 2,2,1, 3,2,1, 5,2,1, 6,2,1, 5,2,3, 1,2,1, 2,2,1,
        3,2,1, 6,2,1, 5,2,3, 5,2,1, 6,2,1, 1,3,2, 6,2,1,
        5,2,1, 3,2,1, 5,2,1, 3,2,2, 1,2,1, 6,1,1, 3,2,1, 2,2,1, 1,2,1, 6,1,1,
        1,2,1, 2,2,1, 2,2,1, 1,2,4, 0,0,0
    },

    //当你孤单会想起谁
    {
        3,2,2, 3,2,1, 4,2,1, 3,2,2, 2,2,1, 1,2,1,  2,2,2, 5,2,2, 2,2,2, 2,2,3,
        1,2,2, 1,2,1, 2,2,1, 1,2,2, 7,1,1, 6,1,1, 7,1,2, 3,2,2, 7,1,2, 7,1,3,
        6,1,2, 2,2,1, 3,2,1, 2,2,1, 1,2,1, 6,1,2, 5,1,2, 2,2,1, 3,2,1, 2,2,1,
        1,2,1, 6,1,2, 6,1,2, 2,2,1, 3,2,1, 2,2,1, 1,2,1, 6,1,1, 7,1,1, 1,2,6, 0,0,0
    },
		
		//简单爱
    {
     5,1,1, 1,2,1, 2,2,1, 3,2,1, 2,2,1, 3,2,1, 4,2,1, 5,2,1, 5,2,1, 5,2,1, 
         4,2,1, 3,2,1, 2,2,3, 5,1,1, 1,2,1, 2,2,1, 3,2,1, 4,2,1, 5,2,1, 5,2,1, 
         5,2,1, 6,2,1, 5,2,2, 2,2,1, 3,2,1, 1,2,2, 1,2,1, 6,1,1, 2,2,1, 2,2,1, 
         3,2,1, 3,2,1, 1,2,1, 5,2,1, 1,2,1, 5,2,1, 1,2,1, 7,1,1, 1,2,1, 1,2,1, 6,1,1, 
         2,2,1, 2,2,1, 3,2,1, 3,2,1, 5,2,1, 5,2,1, 
         5,2,1, 6,2,1, 5,2,2, 2,2,1, 3,2,1, 1,2,2,  
         5,1,1, 1,2,1, 2,1,2, 3,2,1, 2,2,1, 3,2,1, 4,2,1, 5,2,1, 5,2,1, 5,2,1, 
         4,2,1, 3,2,1, 2,2,3, 5,1,1, 1,2,1, 2,2,1, 3,2,1, 2,2,1, 3,2,1, 4,2,1, 
         5,2,1, 5,2,1, 5,2,2, 2,2,1, 3,2,1, 1,2,2, 1,2,1, 6,1,1, 2,2,1, 2,2,1, 
         3,2,1, 3,2,1, 1,2,2, 5,2,1, 1,2,1, 5,2,1, 5,2,1, 7,1,1, 1,2,1, 0,0,0 }
};


//定义歌曲名字
uchar code Player_Number1[10]="1.CyRoad ";
uchar code Player_Number2[10]="2.FeWell ";
uchar code Player_Number3[10]="3.LCover ";
uchar code Player_Number4[10]="4.Mother ";
uchar code Player_Number5[10]="5.Birhday";
uchar code Player_Number6[10]="6.SnHair ";
uchar code Player_Number7[10]="7.Althink";
uchar code Player_Number8[10]="8.SimLove";


//定义9各空格来进行下一首歌曲名字的显示
uchar code Tab[9]="         ";

//定义变量Singin_interface来判断是否处于点歌界面当变量等于一时表示处于点个界面中
//定义变量Start,Stop来判断点歌的开始与停止等于一时有效
uchar Singin_interface=0,Start=0,Stop=0;



/*定义变量timer1h, timer1l来存储定时器的初值,TIME用来控制延时时间,
K_Value用来存储键值Num用来记录
音乐播放到那一首*/


uchar timer1h, timer1l,time,K_Value;
char Number=0;


//发声控制函数
void song()
{
    TH1 = timer1h;               //控制音调
    TL1 = timer1l;
    TR1 = 1;                     //启动T0, 由T0输出方波去发音
    delay_player(time);                 //控制时间长度
}


void key_scan()
{

    //判断是否按下了播放按键
    if(Player==0)
    {
        Delay5ms();
        if(Player==0)
        {
            while(Player==0);
            K_Value=1;
        }


    }


    //判断是否按下了下一首按键
    else if(Next_Song==0)
    {
        Delay5ms();
        if(Next_Song==0)
        {
            while(Next_Song==0);
            K_Value=2;
        }

    }
    //判断是否按下了上一首的按键
    else if(Last_Song==0)
    {
        Delay5ms();
        if(Last_Song==0)
        {
            while(Last_Song==0);
            K_Value=3;
        }
    }

    //判断是否按下了点歌按钮
    else if(Choose_Song==0)
    {
        Delay5ms();
        if(Choose_Song==0)
        {
            while(Choose_Song==0);
            K_Value=4;
        }

    }
    //判断是否按下了确定按钮
    else if(Confirmation==0)
    {
        Delay5ms();
        if(Confirmation==0)
        {
            while(Confirmation==0);
            K_Value=5;
        }

    }
}

//音乐播放控制函数
void Song(uchar j) 	//j表示第n+1首曲   9
{
    uchar k, i,flag_play=0;
    uchar LCD_i=0;//用来显示从点歌界面切换回来时的自定义字符
    static char flag_next_song=0,K=0;//flag_next_song用来记录切换到了那一首歌曲,i用来记录按键5按下的次数
    i = 0;
    time = 1;
    while(time)
    {
        key_scan();
       if(Singin_interface==0)
			 {
        //说明播放按钮按下了,执行相应的操作
        if(K_Value==1)
        {
            TR1=0;
            ET1=0;
            flag_play++;
            K_Value=0;
            if( flag_play==2)
            {
                flag_play=0;
                TR1=1;
                ET1=1;
            }
        }

        //切换到下一首歌曲
        else if(K_Value==2)
        {

            K_Value=0;
            //开启定时器
            TR1=0;
            ET1=0;
            flag_next_song++;

            if(flag_next_song>7)//当到最后一首歌时循环到第一首
            {

                flag_next_song=0;
            }
            Number=flag_next_song;

            //在1602上显示歌曲名字
            switch(Number)
            {
            case 0:
                lcd_pos (0x43);
                lcd_word(Player_Number1);
                break;
            case 1:
                lcd_pos (0x43);
                lcd_word(Player_Number2);
                break;
            case 2:
                lcd_pos (0x43);
                lcd_word(Player_Number3);
                break;
            case 3:
                lcd_pos (0x43);
                lcd_word(Player_Number4);
                break;
            case 4:
                lcd_pos (0x43);
                lcd_word(Player_Number5);
                break;
            case 5:
                lcd_pos (0x43);
                lcd_word(Player_Number6);
                break;
            case 6:
                lcd_pos (0x43);
                lcd_word(Player_Number7);
                break;
						case 7:
							  lcd_pos (0x43);
                lcd_word(Player_Number8);
						    break;
            default:
                break;
            }

            TR1=1;
            ET1=1;

            break;
        }

        //切换到上一首歌
        else if(K_Value==3)
        {

            K_Value=0;
            //开启定时器
            TR1=0;
            ET1=0;
            flag_next_song--;
            if(flag_next_song<0)//当到最后一首歌时循环到第一首
            {
                flag_next_song=7;
            }
            Number=flag_next_song;

            //在1602上显示歌曲名字
            switch(Number)
            {
            case 0:
                lcd_pos (0x43);
                lcd_word(Player_Number1);
                break;
            case 1:
                lcd_pos (0x43);
                lcd_word(Player_Number2);
                break;
            case 2:
                lcd_pos (0x43);
                lcd_word(Player_Number3);
                break;
            case 3:
                lcd_pos (0x43);
                lcd_word(Player_Number4);
                break;
            case 4:
                lcd_pos (0x43);
                lcd_word(Player_Number5);
                break;
            case 5:
                lcd_pos (0x43);
                lcd_word(Player_Number6);
                break;
            case 6:
                lcd_pos (0x43);
                lcd_word(Player_Number7);
                break;
						case 7:
							  lcd_pos (0x43);
                lcd_word(Player_Number8);
						    break;
            default:
                break;
            }
            TR1=1;
            ET1=1;
            break;
        }

        //表示按下了点歌按键
        else if(K_Value==4)
        {

            Singin_interface=1;//将标志为置为一表示处于点歌界面中
            TR1=0;
            ET1=0;
            K_Value=0;
            lcd_wcmd (0x01);//刷新屏幕
            lcd_pos(0x00);
            lcd_word("Hello!  Welcome!");
            lcd_pos(0x41);
            lcd_word("Start      Stop");

        }
			}
        else if(Singin_interface==1)//表示在点歌界面中
        {
            //选择点歌的开始按钮
            if(K_Value==5)
            {

                K_Value=0;
                K++;
                if(K==1)
                {
                    ET1=0;
                    TR1=0;
                    Start=1;
                    Stop=0;
                    lcd_pos(0x40);
                    lcd_wdat('*');
                    lcd_pos(0x4b);
                    lcd_wdat(' ');
                }
                else if(K==2)
                {
                    Start=0;
                    Stop=1;
                    lcd_pos(0x40);
                    lcd_wdat(' ');
                    lcd_pos(0x4b);
                    lcd_wdat('*');
                    K=0;
                    Delay100ms();//100MS开始播放选中的歌曲
                    ET1=1;
                    TR1=1;
                    Song(Number);
                }
            }

            else if(K_Value==1)//当处于点个界面时按下上一首按键时退出点歌界面
            {
							
							  K_Value=0;
                Singin_interface=0;//点歌界面标志位清零
                Start=0;
                Stop=0;
                Number=0;
							  flag_next_song=0;
                //先关闭定时器
                ET1=0;
                TR1=0;
                //Number=0;
                //进行主界面显示
                lcd_wcmd(0x01);
							  Delay100ms();
                //再1602上显示自定义字符							
                //显示字符的前四位
                lcd_pos (0x0c);
                for( LCD_i=0; LCD_i<4; LCD_i++)
                {
                    lcd_wdat(LCD_i);
                }
								 
                //显示自定义字符的后四位
                lcd_pos (0x4c);
                for( LCD_i=4;  LCD_i<8;  LCD_i++)
                {
                    lcd_wdat( LCD_i);
                }

                //在1602上显示自定义布局
                lcd_pos(0x00);
                lcd_word("T:");
                //温度
                lcd_pos(0x04);
                lcd_wdat(0xdF);
                lcd_wdat('C');
                //湿度
                lcd_pos(0x07);
                lcd_word("H:");
                lcd_pos(0x0b);
                lcd_wdat('%');


                lcd_pos (0x40);
                lcd_word("Sg:");
                lcd_word(Player_Number1);
                ET1=1;
                TR1=1;
								Song(Number);
            }
        }

        k = music[j][i] + 7 * music[j][i + 1] - 1;                            //第i个是音符, 第i+1个是第几个八度
        timer1h = FREQH[k];      //从数据表中读出频率数值
        timer1l = FREQL[k];      //实际上, 是定时的时间长度
        time = music[j][i + 2];   //读出时间长度数值
        i += 3;
        song();                  //发出一个音符
    }
}

Proteus电路仿真图

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44223883/article/details/103302155
今日推荐