📄 clock.c
字号:
#include<reg52.h>
#include<string.h>
#define uchar unsigned char
#define uint unsigned int
sbit rs=P1^0;
sbit rw=P1^1;
sbit lcden=P1^2;
sbit sclk=P3^7;
sbit io=P3^5;
sbit rst=P3^6;
void delay(uint z)
{
uint x;
for(;z>0;z--)
for(x=10;x>0;x--)
;
}
void write_com(uchar command)
{
lcden=0;
rs=0;
rw=0;
P0=command;
lcden=1;
delay(1);
lcden=0;
}
void write_data(uchar date)
{
lcden=0;
rs=1;
rw=0;
P0=date;
lcden=1;
delay(1);
lcden=0;
}
void init()
{
write_com(0x38);
write_com(0x0c);
write_com(0x06);
}
/*****************************************
函数名称:write_byte
功能:向DS1302写入一个字节数据(无RST操作)
参数:byte 要写入数据
返回值:无
*****************************************/
void write_byte(uchar byte)
{
uchar i; //8位数据计数
for(i=0;i<8;i++)
{
sclk=0; //拉低时钟信号
io=byte&0x01; //给数据最低位
delay(1); //调整时钟和脉冲宽度
sclk=1; //提供时钟上升沿
byte=byte>>1; //数据右移一位,为送出新数据做准备
}
}
uchar read_byte(void) //读一个字节
{
uchar i,byte=0;
for(i=0;i<8;i++)
{
byte>>=1; //保存输出数据
sclk=1; //时钟是高电平
delay(1); //延时,调整时钟脉冲宽度
sclk=0; //时钟下降沿,准备读数据位
delay(1);
if(io==1) //读出数据位为1,给最高位置1
byte=byte|0x80;
if(io==0) //读出数据位为0,给最高位置0
byte=byte&0x7f;
}
return byte; //返回读出数据
}
void write_D(uchar addr,uchar date) //向某个地址写入一个字节的数据
{
rst=0; //拉低片选端
sclk=0; //拉低时钟端
delay(1);
rst=1; //拉高片选端
delay(1);
write_byte(addr); //写入操作命令(地址)
delay(1);
sclk=0; //拉低时钟端端
delay(1);
write_byte(date); //写入数据
sclk=0; //拉低时钟端
delay(1);
rst=0; //拉低片选端
}
/*uchar read_D(uchar addr) //在某地址读一个字节数据
{
uchar date;
rst=0; //拉低片选端
sclk=0; //拉低时钟端
delay(1);
rst=1; //拉高片选端
delay(1);
write_byte(addr); //写入操作命令(地址)
delay(1);
date=read_byte; //读出数据
delay(1);
sclk=0; //拉低时钟端
rst=0; //拉低片选端
return date; //返回读出数据
}*/
void set_time(uchar ptime[]) //设置时间
{
uchar i;
uchar addr=0x80;
write_D(0x8e|0x00,0x00); //写入控制命令,WP为0,允许写操作
delay(200); //稍长延时
for(i=0;i<7;i++)
{
write_D(addr|0x00,ptime[i]); //写入秒 分 时 日 月 星期 年
addr=addr+2; //地址加2
delay(10);
}
write_D(0x8e|0x00,0x80); //写控制命令,WP为1
}
void get_time(uchar time[]) //读取当前时间
{
uchar i;
/****************************************
//单次读写
uchar addr=0x80;
for(i=0;i<7;i++)
{
time[i]=read_D(addr|0x00); //秒 分 时 日 月 星期 年
addr=addr+2;
}
*******************************************/
//多字节读取
rst=0; //拉低片选
delay(1);
rst=1; //拉高片选
delay(1);
write_byte(0xbf); //写入时钟多字节读取命令 0xbf
for (i=0;i<8;i++) //时间数据的存放格式是:
{ //秒,分,时,日,月,星期,年,控制
time[i]=read_byte(); //【7个数据(BCD格式)+1个控制】
}
rst=0; //拉低片选
//
sclk=0; //拉低时钟端
}
void DS_init() //初始化DS1302
{
write_D(0x8e|0x00,0x00); //写入写允许命令
write_D(0x80|0x00,0x00); //启动振荡器,DS1302开始工作
write_D(0x8e|0x00,0x80); //写控制命令,不允许写操作
}
void bcd_asc(uchar bcd,uchar pasc[])
{
pasc[0]=bcd/16|0x30; //转换十位
pasc[1]=bcd&0x0f|0x30; //转换个位
}
void disp(uchar time[])
{
uchar i,asc[2];
uchar line1[11]={0,0,'-',0,0,'-',0,0,' ',0,'\0'};//显示第1行的字符数组
uchar line2[9]={0,0,':',0,0,':',0,0,'\0'}; //显示第2行的字符数组
for(i=0;i<3;i++) //
{
bcd_asc(time[2-i],asc);
line2[i*3]=asc[0];
line2[i*3+1]=asc[1];
}
bcd_asc(time[6],asc);
line1[0]=asc[0];
line1[1]=asc[1];
bcd_asc(time[4],asc); //为第1行的月赋值
line1[3]=asc[0];
line1[4]=asc[1];
bcd_asc(time[3],asc); //为第1行的日赋值
line1[6]=asc[0];
line1[7]=asc[1];
bcd_asc(time[5],asc); //为第1行的星期赋值
line1[9]=asc[1];
write_com(0x80+0x01);
for(i=0;i<strlen(line1);i++)
{
write_data(line1[i]);
} //显示第一行
write_com(0x80+0x44);
for(i=0;i<strlen(line2);i++)
{
write_data(line2[i]);
} //显示第二行
}
void main()
{
// uchar setadd,setdat,shift; //setadd指定将当前数值送入DS1302的哪个寄存器
//setdat是当前设置的数值,即被送入DS1302指定寄存器的数
//shift来实现十位和各位的设置相互独立(因为十位和个位是在一个寄存器里的)
//uchar dis_x,dis_y; //存储1602液晶当前光标的位置
uchar settime[7]={0x50,0x27,0x19,0x05,0x02,0x06,0x09};//设置的秒,分,时,日,月,星期,年
uchar gettime[7]={0x00,0x00,0x00,0x00,0x00,0x00,0x00};//保存当前时间的数组
// LCD1602_initial(); //初始化1602液晶
//DS1302_portinit(); //初始化DS1302的三根数据线
init();
DS_init(); //启动振荡器,DS1302开始工作
set_time(settime); //设置初始时间
while(1) //以下程序完成显示和设置时间
{
get_time(gettime); //获得当前时间
disp(gettime); //显示当前时间
}
// while(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -