在51单片机上使用DS1302

1、硬件电路
在51单片机上使用DS1302_第1张图片2、程序
SCLK、IO、RET三个口都要接上拉电阻,实验中SCLK接P0.3,I/O接P0.4,RET接P0.5
在51单片机上使用DS1302_第2张图片
根据DS1302的时序图,往DS1302中写数据时,RST先要有一个上升沿。所以初始化时把RET和SCLK全部设置为0。
//==========================================
// DS1302初始化
//==========================================
void Ds1302_Init(void)
{
CE = 0; //RST脚置低
SCLK = 0; //SCK脚置低
Ds1302_Write_Byte(WRITE_SECOND,0x00); //开始
}
然后启动读字节,让RST有一个上升沿。
void Ds1302_Write_Byte (uchar addr, uchar dat)
{
uchar i;
CE = 1;
//写入目标地址:addr
addr = addr & 0xFE; //最低位置零
for (i = 0; i < 8; i ++)
{
if (addr & 0x01)
{
DIO = 1;
}
else
{
DIO = 0;
}
SCLK = 1;
SCLK = 0;
addr = addr >> 1;
}
//写入数据:d
for (i = 0; i < 8; i ++)
{
if (dat & 0x01)
{
DIO = 1;
}
else
{
DIO = 0;
}
SCLK = 1;
SCLK = 0;
dat = dat >> 1;
}
CE = 0;; //停止DS1302总线
}
3、遇到的问题
时钟显示为2000-00-00,引脚没接好,短路了
时钟显示为初始时间,不走了,首先看晶振是否是32.7k的,然后更换电容6p或者30p的都行。

4、总程序(时间显示在128*64的LCD屏幕上):
#include
#include
#define uchar unsigned char
#define uint unsigned int
unsigned int i;
/LCD管脚设置*/
sbit RS=P1^3;
sbit RW=P1^4;
sbit EN=P1^5;
sbit PSB=P1^6;
sbit RET=P0^7;
//sfr16 TMR2RL = 0xca;// 定时器2重载值这里采用的是定时器2的16位自动重载
//sfr16 TMR2 = 0xcc;// 定时器2计数值
//sfr16 ADC0 = 0xbd;// P35 ADC0的采样值
#define SYSCLK 24500000 // 内部晶振频率为24.5MHz
#define BAUDRATE 115200 // 串口通讯波特率为115200
void SYSCLK_Init (void)
{
OSCICN = 0x84; // 内部振荡器不分频为24.5MHz P138
RSTSRC = 0x04; // 复位源寄存器 时钟丢失检测器标志置1
CLKSEL = 0x00;
}
void delay_50us(uint t)
{
uchar i=2;
while(t–)
while(i–);
}
void delay_50ms(uint t)
{
uint i,j,k;
for (i=t;i>0;i–)
for (j=57;j>0;j–)
for(k=100;k>0;k–);
}
void write12864com(uchar com)//写指令
{ RS=0;
RW=0;
delay_50us(1);
P2=com;
EN=1;
delay_50us(1);
EN=0;
delay_50us(1);
}
void write12864dat(uchar dat)//写数据
{
RS=1;
RW=0;
delay_50us(1);
P2=dat;
EN=1;
delay_50us(1);
EN=0;
delay_50us(1);
}
void initinal12864(void)//LCD12864初始化设置
{ PSB=1;
RET=1;
delay_50ms(2);
write12864com(0x30);
delay_50us(2);
write12864com(0x30);
delay_50us(2);
write12864com(0x0c);
delay_50us(1);
write12864com(0x01);
delay_50us(20);
write12864com(0x06);
delay_50us(2);
}
void write12864place(uchar x,uchar y)//液晶地址设置
{
uchar tempaaa=0x80;
switch(x)
{
case 1: tempaaa=0x7f;
break;
case 2: tempaaa=0x8f;
break;
case 3: tempaaa=0x87;
break;
case 4: tempaaa=0x97;
break;

}
tempaaa=tempaaa+y;
write12864com(tempaaa);
delay_50us(4);	

}
/**************************
uchar table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//数码管显示
uchar dis_buf[4];
sbit wei1=P1^0;//数码管位选设置
sbit wei2=P1^1;//数码管位选设置
sbit wei3=P1^2;//数码管位选设置
sbit wei4=P1^3;//数码管位选设置
void Delay1(unsigned char i)
{
for(i;i>0;i–);
}
//数码管扫描显示函数
void Display(uint analog)
{
uint i;
// analog=analog1.0/40962.51000;
dis_buf[0]=analog/1000; //千位数值显示
dis_buf[1]=analog/100%10; //百位数值显示
dis_buf[2]=analog/10%10;//十位数值显示
dis_buf[3]=analog%10; //个位数值显示
for(i=0;i<500;i++)//数码管扫描显示
{
P2=table[dis_buf[0]];
wei1=0;
Delay1(80);
wei1=1;
P2=table[dis_buf[1]]&0x7f;
wei2=0;
Delay1(80);
wei2=1;
P2=table[dis_buf[2]];
wei3=0;
Delay1(80);
wei3=1;
P2=table[dis_buf[3]];
wei4=0;
Delay1(80);
wei4=1;
}
}
**************************/
sbit SCLK = P0^3 ; //DS1302时钟
sbit DIO = P0^4 ; //DS1302数据
sbit CE = P0^5 ; //DS1302片选
void Ds1302_Write_Byte (uchar addr, uchar dat);
uchar Ds1302_Read_Byte ( uchar addr );
void Ds1302_Write_Time(void);
void Ds1302_Read_Time(void);
void Ds1302_Init(void);
#define WRITE_SECOND 0x80
#define WRITE_MINUTE 0x82
#define WRITE_HOUR 0x84
#define WRITE_DAY 0x86
#define WRITE_MONTH 0x88
#define WRITE_WEEK 0x8A
#define WRITE_YEAR 0x8C
#define WRITE_TIMER_FLAG 0xC0
#define READ_SECOND 0x81
#define READ_MINUTE 0x83
#define READ_HOUR 0x85
#define READ_DAY 0x87
#define READ_MONTH 0x89
#define READ_WEEK 0x8B
#define READ_YEAR 0x8D
#define READ_TIMER_FLAG 0xC1
#define WRITE_PROTECT 0x8E
uchar time_buf1[8] = {20,18,1,10,14,59,50,3}; //写年月日时分秒周
uchar time_buf[8]; //读年月日时分秒周
void Oscillator_Init()
{
OSCICN = 0x84;
}
void PCA_Init()
{
PCA0MD &= ~0x40;
PCA0MD = 0x00;
}
void Port_IO_Init()
{
XBR1 = 0x40;
}
void Init_Device(void)
{
Oscillator_Init();
PCA_Init();
Port_IO_Init();
}
//============================================
//函数名称:void Ds1302_Write_Byte (byte addr, byte dat)
//功能: 串行发送地址、数据,先发低位,且在上升沿发送
//参数传递:有,地址和数据
//返回值: 无
//===========================================
void Ds1302_Write_Byte (uchar addr, uchar dat)
{
uchar i;
CE = 1;
//写入目标地址:addr
addr = addr & 0xFE; //最低位置零
for (i = 0; i < 8; i ++)
{
if (addr & 0x01)
{
DIO = 1;
}
else
{
DIO = 0;
}
SCLK = 1;
SCLK = 0;
addr = addr >> 1;
}
//写入数据:d
for (i = 0; i < 8; i ++)
{
if (dat & 0x01)
{
DIO = 1;
}
else
{
DIO = 0;
}
SCLK = 1;
SCLK = 0;
dat = dat >> 1;
}
CE = 0;; //停止DS1302总线
}
//===============================================
//函数名称:byte Ds1302_Read_Byte ( byte addr )
//功能: 串行读取数据,先发低位,且在下降沿发送
//参数传递:有,地址
//返回值: 有,读取的数据
//===============================================
uchar Ds1302_Read_Byte ( uchar addr )
{
uchar i;
uchar temp;
CE = 1;
//写入目标地址:addr
addr = addr | 0x01; //最低位置高
for (i = 0; i < 8; i ++)
{
if (addr & 0x01)
{
DIO = 1;
}
else
{
DIO = 0;
}
SCLK = 1;
SCLK = 0;
addr = addr >> 1;
}
//输出数据:temp
for (i = 0; i < 8; i ++)
{
temp = temp >> 1;
if (DIO)
{
temp |= 0x80;
}
else
{
temp &= 0x7F;
}
SCLK = 1;
SCLK = 0;
}
CE = 0;//停止DS1302总线
return temp;
}
//===============================================
// 向DS1302写入时钟数据
//===============================================
void Ds1302_Write_Time(void)
{
uchar i,tmp;
//BCD处理,将十进制数据转换十六进制
for(i=0;i<8;i++)
{
tmp=time_buf1[i]/10;
time_buf[i]=time_buf1[i]%10;
time_buf[i]=time_buf[i]+tmp
16;
}
Ds1302_Write_Byte(WRITE_PROTECT,0x00); //关闭写保护
Ds1302_Write_Byte(WRITE_SECOND,0x80); //暂停
Ds1302_Write_Byte(WRITE_YEAR,time_buf[1]); //年
Ds1302_Write_Byte(WRITE_MONTH,time_buf[2]); //月
Ds1302_Write_Byte(WRITE_DAY,time_buf[3]); //日
Ds1302_Write_Byte(WRITE_HOUR,time_buf[4]); //时
Ds1302_Write_Byte(WRITE_MINUTE,time_buf[5]); //分
Ds1302_Write_Byte(WRITE_SECOND,time_buf[6]); //秒
Ds1302_Write_Byte(WRITE_WEEK,time_buf[7]); //周
Ds1302_Write_Byte(WRITE_PROTECT,0x80); //打开写保护
}
//========================================
// 从DS1302读出时钟数据
//========================================
void Ds1302_Read_Time(void)
{
uchar i,tmp;
time_buf[1]=Ds1302_Read_Byte(READ_YEAR); //年
time_buf[2]=Ds1302_Read_Byte(READ_MONTH); //月
time_buf[3]=Ds1302_Read_Byte(READ_DAY); //日
time_buf[4]=Ds1302_Read_Byte(READ_HOUR); //时
time_buf[5]=Ds1302_Read_Byte(READ_MINUTE); //分
time_buf[6]=(Ds1302_Read_Byte(READ_SECOND))&0x7F; //秒
time_buf[7]=Ds1302_Read_Byte(READ_WEEK); //周
//BCD处理,将十六进制数据转换十进制
for(i=0;i<8;i++)
{
tmp=time_buf[i]/16;
time_buf1[i]=time_buf[i]%16;
time_buf1[i]=time_buf1[i]+tmp*10;
}
}
//==========================================
// DS1302初始化
//==========================================
void Ds1302_Init(void)
{
CE = 0; //RST脚置低
SCLK = 0; //SCK脚置低
Ds1302_Write_Byte(WRITE_SECOND,0x00); //开始
}
void main (void)
{
Init_Device();
Ds1302_Init();
Ds1302_Write_Time();
initinal12864();//初始化12864
// delay_50us(3);
//液晶显示
while(1){
Ds1302_Read_Time();
// Display(time_buf1[1]);//数码管显示年
write12864place(1,1);
write12864dat(time_buf1[0]/10%10+0x30);
write12864dat(time_buf1[0]%10+0x30);
write12864dat(time_buf1[1]/10%10+0x30);
write12864dat(time_buf1[1]%10+0x30);//液晶显示年
write12864place(2,1);
write12864dat(time_buf1[2]/10+0x30);
write12864dat(time_buf1[2]%10+0x30);//液晶显示月
write12864dat(’-’);
write12864dat(time_buf1[3]/10+0x30);
write12864dat(time_buf1[3]%10+0x30);//液晶显示日
write12864place(3,1);
write12864dat(time_buf1[4]/10+0x30);
write12864dat(time_buf1[4]%10+0x30);//液晶显示时
write12864dat(’:’);
write12864dat(time_buf1[5]/10+0x30);
write12864dat(time_buf1[5]%10+0x30);//液晶显示分
write12864dat(’:’);
write12864dat(time_buf1[6]/10+0x30);
write12864dat(time_buf1[6]%10+0x30);//液晶显示秒
write12864place(4,1);
switch(time_buf1[7])//液晶显示周
{
case 1: write12864dat(‘M’);
write12864dat(‘o’);
write12864dat(‘n’);
break;
case 2: write12864dat(‘T’);
write12864dat(‘u’);
write12864dat(‘e’);
write12864dat(‘s’);
break;
case 3: write12864dat(‘W’);
write12864dat(‘e’);
write12864dat(‘d’);
break;
case 4: write12864dat(‘T’);
write12864dat(‘h’);
write12864dat(‘u’);
write12864dat(‘r’);
break;
case 5: write12864dat(‘F’);
write12864dat(‘r’);
write12864dat(‘i’);
break;
case 6: write12864dat(‘S’);
write12864dat(‘a’);
write12864dat(‘t’);
break;
case 7: write12864dat(‘S’);
write12864dat(‘u’);
write12864dat(‘n’);
break;
}
}
}
3、现象
在51单片机上使用DS1302_第3张图片

你可能感兴趣的:(8051F410)