我们要实现时间显示并且按s加,计时模式并且用独立按键控制两种不同模式
一、原理
在DS1302内部有时钟寄存器
就是寄存时分秒等的寄存器,就是我们需要用的
可以看到它的原理图上端链接两个vcc,左边两个分别连接晶振,一个接地,一个复位,一个与IAPF2K61S2相连,一个是时钟。
我们需要的就是通过控制其中的寄存器来得到我们需要的时分秒
二、编程
就需要给到的DS1302.c/.h了
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
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;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
在使用DS1302时我们需要先清零,之后把复位端拉高,产生时钟上升沿,最后才能读取或写入数据,一定要先读或写对应的地址,之后再读或写需要的数据。
在读取中我们需要先写对应地址,找到对应寄存器之后再读取数据。
注意:上升沿是写入,下降沿是读取
再去写设置和读取函数
在写对应时分秒时需要用到设置,先定义中间变量,之后把wp复位允许写入,之后把给定的数组里,三位分别把数分开,转换成16进制,再存入寄存器对应时分秒的位置,最后再把wp赋值1禁止写入。
读取函数,先读取寄存器里的地址,把对应数存到中间变量里,再存入数组中去。
主函数
void main()
{
Cls_Peripheral();
Timer1Init();
EA=1;
Set_Rtc(ucRtc);
while(1)
{
Key_Proc();
Seg_Proc();
LED_Proc();
}
}
void tm1_isr() interrupt 3
{
if(++Key_Slow_Down==10)Key_Slow_Down=0;//¼õËÙ
if(++Seg_Slow_Down==500)Seg_Slow_Down=0;
if(++ms_count==1000)//¼Ç¼ÔËÐÐʱ¼ä
{
s_count++;
ms_count=0;
}
Seg_Disp(seg_buf,pos);//Ë¢ÐÂÏÔʾ
if(++pos==8) pos=0;
Led_Disp(ucLed);
}
先设置,再在while里放三个进程,中断里先延迟,再进行毫秒叠加秒,显示对应数组里的数和LED灯。
void Key_Proc(void)//¾ØÕó°´¼ü´¦Àí
{
if(Key_Slow_Down)return;//¼õËÙ³ÌÐò
Key_Slow_Down=1;
Key_Value=Key_Read_BTN(); //¶ÁÈ¡°´¼ü°´ÏµıàºÅ
Key_Down=Key_Value & (Key_Old^Key_Value);//£¡ 0000^0101=0101&0101=0101,Èç¹û°´¼ü·¢ÉúϽµÑصı仯£¬Êä³ö½á¹ûºÍ±¾´Î°´¼üÊýÖµÏàͬ(ʵ¼ÊÖÐÓÐϽµÑØÌø±ä¾ÍÊÇ°´ÏÂÁ˼üÅÌ)
//£¡ 0101^0101=0000&0101=0000,Èç¹ûÒ»Ö±±£³Ö²»±ä£¬Êä³ö½á¹ûΪ0
Key_Old=Key_Value;//Key_OldΪÉÏÒ»¸ö״̬£¬Ñ»·Ò»´Î°ÑÏÂÒ»¸ö״̬¸³Öµ¸øÉÏÒ»´Î£¬ÓÃÓÚÅжÏ
if(Key_Down)//Èç¹û°´Ï¼üÅ̺󣬽«¼üÅ̶ÔÓ¦µÄÖµ¸³Öµ¸øÏÔʾ±ê־λ
{
if(++Running_State==2) Running_State=0;
}
}
void Seg_Proc(void)//ÏÔʾ´¦Àí
{
if(Seg_Slow_Down)return;//¼õËÙ³ÌÐò
Seg_Slow_Down=1;
switch(Running_State)
{
case 0:
Read_Rtc(ucRtc);
sprintf(seg_string,"%02d_%02d_%02d",(unsigned int)ucRtc[0],(unsigned int)ucRtc[1],(unsigned int)ucRtc[2]);//½«ÒªÏÔʾµÄÊýÖµ´òÓ¡µ½×Ö·û´®ÖÐ
break;
case 1:
sprintf(seg_string,"-----%03d",(unsigned int)s_count);
break;
}
Seg_Tran(seg_string,seg_buf);
}
void Led_Proc(void)
{
switch(Running_State)
{
case 0:
ucLed=0x0f;
break;
case 1:
ucLed=0xf0;
break;
}
}
led里是放入两种模式对应led的亮灭
key是放入 定义按键,设置两种状态0,1。
seg放入数码管显示根据两种状态分别显示两种状态1是设置好的时分秒,2是计数器。