DS1302.c
#include "DS1302.h"
//引脚定义
sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;
//寄存器写入地址/指令定义
#define DS1302_miao 0x80
#define DS1302_feng 0x82
#define DS1302_shi 0x84
#define DS1302_ri 0x86
#define DS1302_yue 0x88
#define DS1302_xingqi 0x8A
#define DS1302_nian 0x8C
#define DS1302_WP 0x8E //写保护
//时间数组,索引0~6分别为年、月、日、时、分、秒、星期,设置为有符号的便于<0的判断
char DS1302_Time[]={19,11,16,22,56,0,6};
void DS1302_Init(void) //DS1302初始化
{
DS1302_CE=0;
DS1302_SCLK=0;
}
void DS1302_WriteByte(unsigned char Command,Data) //DS1302写一个字节 Command 命令字/地址 Data 要写入的数据
{
unsigned char i;
DS1302_CE=1; //CE时钟高开始写数据
for(i=0;i<8;i++) //写命令
{
// DS1302_IO=Command&(0x01<<i); //最低位开始写
DS1302_IO=Command&0x01; //读数据
Command >>= 1;
DS1302_SCLK=1; //SCLK高写数据
DS1302_SCLK=0;
}
for(i=0;i<8;i++) //写数据
{
DS1302_IO=Data&(0x01<<i); //最低位开始写
// DS1302_IO=Data&0x01; //读数据
// Data >>= 1;
DS1302_SCLK=1; //SCLK高写数据
DS1302_SCLK=0;
}
DS1302_CE=0; //写完释放时钟CE置零
}
unsigned char DS1302_ReadByte(unsigned char Command) //DS1302读一个字节 Command 命令字/地址
{
unsigned char i,Data=0x00;
Command|=0x01; //将指令转换为读指令
DS1302_CE=1; //CE时钟高开始读数据a
for(i=0;i<8;i++) //读命令
{
DS1302_IO=Command&(0x01<<i); //读数据
// DS1302_IO=Command&0x01; //读数据
// Command >>= 1;
DS1302_SCLK=0;
DS1302_SCLK=1; //SCLK高写数据
}
for(i=0;i<8;i++) //读数据
{
DS1302_SCLK=1;
DS1302_SCLK=0; //SCLK读数据
if(DS1302_IO){Data|=(0x01<<i);} //{Data=Data|(0x01<<i);} 读出端口是1就置1
// Data>>=1;
// if(DS1302_IO){Data|=0x80;} //{Data=Data|(0x01<<i);} 读出端口是1就置1
}
DS1302_CE=0; //读完释放时钟CE置零
DS1302_IO=0; //读取后将IO设置为0,否则读出的数据会出错
return Data;
}
uchar dat_to_BCD(uchar dat)//数据转BCD码
{
uchar dat1,dat2;
dat1 = dat / 10;
dat2 = dat % 10;
dat2 = dat2 + dat1 * 16;
return dat2;
}
uchar BDD_to_dat(uchar dat)//BCD码转数据
{
uchar dat1,dat2;
dat1 = dat /16;
dat2 = dat % 16;
dat2 = dat2 + dat1 * 10;
return dat2;
}
void DS1302_SetTime(void) //十进制转BCD码后写入DS1302中
{
DS1302_WriteByte(DS1302_WP,0x00); //WP=0 写操作
DS1302_WriteByte(DS1302_nian,dat_to_BCD(DS1302_Time[0]));//年
DS1302_WriteByte(DS1302_yue,dat_to_BCD(DS1302_Time[1])); //月
DS1302_WriteByte(DS1302_ri ,dat_to_BCD(DS1302_Time[2]));//日
DS1302_WriteByte(DS1302_shi ,dat_to_BCD(DS1302_Time[3]));//时
DS1302_WriteByte(DS1302_feng,dat_to_BCD(DS1302_Time[4]));//分
DS1302_WriteByte(DS1302_miao,dat_to_BCD(DS1302_Time[5]));//秒
DS1302_WriteByte(DS1302_xingqi,dat_to_BCD(DS1302_Time[6]));//星期
DS1302_WriteByte(DS1302_WP,0x80); //WP=0x80打开写保护功能
}
void DS1302_ReadTime(void) //BCD码转十进制后保存到数组准备读取
{
DS1302_Time[0]=BDD_to_dat(DS1302_ReadByte(DS1302_nian));
DS1302_Time[1]=BDD_to_dat(DS1302_ReadByte(DS1302_yue));
DS1302_Time[2]=BDD_to_dat(DS1302_ReadByte(DS1302_ri));
DS1302_Time[3]=BDD_to_dat(DS1302_ReadByte(DS1302_shi));
DS1302_Time[4]=BDD_to_dat(DS1302_ReadByte(DS1302_feng));
DS1302_Time[5]=BDD_to_dat(DS1302_ReadByte(DS1302_miao));
DS1302_Time[6]=BDD_to_dat(DS1302_ReadByte(DS1302_xingqi));
}
DS1302.h
#include "system.h"
//外部可调用时间数组,索引0~6分别为年、月、日、时、分、秒、星期,设置为有符号的便于<0的判断
extern char DS1302_Time[];
void DS1302_Init(void);
void DS1302_WriteByte(unsigned char Command,Data);
unsigned char DS1302_ReadByte(unsigned char Command);
void DS1302_SetTime(void);
void DS1302_ReadTime(void);
uchar dat_to_BCD(uchar dat);//数据转BCD码
uchar BDD_to_dat(uchar dat);//BCD码转数据
//void DS1302_WriteByte(unsigned char addr,dat); //向DS1302 命令(地址+数据);
#endif
smg.c
#include "smg.h"
#include "DS1302.h"
#include "led.h"
#include "key.h"
uchar code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值
uchar DisplayData[8]; //定义8位数组
int x=0,y=0; //段选数码管赋值给x,y,x表示列,y表示行
uchar num;
uchar key,wei;
void DigDisplay() //数码管显示位选
{
// uchar i; //位选变量
// for(i=0;i<8;i++)
// {
// switch(i) //位选,选择点亮的数码管,
// {
// case(0):
// LSA=1;LSB=1;LSC=1; break;//显示第7位
// case(1):
// LSA=0;LSB=1;LSC=1; break;//显示第6位
// case(2):
// LSA=1;LSB=0;LSC=1; break;//显示第5位
// case(3):
// LSA=0;LSB=0;LSC=1; break;//显示第4位
// case(4):
// LSA=1;LSB=1;LSC=0; break;//显示第3位
// case(5):
// LSA=0;LSB=1;LSC=0; break;//显示第2位
// case(6):
// LSA=1;LSB=0;LSC=0; break;//显示第1位
// case(7):
// LSA=0;LSB=0;LSC=0; break;//显示第0位
// }
// P0=DisplayData[i];//发送段码
// Delay_us(100); //间隔一段时间扫描
// P0=0x00;//消隐
// }
static uchar i;
P0=0x00;//消隐
switch(i) //位选,选择点亮的数码管,
{
case(0):
LSA=1;LSB=1;LSC=1; P0=DisplayData[0];break;//显示第0位
case(1):
LSA=0;LSB=1;LSC=1; P0=DisplayData[1];break;//显示第1位
case(2):
LSA=1;LSB=0;LSC=1; P0=DisplayData[2];break;//显示第2位
case(3):
LSA=0;LSB=0;LSC=1; P0=DisplayData[3];break;//显示第3位
case(4):
LSA=1;LSB=1;LSC=0; P0=DisplayData[4];break;//显示第4位
case(5):
LSA=0;LSB=1;LSC=0; P0=DisplayData[5];break;//显示第5位
case(6):
LSA=1;LSB=0;LSC=0; P0=DisplayData[6];break;//显示第6位
case(7):
LSA=0;LSB=0;LSC=0; P0=DisplayData[7];break;//显示第7位
}
i++; //
if(i>7){i=0;}
}
void TimeShow(void)//时间显示功能
{
DS1302_ReadTime();//读取时间
DisplayData[0] = smgduan[DS1302_Time[3]/10]; //时
DisplayData[1] = smgduan[DS1302_Time[3]%10]; //时
DisplayData[2] = 0x40;
DisplayData[3] = smgduan[DS1302_Time[4]/10]; //分
DisplayData[4] = smgduan[DS1302_Time[4]%10]; //分
DisplayData[5] = 0x40;
DisplayData[6] = smgduan[DS1302_Time[5]/10]; //秒
DisplayData[7] = smgduan[DS1302_Time[5]%10]; //秒
}
void key_xs ()
{
if(key==2) //设置选择位加1
{
wei++;//设置选择位加1
wei%=3;//位选越界清零
//显示
DisplayData[0] = smgduan[DS1302_Time[3]/10]; //时
DisplayData[1] = smgduan[DS1302_Time[3]%10]; //时
DisplayData[3] = smgduan[DS1302_Time[4]/10]; //分
DisplayData[4] = smgduan[DS1302_Time[4]%10]; //分
DisplayData[6] = smgduan[DS1302_Time[5]/10]; //时
DisplayData[7] = smgduan[DS1302_Time[5]%10]; //秒
}
if(key==3) //选中的位选--
{
switch(wei) //选中的位选--
{
case 0: DS1302_Time[3]++; break; //时
case 1: DS1302_Time[4]++; break; //分++
case 2: DS1302_Time[5]++; break; //秒++
}
//更新显示
DisplayData[0] = smgduan[DS1302_Time[3]/10]; //时
DisplayData[1] = smgduan[DS1302_Time[3]%10]; //时
DisplayData[3] = smgduan[DS1302_Time[4]/10]; //分
DisplayData[4] = smgduan[DS1302_Time[4]%10]; //分
DisplayData[6] = smgduan[DS1302_Time[5]/10]; //时
DisplayData[7] = smgduan[DS1302_Time[5]%10]; //秒
DS1302_SetTime(); //十进制转BCD码后写入
}
else if(key==4) //选中的位选--
{
switch(wei) //选中的位选--
{
case 0: DS1302_Time[3]--; break; //时
case 1: DS1302_Time[4]--; break; //分
case 2: DS1302_Time[5]--; break; //秒
}
//更新显示
DisplayData[0] = smgduan[DS1302_Time[3]/10]; //时
DisplayData[1] = smgduan[DS1302_Time[3]%10]; //时
DisplayData[3] = smgduan[DS1302_Time[4]/10]; //分
DisplayData[4] = smgduan[DS1302_Time[4]%10]; //分
DisplayData[6] = smgduan[DS1302_Time[5]/10]; //秒
DisplayData[7] = smgduan[DS1302_Time[5]%10]; //秒
DS1302_SetTime(); //十进制转BCD码后写入
}
//越界处理
if(DS1302_Time[5]==60){DS1302_Time[5]=0;} //秒
if(DS1302_Time[4]==60){DS1302_Time[4]=0;} //分
if(DS1302_Time[3]==24){DS1302_Time[3]=0;} //时
if(DS1302_Time[5]<0){DS1302_Time[5]=59;} //秒
if(DS1302_Time[4]<0){DS1302_Time[4]=59;} //分
if(DS1302_Time[3]<0){DS1302_Time[3]=23;} //时
}
void moshi() //模式切换
{
static uchar moshi=0; //1位设置模式,0为非设置模式
key=KeyScan(); //key=调用检测按键函数
if(key==1)
{
moshi++;
if(moshi>1){moshi=0;}
// moshi%=2;//越界清零
// moshi=moshi%2;//越界清零
}
switch(moshi)
{
case 0: TimeShow();break;//时间显示功能
case 1:key_xs ();smg_sansuo();DS1302_SetTime();break;
}
}
void smg_sansuo()
{
static uint i;
i++;
if(i==30)//250ms
{
switch(wei) //选中的位选
{
case 0: DisplayData[0] =0x00;DisplayData[1] = 0x00;break; //时
case 1: DisplayData[3] =0x00;DisplayData[4] = 0x00;break; //分
case 2: DisplayData[6] =0x00;DisplayData[7] = 0x00;break; //秒
}
}
if(i==60) //500ms
{
i=0;
switch(wei) //选中的位选
{
case 0: DisplayData[0]= smgduan[DS1302_Time[3]/10]; DisplayData[1] = smgduan[DS1302_Time[3]%10];break; //时
case 1: DisplayData[3]= smgduan[DS1302_Time[4]/10]; DisplayData[4]=smgduan[DS1302_Time[4]%10];break; //分
case 2: DisplayData[6]= smgduan[DS1302_Time[5]/10]; DisplayData[7]=smgduan[DS1302_Time[5]%10];break; //秒
}
}
}
smg.h
#include "system.h"
sbit LSA=P2^2; //数码管位选管脚
sbit LSB=P2^3;
sbit LSC=P2^4;
void TimeShow(void);//时间显示功能
void DigDisplay(); //数码管显示位选
void smg_xs (); //数码管显示显示
void key_xs ();
void smg_sansuo();
key.c
#include "key.h" //把led.h文件包含进来
#include "system.h" //把timer0.h文件包含进来
#include "led.h"
u8 KeyScan () //按键扫描函数
{
static uint timer=0;
if(k1==0)
{
timer++;
if(timer==10){return 1;} //定时10毫秒返回
else if(timer==1000){timer=500;return 1;} //否则长按不停加1
}
else if(k2==0)
{
timer++;
if(timer==10){return 2;} //定时10毫秒返回
//else if(timer==1000){timer=900;return 2;} //否则长按不停加1
else if(timer==1000){timer=500;return 2;} //否则长按不停加1
}
else if(k3==0)
{
timer++;
if(timer==10){return 3;} //定时10毫秒返回
else if(timer==1000){timer=500;return 3;} //否则长按不停加1
}
else if(k4==0)
{
timer++;
if(timer==10){return 4;} //定时10毫秒返回
else if(timer==1000){timer=500;return 4;} //否则长按不停加1
}
else
{
timer=0; //定时清0
}
return 0;
}
key.h
#include "system.h" //把timer0.h文件包含进来
sbit k1=P3^1;
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3; //定义按键端口
u8 KeyScan (); //按键扫描函数
void datapros();
main.c
#include "system.h"
#include "key.h"
#include "led.h"
#include "system.h"
#include "smg.h"
#include "DS1302.h"
extern uchar flag_1ms; //在其他模块中寻找其定义。另外,extern也可用来进行链接指定。
void main(void) //程序的主函数
{
Timer0_Init(); ////定时器0函数调用
DS1302_Init();
//
DS1302_SetTime();//设置时间
while(1) //大括号里面的东西,被不停的循环执行
{
//1ms进入一次
if(flag_1ms==1) //加了我之后,我的大括号里面的东西,被定期的1ms执行一次,反复执行
{
flag_1ms=0;
// DigDisplay(); //数码管显示位选
moshi(); //模式切换
}
}
}
system.c
#include "system.h"
#include "led.h"
#include "smg.h"
uchar flag_1ms=0;
void Timer0_Init(void)
{
TH0 = T1MS>>8; //赋初值
TL0 = T1MS; //赋初值
TMOD = 0x01; //设置定时器0用十六位定时器方式
EA = 1; //打开总中断
ET0 = 1; //打开定时器0中断
TR0 = 1; //启动定时器0
}
void Timer0() interrupt 1 //中断号1
{
TH0 = T1MS>>8; //赋初值
TL0 = T1MS; //赋初值
flag_1ms=1;
DigDisplay(); //数码管显示位选
}
system.h
#include "reg51.h"
#define uchar unsigned char //定义无符号字符
#define uint unsigned int //定义无符号整形
#define u8 unsigned char //定义无符号字符
#define u16 unsigned int //定义无符号整形
#define FOSC 12000000L //定义晶振频率
#define T1MS (65536-FOSC/12/1000) //定时1毫秒的时候,计数器要写入的值
void Delay_us(uint xus); //us级延时
void Delay_ms(uint xms); //ms级延时
void Timer0_Init(void); //定时器初始化