单片机之DS1302万年历实验程序

(41) 2023-12-14 21:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说单片机之DS1302万年历实验程序,希望能够帮助你!!!。

这篇文章是接上一篇《教你玩单片机之DS1302》的内容,有不明白的朋友可以进入我的主页,看我之前发的内容,不喜勿喷。

单片机之DS1302万年历实验程序_https://bianchenghao6.com/blog__第1张

万年历实验

实验效果 :1602显示时钟,按K3进入时钟设置,按K1选择设置的时分秒日月,按K2选择设置加1。

主程序

#include<reg51.h>

#include"lcd.h"

#include"ds1302.h"

sbit K1=P3^1;

sbit K2=P3^0;

sbit K3=P3^2;

sbit K4=P3^3;

void Int0Configuration();

void LcdDisplay();

unsigned char SetState,SetPlace;

void Delay10ms(void); //误差 0us

void main()

{

unsigned char i;

Int0Configuration();

LcdInit();

Ds1302Init();

while(1)

{

if(SetState==0)

{

Ds1302ReadTime();

}

else

{

if(K1==0)//检测按键K1是否按下

{

Delay10ms();//消除抖动

if(K1==0)

{

SetPlace++;

if(SetPlace>=7)

SetPlace=0;

}

while((i<50)&&(K1==0)) //检测按键是否松开

{

Delay10ms();

i++;

}

i=0;

}

if(K2==0)//检测按键K2是否按下

{

Delay10ms();//消除抖动

if(K2==0)

{

TIME[SetPlace]++;

if((TIME[SetPlace]&0x0f)>9) //换成BCD码。

{

TIME[SetPlace]=TIME[SetPlace]+6;

}

if((TIME[SetPlace]>=0x60)&&(SetPlace<2))//分秒只能到59

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x24)&&(SetPlace==2))//小时只能到23

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x32)&&(SetPlace==3))//日只能到31

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x13)&&(SetPlace==4))//月只能到12

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x7)&&(SetPlace==5))//周只能到7

{

TIME[SetPlace]=1;

}

//if(SetPlace==5)//月只能到12

//{

//TIME[SetPlace]=;

//}

}

while((i<50)&&(K2==0)) //检测按键是否松开

{

Delay10ms();

i++;

}

i=0;

}

}

LcdDisplay();

}

}

void LcdDisplay()

{

LcdWriteCom(0x80+0X40);

LcdWriteData('0'+TIME[2]/16);//时

LcdWriteData('0'+(TIME[2]&0x0f));

LcdWriteData('-');

LcdWriteData('0'+TIME[1]/16);//分

LcdWriteData('0'+(TIME[1]&0x0f));

LcdWriteData('-');

LcdWriteData('0'+TIME[0]/16);//秒

LcdWriteData('0'+(TIME[0]&0x0f));

LcdWriteCom(0x80);

LcdWriteData('2');

LcdWriteData('0');

LcdWriteData('0'+TIME[6]/16);//年

LcdWriteData('0'+(TIME[6]&0x0f));

LcdWriteData('-');

LcdWriteData('0'+TIME[4]/16);//月

LcdWriteData('0'+(TIME[4]&0x0f));

LcdWriteData('-');

LcdWriteData('0'+TIME[3]/16);//日

LcdWriteData('0'+(TIME[3]&0x0f));

LcdWriteCom(0x8D);

LcdWriteData('0'+(TIME[5]&0x07));//星期

}

void Int0Configuration()

{

//设置INT0

IT0=1;//跳变沿出发方式(下降沿)

EX0=1;//打开INT0的中断允许。

EA=1;//打开总中断

}

void Int0() interrupt 0

{

Delay10ms();

if(K3==0)

{

SetState=~SetState;

SetPlace=0;

Ds1302Init();

}

}

void Delay10ms(void) //误差 0us

{

unsigned char a,b,c;

for(c=1;c>0;c--)

for(b=38;b>0;b--)

for(a=130;a>0;a--);

}

#include"lcd.h"

