【蓝桥杯省赛】如何让DS1302暂停
问题
之前复习蓝桥杯的时候,我有一个小脑洞:如何让DS1302暂停
当然比赛好像没考过这种
解题思路
以下是DS1302的部分寄存器:(此处参考小蜜蜂老师的文章)
查询资料时发现大家用的多是这一句:
Write_Ds1302_Byte(0x80,temp|0x80);
用在我的板子上暂时不可,原因不明,有大神知道的请指教
因此我改成了:
Write_Ds1302_Byte(0x80,temp&0x7f);
尝试了一下,可以完成效果
完整代码参考
实验现象:每分钟的第一秒都会暂停一段时间,然后恢复计时
ds1302.h
#ifndef __DS1302_H
#define __DS1302_H
void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat);
unsigned char Read_Ds1302_Byte ( unsigned char address );
#endif
ds1302.c
#include <reg52.h>
#include <intrins.h>
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
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);
}
main.c
#include <STC15F2K60S2.h>
#include <ds1302.h>
/*实验现象:每分钟的第一秒都会暂停一段时间,然后恢复计时*/
unsigned char code NixieTube_dat[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char code Write_Ds1302_ADD[7] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
unsigned char code Read_Ds1302_ADD[7] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
unsigned char Time[] = {0x55,0x59,0x11,0x11,0x10,0x07,0x20};
unsigned char Time_2[7] ;
void Ds1302_config()
{
unsigned char n;
Write_Ds1302_Byte(0x8e,0x00);
for(n = 0;n<7;n++)
{
Write_Ds1302_Byte(Write_Ds1302_ADD[n],Time[n]);
}
Write_Ds1302_Byte(0x8E,0x80);
}
void Ds1302_Read_dat()
{
unsigned char n;
for(n = 0;n<7;n++)
{
Time_2[n] = Read_Ds1302_Byte(Read_Ds1302_ADD[n]);
}
}
void _573_select(unsigned char channal)
{
switch(channal)
{
case 0:P2 = (P2 & 0x1f) | 0x00;break;
case 4:P2 = (P2 & 0x1f) | 0x80;break;
case 5:P2 = (P2 & 0x1f) | 0xa0;break;
case 6:P2 = (P2 & 0x1f) | 0xc0;break;
case 7:P2 = (P2 & 0x1f) | 0xe0;break;
}
}
void Sys_Init()
{
_573_select(4);
P0 = 0xff;
_573_select(0);
_573_select(5);
P0 = 0x00;
_573_select(0);
}
void NixieTube_Byte(unsigned char pos,unsigned char value)
{
P0 = 0x00;
_573_select(7);
P0 = value;
_573_select(0);
P0 = 0x00;
_573_select(6);
P0 = 0x01<<pos;
}
void Dealy(unsigned char t)
{
while(t--);
}
void NixieTube_show()
{
NixieTube_Byte(7,NixieTube_dat[Time_2[0]%16]);Dealy(100);
NixieTube_Byte(6,NixieTube_dat[(Time_2[0]&0x7f)/16]);Dealy(100);
NixieTube_Byte(5,0xbf);Dealy(100);
NixieTube_Byte(4,NixieTube_dat[Time_2[1]%16]);Dealy(100);
NixieTube_Byte(3,NixieTube_dat[Time_2[1]/16]);Dealy(100);
NixieTube_Byte(2,0xbf);Dealy(100);
NixieTube_Byte(1,NixieTube_dat[Time_2[2]%16]);Dealy(100);
NixieTube_Byte(0,NixieTube_dat[Time_2[2]/16]);Dealy(100);
NixieTube_Byte(0,0xff);
}
void Delay(unsigned int t)//在延时函数中也要显示数码管
{
while(t--)
{
NixieTube_show();
}
}
void main()
{
Sys_Init();
Ds1302_config();
while(1)
{
Ds1302_Read_dat();
NixieTube_show();
if(Time_2[0] == 0x01)
{
Write_Ds1302_Byte(0x8e,0x00);
Write_Ds1302_Byte(0x80,Time_2[0]&0x7f);//停止
Delay(10000);
Write_Ds1302_Byte(0x80,Time_2[0]+1);
Write_Ds1302_Byte(0x8e,0x80);
}
}
}