一、实验现象
通过DS1302 涓流充电时钟芯片,在数码管上显示电子时钟时分秒,格式为“XX-XX-XX”
二、核心知识点 - DS1302时序
三、项目结构
main.c
/**************************************************************************************
实验名称:DS1302时钟实验
接线说明:
实验现象:下载程序后,数码管上显示电子时钟时分秒,格式为“XX-XX-XX”
注意事项:
***************************************************************************************/
#include "public.h"
#include "smg.h"
#include "ds1302.h"/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{ u8 time_buf[8];//启动涓流充电 (预留,目前用不了)//ds1302_write_byte(0x90,0XA0); //初始化DS1302(正常第一初始化后。再次屏蔽这行代码,再次下发,如果备用电池生效,会显示初始化的时间//我这里并不能生效,显示00-00-00。不知道是什么原因,电池是3.3V的新电池)ds1302_init();while(1){ ds1302_read_time();time_buf[0]=gsmg_code[gDS1302_TIME[2]/16];time_buf[1]=gsmg_code[gDS1302_TIME[2]&0x0f];time_buf[2]=0x40;time_buf[3]=gsmg_code[gDS1302_TIME[1]/16];time_buf[4]=gsmg_code[gDS1302_TIME[1]&0x0f];time_buf[5]=0x40;time_buf[6]=gsmg_code[gDS1302_TIME[0]/16];time_buf[7]=gsmg_code[gDS1302_TIME[0]&0x0f];smg_display(time_buf,1);}
}
smg.h
#ifndef _smg_H
#define _smg_H#include "public.h"#define SMG_A_DP_PORT P0 //使用宏定义数码管段码口//定义数码管位选信号控制脚
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;extern u8 gsmg_code[17];void smg_display(u8 dat[],u8 pos);#endif
smg.c
#include "smg.h"//共阴极数码管显示0~F的段码数据
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};/*******************************************************************************
* 函 数 名 : smg_display
* 函数功能 : 动态数码管显示
* 输 入 : dat:要显示的数据pos:从左开始第几个位置开始显示,范围1-8
* 输 出 : 无
*******************************************************************************/
void smg_display(u8 dat[],u8 pos)
{u8 i=0;u8 pos_temp=pos-1;for(i=pos_temp;i<8;i++){switch(7-i)//位选{case 0: LSC=1;LSB=1;LSA=1;break;case 1: LSC=1;LSB=1;LSA=0;break;case 2: LSC=1;LSB=0;LSA=1;break;case 3: LSC=1;LSB=0;LSA=0;break;case 4: LSC=0;LSB=1;LSA=1;break;case 5: LSC=0;LSB=1;LSA=0;break;case 6: LSC=0;LSB=0;LSA=1;break;case 7: LSC=0;LSB=0;LSA=0;break;}SMG_A_DP_PORT=dat[i-pos_temp];//传送段选数据delay_10us(100);//延时一段时间,等待显示稳定SMG_A_DP_PORT=0x00;//消音}
}
ds1302.h
#ifndef _ds1302_H
#define _ds1302_H#include "public.h"//管脚定义
sbit DS1302_RST=P3^4;//复位管脚
sbit DS1302_IO=P3^5;//数据管脚
sbit DS1302_CLK=P3^6;//时钟管脚//变量声明
extern u8 gDS1302_TIME[7];//存储时间//函数声明
void ds1302_init(void);
void ds1302_read_time(void);void ds1302_write_byte(u8 addr,u8 dat);#endif
ds1302.c
#include "ds1302.h"
#include "intrins.h"//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
u8 gREAD_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
u8 gWRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};//---DS1302时钟初始化2025年1月11日星期四15点30分19秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
u8 gDS1302_TIME[7] = {0x19, 0x30, 0x15, 0x11, 0x01, 0x01, 0x25};/*******************************************************************************
* 函 数 名 : ds1302_write_byte
* 函数功能 : DS1302写单字节
* 输 入 : addr:地址/命令dat:数据
* 输 出 : 无
*******************************************************************************/
void ds1302_write_byte(u8 addr,u8 dat)
{u8 i=0;DS1302_RST=0;_nop_(); DS1302_CLK=0;//CLK低电平_nop_();DS1302_RST=1;//RST由低到高变化_nop_();for(i=0;i<8;i++)//循环8次,每次写1位,先写低位再写高位{DS1302_IO=addr&0x01;addr>>=1;DS1302_CLK=1;_nop_();DS1302_CLK=0;//CLK由低到高产生一个上升沿,从而写入数据_nop_(); }for(i=0;i<8;i++)//循环8次,每次写1位,先写低位再写高位{DS1302_IO=dat&0x01;dat>>=1;DS1302_CLK=1;_nop_();DS1302_CLK=0;_nop_(); }DS1302_RST=0;//RST拉低_nop_();
}/*******************************************************************************
* 函 数 名 : ds1302_read_byte
* 函数功能 : DS1302读单字节
* 输 入 : addr:地址/命令
* 输 出 : 读取的数据
*******************************************************************************/
u8 ds1302_read_byte(u8 addr)
{u8 i=0;u8 temp=0;u8 value=0;DS1302_RST=0;_nop_(); DS1302_CLK=0;//CLK低电平_nop_();DS1302_RST=1;//RST由低到高变化_nop_();for(i=0;i<8;i++)//循环8次,每次写1位,先写低位再写高位{DS1302_IO=addr&0x01;addr>>=1; DS1302_CLK=1;_nop_();DS1302_CLK=0;//CLK由低到高产生一个上升沿,从而写入数据_nop_(); }for(i=0;i<8;i++)//循环8次,每次读1位,先读低位再读高位{temp=DS1302_IO;value=(temp<<7)|(value>>1);//先将value右移1位,然后temp左移7位,最后或运算DS1302_CLK=1;_nop_();DS1302_CLK=0;_nop_(); }DS1302_RST=0;//RST拉低_nop_(); DS1302_CLK=1;//对于实物中,P3.4口没有外接上拉电阻的,此处代码需要添加,使数据口有一个上升沿脉冲。_nop_();DS1302_IO = 0;_nop_();DS1302_IO = 1;_nop_(); return value;
}/*******************************************************************************
* 函 数 名 : ds1302_init
* 函数功能 : DS1302初始化时间
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void ds1302_init(void)
{u8 i=0;ds1302_write_byte(0x8E,0X00);for(i=0;i<7;i++){ds1302_write_byte(gWRITE_RTC_ADDR[i],gDS1302_TIME[i]); }ds1302_write_byte(0x8E,0X80);
}/*******************************************************************************
* 函 数 名 : ds1302_read_time
* 函数功能 : DS1302读取时间
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void ds1302_read_time(void)
{u8 i=0;for(i=0;i<7;i++){gDS1302_TIME[i]=ds1302_read_byte(gREAD_RTC_ADDR[i]); }
}
public.h
#ifndef _public_H
#define _public_H#include "reg52.h"typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;void delay_10us(u16 ten_us);
void delay_ms(u16 ms);#endif
public.c
#include "public.h"/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{while(ten_us--);
}/*******************************************************************************
* 函 数 名 : delay_ms
* 函数功能 : ms延时函数,ms=1时,大约延时1ms
* 输 入 : ms:ms延时时间
* 输 出 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{u16 i,j;for(i=ms;i>0;i--)for(j=110;j>0;j--);
}
四、涓流充电、后备电池(实验失败,谁成功的求留言)
①涓流充电、后备电池应该是两回事,后备电池不生效,不知道是什么原因。电池是新电池3.2V
②普中官方说,不需要外接二极管,也不需要配置0x90。后备电池也生效。
③涓流充电寄存器
此寄存器控制DS1302的涓流充电特性.图5的简化结构图显示了涓流充电器的基本元件. 涓流充电选择(TCS) 位(位4到 位 7)控制涓流充电器的选择.为了防止意外使能,只有1010的模式才能使涓流充电器使能. 所有其他模式都会禁止涓流充电器. DS1302加电时涓流充电器是禁止的. 二极管选择(DS)位 (位 2和位 3) 选择VCC2和VCC1之间连了一个还是两个二极管. 如果DS 是01,一个二极管,10就是2个二极管. 如果DS是00或者11,不管TCS,涓流充电器被禁止. RS 位(位 0 和位1)选择连在VCC2 和 VCC1之间的电阻. 表2显示了RS和DS选择电阻和二极管.