程序代码由3个文件组成,main.c,DS1302.c,DS1302.h。
1. main.c
/************************************************************************************* * 实验现象: 实时时间显示及调节 * 接线说明: 动态数码管段选接P0,位选接P2^2,3,4口,k1、k2、k3、k4接P3^1、0、2、3,beep接P1^5 ************************************************************************************** */ #include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器 #include "ds1302.h" typedef unsigned int u16; //对数据类型进行声明定义 typedef unsigned char u8; sbit LSA = P2 ^ 2; sbit LSB = P2 ^ 3; sbit LSC = P2 ^ 4; sbit k1 = P3 ^ 1; sbit k2 = P3 ^ 0; sbit k3 = P3 ^ 2; sbit k4 = P3 ^ 3; sbit beep = P1 ^ 5; char num = 0; u8 DisplayData[8]; u8 code smgduan[20] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, 0x00, 0x40}; //显示0~F,无,'-'的值 u8 clocks, minutes, seconds; u8 stopSwitch = 0; u8 beepSwitch = 0; /******************************************************************************* * 函 数 名 : delay() * 函数功能 : 延时函数,i=1时,大约延时10us *******************************************************************************/ void delay(u16 i) { while (i--) ; } /******************************************************************************* * 函 数 名 : DS1302WriteTime() * 函数功能 : 时分秒写入函数 * 输 入 : 时、分、秒 * 输 出 : 无 *******************************************************************************/ void DS1302WriteTime(u8 clocks, u8 minutes, u8 seconds) { u8 clocks_16, minutes_16, seconds_16; clocks_16 = (clocks / 10 * 16) | (clocks % 10); minutes_16 = (minutes / 10 * 16) | (minutes % 10); seconds_16 = (seconds / 10 * 16) | (seconds % 10); Ds1302Write(0x8E, 0X00); //禁止写保护,就是关闭写保护功能 Ds1302Write(WRITE_RTC_ADDR[2], clocks_16); Ds1302Write(WRITE_RTC_ADDR[1], minutes_16); Ds1302Write(WRITE_RTC_ADDR[0], seconds_16); Ds1302Write(0x8E, 0x80); //打开写保护功能 } /******************************************************************************* * 函 数 名 : getTime() * 函数功能 : 时间读取处理转换函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void getTime() { if (stopSwitch) { DS1302WriteTime(clocks, minutes, seconds); } else { Ds1302ReadTime(); clocks = (TIME[2] / 16 * 10) + (TIME[2] % 16); minutes = (TIME[1] / 16 * 10) + (TIME[1] % 16); seconds = (TIME[0] / 16 * 10) + (TIME[0] % 16); } } /******************************************************************************* * 函 数 名 : DigDisplay * 函数功能 : 数码管显示函数 * 参数 : ord为数码管次序,ch为该数码管显示符号 *******************************************************************************/ void DigDisplay(u8 ord, u8 ch) { switch (ord) //位选,选择点亮的数码管, { case (0): LSA = 1; LSB = 1; LSC = 1; break; //显示第0位 case (1): LSA = 0; LSB = 1; LSC = 1; break; //显示第1位 case (2): LSA = 1; LSB = 0; LSC = 1; break; //显示第2位 case (3): LSA = 0; LSB = 0; LSC = 1; break; //显示第3位 case (4): LSA = 1; LSB = 1; LSC = 0; break; //显示第4位 case (5): LSA = 0; LSB = 1; LSC = 0; break; //显示第5位 case (6): LSA = 1; LSB = 0; LSC = 0; break; //显示第6位 case (7): LSA = 0; LSB = 0; LSC = 0; break; //显示第7位 } P0 = smgduan[ch]; //发送段码 if (beepSwitch) beep = ~beep; } /******************************************************************************* * 函 数 名 : timeDisplay * 函数功能 : 将时分秒显示在数码管上 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void timeDisplay() { u8 n = 0; u8 dig[10]; getTime(); dig[0] = clocks / 10; dig[1] = clocks % 10; dig[2] = 17; dig[3] = minutes / 10; dig[4] = minutes % 10; dig[5] = 17; dig[6] = seconds / 10; dig[7] = seconds % 10; for (n = 0; n < 8; n++) { DigDisplay(n, dig[n]); delay(10); DigDisplay(n, 16); } } /******************************************************************************* * 函 数 名 : keypros * 函数功能 : 按键处理 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void keypros() { u16 delayTimes = 10; //按键K1 if (k1 == 0) //检测按键K1是否按下 { while (delayTimes--) timeDisplay(); //消除抖动 一般大约10ms if (k1 == 0) //再次判断按键是否按下 { if (++clocks == 24) { clocks = 0; } DS1302WriteTime(clocks, minutes, seconds); } while (!k1) timeDisplay(); //检测按键是否松开 } //按键K2 if (k2 == 0) //检测按键是否按下 { while (delayTimes--) timeDisplay(); //消除抖动 一般大约10ms if (k2 == 0) //再次判断按键是否按下 { if (++minutes == 60) { minutes = 0; } DS1302WriteTime(clocks, minutes, seconds); } while (!k2) timeDisplay(); //检测按键是否松开 } //按键K3 if (k3 == 0) //检测按键是否按下 { while (delayTimes--) timeDisplay(); //消除抖动 一般大约10ms if (k3 == 0) //再次判断按键是否按下 { if (++seconds == 60) { seconds = 0; } DS1302WriteTime(clocks, minutes, seconds); } while (!k3) timeDisplay(); //检测按键是否松开 } //按键K4 if (k4 == 0) //检测按键是否按下 { while (delayTimes--) timeDisplay(); //消除抖动 一般大约10ms if (k4 == 0) //再次判断按键是否按下 { stopSwitch = (stopSwitch + 1) % 2; } while (!k4) timeDisplay(); //检测按键是否松开 } } /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void main() { Ds1302Init(); //初始化 while (1) { keypros(); //按键处理 timeDisplay(); //显示时间 //蜂鸣器整点响应 if (minutes == 59 && seconds == 59) { beepSwitch = 1; } if (beepSwitch == 1) { if (minutes == 0 && seconds == 3) { beepSwitch = 0; } } } }
2. ds1302.h
#ifndef __DS1302_H_ #define __DS1302_H_ //---包含头文件---// #include<reg52.h> #include<intrins.h> //---重定义关键词---// #ifndef uchar #define uchar unsigned char #endif #ifndef uint #define uint unsigned int #endif //---定义ds1302使用的IO口---// sbit DSIO=P3^4; sbit RST=P3^5; sbit SCLK=P3^6; //---定义全局函数---// void Ds1302Write(uchar addr, uchar dat); uchar Ds1302Read(uchar addr); void Ds1302Init(); void Ds1302ReadTime(); //---加入全局变量--// extern uchar TIME[7]; //加入全局变量 extern uchar code WRITE_RTC_ADDR[7]; #endif
3. ds1302.c
#include"ds1302.h" //---DS1302写入和读取时分秒的地址命令---// //---秒分时日月周年 最低位读写位;-------// uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c}; //---DS1302时钟初始化2016年5月7日星期六12点00分00秒。---// //---存储顺序是秒分时日月周年,存储格式是用BCD码---// uchar TIME[7] = {0, 0, 0x12, 0x07, 0x05, 0x06, 0x16}; /******************************************************************************* * 函 数 名 : Ds1302Write * 函数功能 : 向DS1302命令(地址+数据) * 输 入 : addr,dat * 输 出 : 无 *******************************************************************************/ void Ds1302Write(uchar addr, uchar dat) { uchar n; RST = 0; _nop_(); SCLK = 0;//先将SCLK置低电平。 _nop_(); RST = 1; //然后将RST(CE)置高电平。 _nop_(); for (n=0; n<8; n++)//开始传送八位地址命令 { DSIO = addr & 0x01;//数据从低位开始传送 addr >>= 1; SCLK = 1;//数据在上升沿时,DS1302读取数据 _nop_(); SCLK = 0; _nop_(); } for (n=0; n<8; n++)//写入8位数据 { DSIO = dat & 0x01; dat >>= 1; SCLK = 1;//数据在上升沿时,DS1302读取数据 _nop_(); SCLK = 0; _nop_(); } RST = 0;//传送数据结束 _nop_(); } /******************************************************************************* * 函 数 名 : Ds1302Read * 函数功能 : 读取一个地址的数据 * 输 入 : addr * 输 出 : dat *******************************************************************************/ uchar Ds1302Read(uchar addr) { uchar n,dat,dat1; RST = 0; _nop_(); SCLK = 0;//先将SCLK置低电平。 _nop_(); RST = 1;//然后将RST(CE)置高电平。 _nop_(); for(n=0; n<8; n++)//开始传送八位地址命令 { DSIO = addr & 0x01;//数据从低位开始传送 addr >>= 1; SCLK = 1;//数据在上升沿时,DS1302读取数据 _nop_(); SCLK = 0;//DS1302下降沿时,放置数据 _nop_(); } _nop_(); for(n=0; n<8; n++)//读取8位数据 { dat1 = DSIO;//从最低位开始接收 dat = (dat>>1) | (dat1<<7); SCLK = 1; _nop_(); SCLK = 0;//DS1302下降沿时,放置数据 _nop_(); } RST = 0; _nop_(); //以下为DS1302复位的稳定时间,必须的。 SCLK = 1; _nop_(); DSIO = 0; _nop_(); DSIO = 1; _nop_(); return dat; } /******************************************************************************* * 函 数 名 : Ds1302Init * 函数功能 : 初始化DS1302. * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Ds1302Init() { uchar n; Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能 for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年 { Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]); } Ds1302Write(0x8E,0x80); //打开写保护功能 } /******************************************************************************* * 函 数 名 : Ds1302ReadTime * 函数功能 : 读取时钟信息 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Ds1302ReadTime() { uchar n; for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年 { TIME[n] = Ds1302Read(READ_RTC_ADDR[n]); } }