DS1302.c
#include "DS1302.h"
#include "lcd1602.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));
}
void TimeShow(void)//时间显示功能
{
DS1302_ReadTime();//读取时间
LCD_ShowNum(1,1,DS1302_Time[0],2);//显示年
LCD_ShowNum(1,4,DS1302_Time[1],2);//显示月
LCD_ShowNum(1,7,DS1302_Time[2],2);//显示日
LCD_ShowNum(2,1,DS1302_Time[3],2);//显示时
LCD_ShowNum(2,4,DS1302_Time[4],2);//显示分
LCD_ShowNum(2,7,DS1302_Time[5],2);//显示秒
}
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 TimeShow(void);//时间显示功能;
#endif
key.c
#include "key.h" //把led.h文件包含进来
#include "system.h" //把timer0.h文件包含进来
#include "led.h"
#include "DS1302.h"
#include "lcd1602.h"
uchar p=0;
unsigned char TimeSetSelect;
uchar flag,wei; //在其他模块中寻找其定义。另外,extern也可用来进行链接指定。
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;
}
void datapros()
{
uchar key;
key=KeyScan(); //key=调用检测按键函数
if(key==1)
{
p++;
if(p>1){p=0;}
// p%=2;//越界清零
// p=p%2;//越界清零
}
if(flag==1) //加了我之后,我的大括号里面的东西,被定期的1ms执行一次,反复执行
{
lcd_sansuo(); //lcd选中的位闪烁
if(key==2)
{
wei++;//设置选择位加1
wei%=6;//位选越界清零
LCD_ShowNum(1,1,DS1302_Time[0],2);//显示年
LCD_ShowNum(1,4,DS1302_Time[1],2);//显示月
LCD_ShowNum(1,7,DS1302_Time[2],2);//显示日
LCD_ShowNum(2,1,DS1302_Time[3],2);//显示时
LCD_ShowNum(2,4,DS1302_Time[4],2);//显示分
LCD_ShowNum(2,7,DS1302_Time[5],2);//显示秒
}
if(key==3)
{
switch(wei) //选中的位选--
{
case 0: DS1302_Time[0]++; break; //年++
case 1: DS1302_Time[1]++; break; //月++
case 2: DS1302_Time[2]++; break; //日++
case 3: DS1302_Time[3]++; break; //时++
case 4: DS1302_Time[4]++; break; //分++
case 5: DS1302_Time[5]++; break; //秒++
}
if(DS1302_Time[0]>99){DS1302_Time[0]=0;}//年越界判断
if(DS1302_Time[1]>12){DS1302_Time[1]=1;}//月越界判断
if(DS1302_Time[2]>12){DS1302_Time[2]=0;}//日越界判断
if(DS1302_Time[3]>23){DS1302_Time[3]=0;}//时越界判断
if(DS1302_Time[4]>59){DS1302_Time[4]=0;}//分越界判断
if(DS1302_Time[5]>59){DS1302_Time[5]=0;}//秒越界判断
LCD_ShowNum(1,1,DS1302_Time[0],2);//显示年
LCD_ShowNum(1,4,DS1302_Time[1],2);//显示月
LCD_ShowNum(1,7,DS1302_Time[2],2);//显示日
LCD_ShowNum(2,1,DS1302_Time[3],2);//显示时
LCD_ShowNum(2,4,DS1302_Time[4],2);//显示分
LCD_ShowNum(2,7,DS1302_Time[5],2);//显示秒
DS1302_SetTime(); //十进制转BCD码后写入
}
if(key==4)
{
switch(wei) //选中的位选--
{
case 0: DS1302_Time[0]--; break; //年++
case 1: DS1302_Time[1]--; break; //月++
case 2: DS1302_Time[2]--; break; //日++
case 3: DS1302_Time[3]--; break; //时++
case 4: DS1302_Time[4]--; break; //分++
case 5: DS1302_Time[5]--; break; //秒++
}
if(DS1302_Time[0]<0){DS1302_Time[0]=99;}//年越界判断
if(DS1302_Time[1]<1){DS1302_Time[1]=12;}//月越界判断
if(DS1302_Time[2]<0){DS1302_Time[2]=31;}//时越界判断
if(DS1302_Time[3]<0){DS1302_Time[3]=23;}//时越界判断
if(DS1302_Time[4]<0){DS1302_Time[4]=59;}//分越界判断
if(DS1302_Time[5]<0){DS1302_Time[5]=59;}//秒越界判断
LCD_ShowNum(1,1,DS1302_Time[0],2);//显示年
LCD_ShowNum(1,4,DS1302_Time[1],2);//显示月
LCD_ShowNum(1,7,DS1302_Time[2],2);//显示日
LCD_ShowNum(2,1,DS1302_Time[3],2);//显示时
LCD_ShowNum(2,4,DS1302_Time[4],2);//显示分
LCD_ShowNum(2,7,DS1302_Time[5],2);//显示秒
DS1302_SetTime(); //十进制转BCD码后写入
}
}
}
void moshi() //模式切换
{
// uchar key;
// key=KeyScan(); //key=调用检测按键函数
// if(key==1)
// {
// p++;
// if(p>1){p=0;}
//// p%=2;//越界清零
//// p=p%2;//越界清零
// }
switch(p)
{
case 0: TimeShow();flag=0; break;//时间显示功能
case 1:;flag=1;break;
}
}
void lcd_sansuo()
{
static uint i;
i++;
if(i==500)//500ms
{
switch(wei) //选中的位选
{
case 0: LCD_ShowString(1,1," "); break; //年++
case 1: LCD_ShowString(1,4," "); break; //月++
case 2: LCD_ShowString(1,7," "); break; //日++
case 3: LCD_ShowString(2,1," "); break; //时++
case 4: LCD_ShowString(2,4," "); break; //分++
case 5: LCD_ShowString(2,7," "); break; //秒++
}
}
if(i==1000) //1000ms
{
i=0;
switch(wei) //选中的位选
{
case 0: LCD_ShowNum(1,1,DS1302_Time[0],2); break; //年++
case 1: LCD_ShowNum(1,4,DS1302_Time[1],2); break; //月++
case 2: LCD_ShowNum(1,7,DS1302_Time[2],2); break; //日++
case 3: LCD_ShowNum(2,1,DS1302_Time[3],2); break; //时++
case 4: LCD_ShowNum(2,4,DS1302_Time[4],2); break; //分++
case 5: LCD_ShowNum(2,7,DS1302_Time[5],2); break; //秒++
}
}
}
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();
void moshill(); //模式切换
void lcd_sansuo(); //lcd选中的位闪烁
main.c
#include "system.h"
#include "key.h"
#include "led.h"
#include "lcd1602.h"
#include "system.h"
#include "DS1302.h"
extern uchar flag_1ms; //在其他模块中寻找其定义。另外,extern也可用来进行链接指定。
void main(void) //程序的主函数
{
Timer0_Init(); ////定时器0函数调用
LCD_Init();
DS1302_Init();
LCD_ShowString(1,1," - - ");//静态字符初始化显示
LCD_ShowString(2,1," : : ");
DS1302_SetTime();//设置时间
while(1) //大括号里面的东西,被不停的循环执行
{
//1ms进入一次
if(flag_1ms==1) //加了我之后,我的大括号里面的东西,被定期的1ms执行一次,反复执行
{
flag_1ms=0;
moshi(); // 时钟模式切换
}
}
}
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); //定时器初始化
system.c
#include "system.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;
datapros();
}
void Delay_us(uint xus)
{
for(;xus>0;xus--);
}
void Delay_ms(uint xms)
{
for(;xms>0;xms--)
{
Delay_us(1000);
}
}