基于51单片机与DS1302时钟模块的电子闹钟设计

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 一、设计原理
  • 1.DS1302介绍
  • 2.闹钟音乐播放原理
  • 二、程序设计
  • 1.DS1302.h
  • 2.ds1302.c
  • 3.music.h
  • 4.main.c
  • 三、电路图
  • 四、运行结果
  • 1.proteus仿真
  • 2.开发板实验
  • 五、总结
  • 六、附件

  • 提示:以下是本篇文章正文内容,下面案例可供参考

    一、设计原理

    1.DS1302介绍

    DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.0V~5.5V。该芯片采用普通32.768kHz晶振,DS1302 工作时功耗很低,保持数据和时钟信息时功率小于1mW,非常适合用于制作电子钟。
    DS1302芯片管脚和实例电路如图:


    DS1302共8个引脚,其中VCC供电口共有两个,VCC1为主供电口,VCC2为备用供电口,备用电源口可以保证DS1302在主供电断电情况下依然可以正常计时,使用过程中仅使用VCC2备用电源作为供电,可保证完整功能。
    DS1302需要与单片机交互的接口为,SCLK、I/O、RST三个,与单片机的数据交换使用I/O接口,为串行通信模式。SCLK为串行时钟输入引脚,保证数据同步传输。RST为复位口。
    DS1302命令字和对应的操纵如下图:

    DS1302向单片机返回的时间日期数值采用压缩BCD码,即用16进制数表示10进制数,比如返回55秒对应的值为0x55,在数据解算时需要按照16进制规则计算。

    2.闹钟音乐播放原理

    闹钟音乐使用无源蜂鸣器播放,基本原理为通过单片机向无源蜂鸣器输出不同频率的方波信号,无源蜂鸣器则对应播放出不同音调的声音,即播放出不同的音符。通过连续播放不同音符并控制每个音符播放的时间,可以组合成完整的音乐。
    单片机输出不同频率的方波使用定时中断实现,首先将每个音符对应的中断计时时间储储存在单片机中,通过在程序中不断改变中断的时间,可以控制单片机输出方波的频率。以此利用无源蜂鸣器播放出音乐。

    二、程序设计

    程序共包括4个文件,分别为main.c、DS1302.h、ds1302.c、music.h三个部分。其中main.c为主程序文件,主要包括lcd1602显示相关函数、可调时钟日期函数、闹钟函数;DS1302.h为ds1302.c的声明文件,声明ds1302.c中的相关函数;ds1302.c中定义了单片机与DS1302芯片通信的主要函数文件,主要包括命令输入,数据读取和输入;music.h定义了音乐播发函数,用于闹钟调用。
    以下为示例代码,完整代码免费分享,见文末。

    1.DS1302.h

    #ifndef __DS1302_H
    #define __DS1302_H
    
    void Write_Ds1302(unsigned char temp);	      //向DS1302写命令函数
    void Write_Ds1302_Byte( unsigned char address,unsigned char dat ); //用户输入的时间日期输入DS1302函数
    unsigned char Read_Ds1302_Byte( unsigned char address );    //读取DS1302时间日期函数
    #endif
    

    2.ds1302.c

    代码如下(示例):

    #include <reg52.h>
    #include <intrins.h>
    
    
    //定义引脚
    sbit SCK=P2^0;//CLK		
    sbit SDA=P2^1;//DIO		
    sbit RST = P2^2;//CE												
    
    void Write_Ds1302(unsigned  char temp) 
    {
    	unsigned char i;
    	for (i=0;i<8;i++)     	
    	{ 
    		SCK=0;			  //开传输
    		SDA=temp&0x01;	  //与0x01相与,每次只取temp最后一位发送
    		temp>>=1; 		  //temp右移位
    		SCK=1;			  //该位传输结束
    	}
    }   
    
    void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
    {
     	RST=0; _nop_();
     	SCK=0; _nop_();
     	RST=1; _nop_();  
     	Write_Ds1302(address);		//写入对应寄存器输入地址
     	Write_Ds1302(dat);			//向对应寄存器中输入数据
     	RST=0; 
    }
    
    unsigned char Read_Ds1302_Byte ( unsigned char address )
    {
     	unsigned char i,temp=0x00;
     	RST=0;	_nop_();
     	SCK=0;	_nop_();
     	RST=1;	_nop_();
     	Write_Ds1302(address);		  //写入对应寄存器读取地址
     	for (i=0;i<8;i++) 			  //串口读取
     	{		
    		SCK=0;
    		temp>>=1;				  //temp右移位
     		if(SDA)	temp|=0x80;	      //如果IO口给高电平,temp最高位置1,相当于保存IO的高电平数据
    		                          //如果IO口给低电平,temp不操作,保持0,相当于保存IO的低电平数据
     		SCK=1;
    	} 
     	RST=0;	_nop_();
     	SCK=0;	_nop_();
    	SCK=1;	_nop_();
    	SDA=0;	_nop_();
    	SDA=1;	_nop_();
    	return (temp);				  //以char类型返回temp的数据
    }
    

    3.music.h

    #ifndef __music_H
    #define __music_H
    
    #include <reg52.h>
    #include <stdio.h>
    
    sbit beep = P2^3;
    sbit key1=P1^0;
    
    unsigned char timer0h, timer0l, time;
    
    //设置好高低音对应的频率
    code unsigned char high_v[] = {
        0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC,//低音1234567
        0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE,//中音1234567 
        0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF,//高音1234567
    };
    
    code unsigned char low_v[] = {
        0x8C, 0x56, 0x22, 0x64, 0x04, 0x90, 0x0C,//低音1234567
        0x44, 0xAA, 0x08, 0x32, 0x82, 0xC8, 0x06,//中音1234567
        0x22, 0x56, 0x84, 0x9A, 0xC0, 0xE4, 0x02,//高音1234567
    };
    
    

    4.main.c

    #include<reg52.h>
    #include "ds1302.h"
    #include "music.h"
    
    typedef unsigned char u8;
    typedef unsigned char u16;
    
    sbit lcdrs=P2^6;    //定义LCD寄存器选择位。高电平时选择数据位寄存器,低电平时选择指令寄存器
    sbit lcdrw=P2^5;	//定义LCD读写信号位。高电平时读操作,低电平时写操作。
    sbit lcden=P2^7;	//定义LCD使能端
    sbit k1=P1^0;
    sbit k2=P1^1;
    sbit k3=P1^2;
    sbit sound=P2^3;
    
    void ds1302_init();
    void ds1302_read();
    void diplay();
    void delay(unsigned int x);
    void delay_ms(unsigned int n);
    void control();
    void time_alter();
    void alarm_alter();
    void lcdwritecmd (unsigned char cmd);	       //用来给LCD输入指令
    void lcdwritedata(unsigned char dat);		       //用来给LCD输入要显示的数据
    void clear();
    void lcdinit();
    void showstring(unsigned char b[]);
    void delay_ms(unsigned int n);
    void alarm_sound();
    
    u8 code read_addr[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; 
    u8 code write_addr[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
    u8 code number[] = "0123456789:. ";
    unsigned char code low[10] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};
    unsigned char code high[10] = {0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90};
    
    //01秒02分03时 4日 5月 周6 07年
    u8 timer[]={0x00,0x00,0x00,0x04,0x05,0x06,0x07};
    //闹钟设置10秒00分00时 音乐2
    u8 alarms[]={0x10,0x00,0x00,0x04};
    unsigned int choose;
    

    三、电路图


    四、运行结果

    1.proteus仿真

    Lcd1602正确显示时间日期,测试CONTROL、K1、K2按钮,所有功能正常。proteus中使用发光二极管D1代表实际开发版上发声元件,当闹钟开始时,蜂鸣器播放选择的音乐,lcd1602显示“alarm!!!”字样,按下CONTROL自动结束闹钟,回到正常显示,同时闹钟不消除,下次同一时间继续响应闹钟。
    时间日期显示:

    响应闹钟:

    2.开发板实验

    将程序下载到开发版,依照上述电路图正确连线,lcd1602正常显示时间日期,闹钟正常响应,蜂鸣器播放设定的音乐。所有现象与proteus仿真一致。

    五、总结

    编译过程中,因为在程序中定义了大量的变量,使得变量所需存储空间一度超出了单片机允许的128字节data,查询相关资料后可知,对于那些仅在程序中读取而不需要更改的变量,可以使用code、xdata数据类型,保存在单片机的其他储存空间之中,可以很好地解决变量溢出的问题。

    注意:在proteus仿真或者开发板实验的时候,如果遇到按键响应过快的问题(即按下一次按键后,单片机判断按键被按下多次),可以尝试更改代码中按键后的延时时间实现。例如下图画红线位置:

    六、附件

    1.DS.uvproj(Keil项目文件,以下为项目下包括文件)
    main.c
    ds1302.h
    ds1302.c
    music.h
    2.clock.pdsprj(proteus仿真项目文件)

    下载地址:基于51单片机、DS1302时钟模块的电子闹钟设计.rar

    物联沃分享整理
    物联沃-IOTWORD物联网 » 基于51单片机与DS1302时钟模块的电子闹钟设计

    发表评论