#include"lcd.h"

void Lcd1602_Delay1ms(uint c) //误差 0us

{

uchar a,b;

for (; c>0; c--)

{

for (b=199;b>0;b--)

{

for(a=1;a>0;a--);

}

}

}

#ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时

void LcdWriteCom(uchar com) //写入命令

{

LCD1602_E = 0; //使能

LCD1602_RS = 0; //选择发送命令

LCD1602_RW = 0; //选择写入

LCD1602_DATAPINS = com; //放入命令

Lcd1602_Delay1ms(1);//等待数据稳定

LCD1602_E = 1; //写入时序

Lcd1602_Delay1ms(5); //保持时间

LCD1602_E = 0;

}

#else

void LcdWriteCom(uchar com) //写入命令

{

LCD1602_E = 0; //使能清零

LCD1602_RS = 0; //选择写入命令

LCD1602_RW = 0; //选择写入

LCD1602_DATAPINS = com;//由于4位的接线是接到P0口的高四位,所以传送高四位不用改

Lcd1602_Delay1ms(1);

LCD1602_E = 1; //写入时序

Lcd1602_Delay1ms(5);

LCD1602_E = 0;

//Lcd1602_Delay1ms(1);

LCD1602_DATAPINS = com << 4; //发送低四位

Lcd1602_Delay1ms(1);

LCD1602_E = 1; //写入时序

Lcd1602_Delay1ms(5);

LCD1602_E = 0;

}

#endif

#ifndef LCD1602_4PINS

void LcdWriteData(uchar dat)//写入数据

{

LCD1602_E = 0;//使能清零

LCD1602_RS = 1;//选择输入数据

LCD1602_RW = 0;//选择写入

LCD1602_DATAPINS = dat; //写入数据

Lcd1602_Delay1ms(1);

LCD1602_E = 1; //写入时序

Lcd1602_Delay1ms(5); //保持时间

LCD1602_E = 0;

}

#else

void LcdWriteData(uchar dat)//写入数据

{

LCD1602_E = 0; //使能清零

LCD1602_RS = 1; //选择写入数据

LCD1602_RW = 0; //选择写入

LCD1602_DATAPINS = dat;//由于4位的接线是接到P0口的高四位,所以传送高四位不用改

Lcd1602_Delay1ms(1);

LCD1602_E = 1; //写入时序

Lcd1602_Delay1ms(5);

LCD1602_E = 0;

LCD1602_DATAPINS = dat << 4; //写入低四位

Lcd1602_Delay1ms(1);

LCD1602_E = 1; //写入时序

Lcd1602_Delay1ms(5);

LCD1602_E = 0;

}

#endif

#ifndefLCD1602_4PINS

void LcdInit() //LCD初始化子程序

{

LcdWriteCom(0x38); //开显示

LcdWriteCom(0x0c); //开显示不显示光标

LcdWriteCom(0x06); //写一个指针加1

LcdWriteCom(0x01); //清屏

LcdWriteCom(0x80); //设置数据指针起点

}

#else

void LcdInit() //LCD初始化子程序

{

LcdWriteCom(0x32); //将8位总线转为4位总线

LcdWriteCom(0x28); //在四位线下的初始化

LcdWriteCom(0x0c); //开显示不显示光标

LcdWriteCom(0x06); //写一个指针加1

LcdWriteCom(0x01); //清屏

LcdWriteCom(0x80); //设置数据指针起点

}

#endif

#include"ds1302.h"

#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时钟初始化2013年1月1日星期二12点00分00秒。---//

//---存储顺序是秒分时日月周年,存储格式是用BCD码---//

uchar TIME[7] = {0, 0, 0x12, 0x01, 0x01, 0x02, 0x13};

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_();

}

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;

}

void Ds1302Init()

{

uchar n;

Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能

for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年

{

Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);

}

Ds1302Write(0x8E,0x80); //打开写保护功能

}

void Ds1302ReadTime()

{

uchar n;

for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年

{

TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);

}

}

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复