基于单片机音乐弹奏播放DS1302万年历显示及源程序

一、系统方案

1、本设计采用51单片机作为主控器。

2、DS1302计时显示年月日时分秒。

3、按键可以弹奏以及播放音乐,内置16首音乐。

二、硬件设计

原理图如下:

三、单片机软件设计

1、首先是系统初始化

/时钟显示 **/

void init_1602_ds1302()

{

write_sfm2_ds1302(1,1,shi); //显示时

write_sfm2_ds1302(1,4,fen); //显示分

write_sfm2_ds1302(1,7,miao); //显示秒

write_sfm2_ds1302(2,2,nian); //显示年

write_sfm2_ds1302(2,5,yue); //显示月

write_sfm2_ds1302(2,8,ri); //显示日

}

2、液晶显示程序

/延时函数 */

void delay_uint(uint q)

{

while(q--);

}

/lcd1602写命令函数 */

void write_com(uchar com)

{

e=0;

rs=0;

rw=0;

P0=com;

delay_uint(3);

e=1;

delay_uint(25);

e=0;

}

/lcd1602写数据函数 */

void write_data(uchar dat)

{

e=0;

rs=1;

rw=0;

P0=dat;

delay_uint(3);

e=1;

delay_uint(25);

e=0;

}

/lcd1602初始化设置 */

void init_1602() //lcd1602初始化设置

{

write_com(0x38); //

write_com(0x0c);

write_com(0x06);

}

/lcd1602上显示一位十进制数 */

void write_sfm1(uchar hang,uchar add,uchar date)

{

if(hang==1)

write_com(0x80+add);

else

write_com(0x80+0x40+add);

write_data(table_num[date % 10]);

}

/lcd1602上显示两位十进制数 */

void write_sfm2(uchar hang,uchar add,uchar date)

{

if(hang==1)

write_com(0x80+add);

else

write_com(0x80+0x40+add);

write_data(table_num[date / 10 % 10]);

write_data(table_num[date % 10]);

}

void write_sfm2_ds1302(uchar hang,uchar add,uchar date)

{

if(hang==1)

write_com(0x80+add);

else

write_com(0x80+0x40+add);

write_data(table_num[date/16]);

write_data(table_num[date%16]);

}

/lcd1602上显示这字符函数 */

void write_string(uchar hang,uchar add,uchar *p)

{

if(hang==1)

write_com(0x80+add);

else

write_com(0x80+0x40+add);

while(1)

{

if(*p == '\0') break;

write_data(*p);

p++;

}

}

/控制光标函数 ***/

void write_guanbiao(uchar hang,uchar add,uchar date)

{

if(hang==1)

write_com(0x80+add);

else

write_com(0x80+0x40+add);

if(date == 1)

write_com(0x0f); //显示光标并且闪烁

else

write_com(0x0c); //关闭光标

}

/lcd1602清除显示 */

void clear_1602()

{

write_string(1,0," ");

write_string(2,0," ");

}

/开机液晶显示函数 初始化液晶的内容 ****************/

void init_1602_dis_csf() //初始化液晶

{

write_string(1,0," : : ");

write_string(2,0,"20 - - ");

}

3、按键电路程序

void anjian() //按键键值识别

{

P1=0xf0; //P1口赋值

if((P1&0xf0)!=0xf0) //判断是否有按键按下

{

delay(); //去抖

if((P1&0xf0)!=0xf0) //再次判断有无按键按下

{

key=getkey(); //扫描按键

Tone_Index=0; //播放音符顺序清零

switch(key) //根据扫描的按键编码将k赋值

{

case 0x88: //按键编码为0x88

k = 0; //k赋值0

break; //已经确定键值后提前跳出switch

case 0x48: //如果不满足上一个case则继续向下判断,直到有符合

k = 1; //k赋值1

break; //下同,略

case 0x28:

k = 2 ;

break;

case 0x18:

k = 3 ;

break;

case 0x84:

k = 4 ;

break;

case 0x44:

k = 5 ;

break;

case 0x24:

k = 6 ;

break;

case 0x14:

k = 7 ;

break;

case 0x82:

k = 8 ;

break;

case 0x42:

k = 9 ;

break;

case 0x22:

k = 10 ;

break;

case 0x12:

k = 11 ;

break;

case 0x81:

k = 12 ;

break;

case 0x41:

k = 13 ;

break;

case 0x21:

k = 14 ;

break;

case 0x11:

k = 15 ;

break;

default : //如果以上都不符合,直接跳出,无键值输出

break;

}

}

}

}

4、核心算法程序

void main(void) //主函数

{

SPK=0;

LED1=1;

LED2=0; //开机默认弹奏模式

senddata_74595(0xc0); //数码管显示0

IE=0x87; //定义外部中断控制器

TMOD=0x01; //定义定时器0的工作方式

IT0=1; //外部中断0为下降沿触发

IT1=1; //外部中断1为下降沿触发

init_1602(); //lcd1602初始化

init_1602_dis_csf(); //lcd1602初始化显示

复制代码
while(1)						   //进入死循环
{
	read_time();		  //读时间
			init_1602_ds1302();   //显示时钟	
	
	P1=0xf0; 					   //P1口赋值
	if((P1&0xf0)!=0xf0)			   //判断P0口是否有变化
	{	
		anjian();				   //读取键值
		senddata_74595(DSY_CODE[k]);			   //显示键值,也就是显示音符
		if(FY==0)				   //如果是弹奏模式
		{
			STH0 = tab[k]/256;
			STL0 = tab[k]%256;	   //根据k的值赋初值给T0
			TR0 = 1;               //打开定时器用于定时产生频率发生     
			while ((P1&0xf0)!=0xf0); //按键不松开的话,T0就一直产生频率 
			TR0=0;                 //按键松开后关闭T0计时,频率停止 
		} 
		else  //如果是播放模式(上面的if语句不成立就执行else)
		{ 
			while (FY==1) 							 //进入播放模式
			{ 
				read_time();		  //读时间
			init_1602_ds1302();   //显示时钟
				if(Song[k][Tone_Index]==-1) 		 //一首播放完退出
				{
					Tone_Index=0;
					SPK=0;
					break; 
				}  
				STH0=(tab[Song[k][Tone_Index]])/256;
				STL0=(tab[Song[k][Tone_Index]])%256; //将内置音乐数组的数据赋给定时器做为初值计时
			//	P0=DSY_CODE[Song[k][Tone_Index]]; 	 //显示播放的音符
				TR0 = 1; 							 //打开定时器定时开关
				delay1(300*Len[k][Tone_Index]); 	 //节拍数组延时
				Tone_Index++; 						 //变量加准备播放下一个音符
				TR0=0;								 //停止定时器
				anjian();							 //扫描按键
				senddata_74595(DSY_CODE[k]);					 //显示音乐序号
				while((P1&0xf0)!=0xf0);
			}
		}
	}
}

}

四、 proteus仿真设计

Proteus软件是一款应用比较广泛的工具,它可以在没有硬件平台的基础上通过自身的软件仿真出硬件平台的运行情况,这样就可以通过软件仿真来验证我们设计的方案有没有问题,如果有问题,可以重新选择器件,连接器件,直到达到我们设定的目的,避免我们搭建实物的时候,如果当初选择的方案有问题,我们器件都已经焊接好了,再去卸载下去,再去焊接新的方案的器件,测试,这样会浪费人力和物力,也给开发者带来一定困惑,Proteus仿真软件就很好的解决这个问题,我们在设计之初,就使用该软件进行模拟仿真,测试,选择满足我们设计的最优方案。最后根据测试没问题的仿真图纸,焊接实物,调试,最终完成本设计的作品。

相关推荐
BreezeJuvenile1 小时前
外设模块学习(5)——DS18B20温度传感器(STM32)
stm32·嵌入式硬件·学习·温度传感器·ds18b20
hollq4 小时前
STM32F103RCT6+STM32CubeMX+keil5(MDK-ARM)+Flymcu实现串口重定向
arm开发·stm32·嵌入式硬件
小鱼儿电子5 小时前
17-基于STM32的宠物饲养系统设计与实现
stm32·嵌入式硬件·物联网·宠物·宠物饲养系统
小莞尔7 小时前
【51单片机】【protues仿真】基于51单片机四层电梯系统
单片机·嵌入式硬件
CFZPL7 小时前
使用江科大串口发送函数发送freertos的vTaskList出现跑飞
单片机
F133168929578 小时前
WD5030A,24V降5V,15A 大电流,应用于手机、平板、笔记本充电器
stm32·单片机·嵌入式硬件·51单片机·硬件工程·pcb工艺
易享电子9 小时前
基于单片机电器断路器保护器系统Proteus仿真(含全部资料)
单片机·嵌入式硬件·fpga开发·51单片机·proteus
爱倒腾的老唐11 小时前
01、如何学习单片机
单片机·嵌入式硬件·学习
点灯小铭11 小时前
基于单片机的夹具压力控制系统设计
单片机·嵌入式硬件·mongodb·毕业设计·课程设计
雾削木17 小时前
stm32解锁芯片
javascript·stm32·单片机·嵌入式硬件·gitee