老规矩先上DS1302.c的代码
#include
//首先 DS1302_Init();
// DS1302_SetTime();
//再在while中DS1302_ReadTime()
//引脚定义
sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;
//寄存器写入地址/指令定义
#define DS1302_SECOND 0x80
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_DATE 0x86
#define DS1302_MONTH 0x88
#define DS1302_DAY 0x8A
#define DS1302_YEAR 0x8C
#define DS1302_WP 0x8E
//时间数组,索引0~6分别为年、月、日、时、分、秒、星期,设置为有符号的便于<0的判断
char DS1302_Time[]={19,11,16,12,59,55,6};
/**
* @brief DS1302初始化
* @param 无
* @retval 无
*/
void DS1302_Init(void)
{
DS1302_CE=0;
DS1302_SCLK=0;
}
/**
* @brief DS1302写一个字节
* @param Command 命令字/地址
* @param Data 要写入的数据
* @retval 无
*/
void DS1302_WriteByte(unsigned char Command,Data)
{
unsigned char i;
DS1302_CE=1;
for(i=0;i<8;i++)
{
DS1302_IO=Command&(0x01<
接下来是DS1302.h的文件
#ifndef __DS1302_H__
#define __DS1302_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);
#endif
使用方法是
#include
#include "DS1302.h"
#include "LCD1602.h"
int m=0;
void time_init(){
TMOD=0x01;//0000 0001 16位定时
TH0=0x3C; // 65535-50000=15535 15535/256
TL0=0XAF; //15535%256
TR0=1;//TIM0 开
TF0=0;//中断标志位,
ET0=1;//打开TIM0定时器中断
EA=1;//打开中断的总开关
}
void main () {
LCD_Init();
time_init();
DS1302_Init();
DS1302_SetTime();
while(1){
DS1302_ReadTime();
LCD_ShowString(1,1,"time:");
// 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);
}
}
void time_limit() interrupt 1{
TH0=0x3C; // 65535-50000=15535 15535/256(为了防止被打断特地调的定时器)
TL0=0XAF; //15535%256+1
m++;
if(m==20){
DS1302_Time[5]++;
if(DS1302_Time[5]==61){
DS1302_Time[4]++;
DS1302_Time[5]=0;
}
if(DS1302_Time[4]==61){
DS1302_Time[3]++;
DS1302_Time[4]=0;
}
m=0;
}
}
时钟操作可通过 AM/PM 指示决定采用 24 或 12 小时格式。
DS1302 与 单片机之间能简单地采用同步串行的方式进行通信,仅需用到三根通信线:
①RES 复位
②I/O 数据线
③SCLK 串行时钟
1,VCC2:主电源引脚
2,X1、X2:DS1302 外部晶振引脚,通常需外接 32.768K 晶振
3,GND:电源地
4,CE:使能引脚,也是复位引脚(新版本功能变)。
5,I/O:串行数据引脚,数据输出或者输入都从这个引脚
6,SCLK:串行时钟引脚
7,VCC1:备用电源
控制寄存器用于存放 DS1302 的控制命令字,DS1302 的 RST 引脚回到高电平 后写入的第一个字节就为控制命令。它用于对 DS1302 读写过程进行控制,格式如下:
1、第 7 位永远都是 1;
2、第 6 位,1 表示 RAM,寻址内部存储器地址;0 表示 CK,寻址内部寄存器;
3、第 5 到第 1 位,为 RAM 或者寄存器的地址;
4、最低位,高电平表示 RD(看0下方),即下一步操作将要“读”;低电平表示 W,即 下一步操作将要“写”。(与 AT24C02类似)
定义
//引脚定义
sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;
//寄存器写入地址/指令定义
#define DS1302_SECOND 0x80
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_DATE 0x86
#define DS1302_MONTH 0x88
#define DS1302_DAY 0x8A
#define DS1302_YEAR 0x8C
#define DS1302_WP 0x8E
控制寄存器 {
寄存器名称
比如要读秒寄存器则命令为 1000 0001,反之写为 1000 0000。
}
日历/时钟寄存器
最重要的!!!:
首先是DS1302初始化:
void DS1302_Init(void)
{
DS1302_CE=0;
DS1302_SCLK=0;
}
为什么要这么写呢?
重新说一下
CE:使能引脚,也是复位引脚(新版本功能变)。
SCLK:串行时钟引脚。
I/O:串行数据引脚,数据输出或者输入都从这个引脚。
也就是说随着SCLK的高低电频的变化是可以通过I/O把数据写入或读出的
同时,如何区分是读还是写?
注意——上文改变的方法:
无论是写还是读都需要把CE拉高
通过SCLK不断变化来写入或读出:
/**
* @brief DS1302写一个字节
* @param Command 命令字/地址
* @param Data 要写入的数据
* @retval 无
*/
void DS1302_WriteByte(unsigned char Command,Data)
{
unsigned char i;
DS1302_CE=1;
for(i=0;i<8;i++)
{
DS1302_IO=Command&(0x01<
/**
* @brief DS1302读一个字节
* @param Command 命令字/地址
* @retval 读出的数据
*/
unsigned char DS1302_ReadByte(unsigned char Command)
{
unsigned char i,Data=0x00;
Command|=0x01; //将指令转换为读指令
DS1302_CE=1;
for(i=0;i<8;i++)
{
DS1302_IO=Command&(0x01<
可以看到DS1302_MONTH之类的是给形参 Command的,那么如DS1302_MONTH是哪来的呢?
由于是写入所以是0(0是低电平而低电平是写入);
——————————————————————————————————————————
同时 我非常疑惑
这个到底是什么?
感谢一位学长为我解答。
总的来说就是通过(0x01<
1000 0001&0000 0001 发送1,移位后 1000 0001&0000 0010发送0;以此类推,最后全部输入或输出。
注意!ds1302的输入/出为BCD码。
void DS1302_SetTime(void)
{
DS1302_WriteByte(DS1302_WP,0x00);
DS1302_WriteByte(DS1302_YEAR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);//十进制转BCD码后写入
DS1302_WriteByte(DS1302_MONTH,DS1302_Time[1]/10*16+DS1302_Time[1]%10);
DS1302_WriteByte(DS1302_DATE,DS1302_Time[2]/10*16+DS1302_Time[2]%10);
DS1302_WriteByte(DS1302_HOUR,DS1302_Time[3]/10*16+DS1302_Time[3]%10);
DS1302_WriteByte(DS1302_MINUTE,DS1302_Time[4]/10*16+DS1302_Time[4]%10);
DS1302_WriteByte(DS1302_SECOND,DS1302_Time[5]/10*16+DS1302_Time[5]%10);
DS1302_WriteByte(DS1302_DAY,DS1302_Time[6]/10*16+DS1302_Time[6]%10);
DS1302_WriteByte(DS1302_WP,0x80);
}
void DS1302_ReadTime(void)
{
unsigned char Temp;
Temp=DS1302_ReadByte(DS1302_YEAR);
DS1302_Time[0]=Temp/16*10+Temp%16;//BCD码转十进制后读取
Temp=DS1302_ReadByte(DS1302_MONTH);
DS1302_Time[1]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_DATE);
DS1302_Time[2]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_HOUR);
DS1302_Time[3]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_MINUTE);
DS1302_Time[4]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_SECOND);
DS1302_Time[5]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_DAY);
DS1302_Time[6]=Temp/16*10+Temp%16;
}
需要讲BCD转为10进制(因为我们看的就是十进制)
十进制数=低四位+高四位*10;
四位即1111(举例也可以是别的);1111是二进制和为16;由于需要高低4位,所以
高四位=BCD数/16;低四位=BCD数%16
A|=B表示A=A|B,如A=0010110x,B=00000001,则执行结果为A=00101101,也就是说A |= B是给B中为1的位对应于A的同样位上置1,A的其他位不变
补充
这个和我当时看的定时器非常像
大一萌新,望海涵