这个实验的内容是:利用DS1302芯片,实现万年历。从DS1302芯片读取的时间数值,以滚显的方式在四位数码管上显示,并使用Proteus仿真。
具体实现方式请看下面的程序:
#include"main.h"
unsigned char DisplayData[20]; //显示时间年-周-月-日-时-分-秒
unsigned char digitvalue[4]={
0xff,0xff,0xff,0xff}; //采用共阳数码管,让四个数码管初始的时候什么也不显示
unsigned char temp;
unsigned char t;
unsigned char i;
unsigned int s;
void delay(unsigned int i){
//延时函数
while(i--);
}
//数码管段码0~9
unsigned char code smgduan[10]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
void datapros(unsigned char *TIME) //将16进制数处理成10进制
{
DisplayData[0] = smgduan[TIME[6]/16]; //年,年的十位
DisplayData[1] = smgduan[TIME[6]&0x0f]; //年的个位,下面同理
DisplayData[2] = ~(0x40); //分隔符
DisplayData[3] = smgduan[TIME[5]/16]; //周
DisplayData[4] = smgduan[TIME[5]&0x0f];
DisplayData[5] = ~(0x40);
DisplayData[6] = smgduan[TIME[4]/16]; //月
DisplayData[7] = smgduan[TIME[4]&0x0f];
DisplayData[8] = ~(0x40);
DisplayData[9] = smgduan[TIME[3]/16]; //日
DisplayData[10] = smgduan[TIME[3]&0x0f];
DisplayData[11] = ~(0x40);
DisplayData[12] = smgduan[TIME[2]/16]; //时
DisplayData[13] = smgduan[TIME[2]&0x0f];
DisplayData[14] = ~(0x40);
DisplayData[15] = smgduan[TIME[1]/16]; //分
DisplayData[16] = smgduan[TIME[1]&0x0f];
DisplayData[17] = ~(0x40);
DisplayData[18] = smgduan[TIME[0]/16]; //秒
DisplayData[19] = smgduan[TIME[0]&0x0f];
}
void DigDisplay(unsigned char *DisplayData)
{
for(t=0;t<20;t++){
//循环20次,以滚显的方式在数码管上显示时间年-周-月-日-时-分-秒,共有20个数
temp=DisplayData[t];
digitvalue[3]=digitvalue[2];
digitvalue[2]=digitvalue[1];
digitvalue[1]=digitvalue[0];
digitvalue[0]=temp;
for(s=0;s<250;s++){
//循环显示,延时一下
for(i=0;i<4;i++)
{
switch(i){
//位选,选择点亮的数码管,
case(0):
LSA=0;LSB=0;LSC=0;LSD=1; break;//显示第 0 位
case(1):
LSA=0;LSB=0;LSC=1;LSD=0; break;//显示第 1 位
case(2):
LSA=0;LSB=1;LSC=0;LSD=0; break;//显示第 2 位
case(3):
LSA=1;LSB=0;LSC=0;LSD=0; break;//显示第 3 位
}
P0=digitvalue[i];//发送数据
delay(100); //间隔一段时间扫描
P0=0xFF;//消隐
}
}
}
}
void main(){
Ds1302Init(); //DS1302芯片初始化,写入初始值
while(1){
Ds1302ReadTime(); //读取DS1302芯片的时间的值
datapros(TIME); //将16进制数处理成10进制
DigDisplay(DisplayData); //将读取到的值在数码管上显示出来
}
}
#ifndef __MAIN_H__
#define __MAIN_H__
#include"ds1302.h"
#include"timer0.h"
extern unsigned char TIME[7];
sbit LSA=P1^3;
sbit LSB=P1^2;
sbit LSC=P1^1;
sbit LSD=P1^0;
#endif
#include"ds1302.h"
//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
unsigned char code READ_RTC_ADDR[7] = {
0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
unsigned char code WRITE_RTC_ADDR[7] = {
0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
unsigned char TIME[7] = {
0x00, 0x00, 0x12, 0x09, 0x12, 0x07, 0x19}; //初始化的时间,秒 分 时 日 月 周 年
//下面要用到SPI总线的时序来发送和接收数据
void Ds1302Write(unsigned char addr, unsigned char dat) //要给函数传入地址和数据
{
unsigned char n;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1; //然后将RST置高电平。
_nop_();
for (n=0; n<8; n++)//开始传送八位地址命令
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
for (n=0; n<8; n++)//写入8位数据
{
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
RST = 0;//传送数据结束
_nop_();
}
unsigned char Ds1302Read(unsigned char addr)
{
unsigned char n,dat,dat1;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1;//然后将RST置高电平。
_nop_();
for(n=0; n<8; n++)//开始传送八位地址命令
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
_nop_();
for(n=0; n<8; n++)//读取8位数据
{
dat1 = DSIO;//从最低位开始接收
dat = (dat>>1) | (dat1<<7);
SCLK = 1;
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
RST = 0;
_nop_(); //以下为DS1302复位的稳定时间,必须的。
SCLK = 1;
_nop_();
DSIO = 0;
_nop_();
DSIO = 1;
_nop_();
return dat;
}
void Ds1302Init()
{
unsigned char n;
Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能
for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
{
Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
}
Ds1302Write(0x8E,0x80); //打开写保护功能
}
void Ds1302ReadTime()
{
unsigned char n;
for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
{
TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
}
}
#ifndef __DS1302_H__
#define __DS1302_H__
#include "reg52.h"
#include //_nop_()函数要用到这个头文件
sbit DSIO=P3^4;
sbit RST=P3^5;
sbit SCLK=P3^6;
void Ds1302Write(unsigned char addr, unsigned char dat);
unsigned char Ds1302Read(unsigned char addr);
void Ds1302Init();
void Ds1302ReadTime();
#endif