#include "ds1302.h"
#include <STC15F2K60S2.H>
#include<intrins.h> //包含_nop_()函数定义的头文件
/***********************************************************************
以下是DS1302芯片的操作程序
************************************************************************/
int ReadValue;
/*****************************************************
函数功能:延时若干微秒
入口参数:n
***************************************************/
void delaynus(unsigned char t)
{
unsigned int i;
_nop_();
_nop_();
i = 3*t-3 ;
while (--i);
}
/*****************************************************
函数功能:向1302写一个字节数据
入口参数:x
***************************************************/
void Write1302(unsigned char dat)
{
unsigned char i;
SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备
delaynus(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续写8个二进制位数据
{
DATA=dat&0x01; //取出dat的第0位数据写入1302
delaynus(2); //稍微等待,使硬件做好准备
SCLK=1; //上升沿写入数据
delaynus(2); //稍微等待,使硬件做好准备
SCLK=0; //重新拉低SCLK,形成脉冲
dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位
}
}
/*****************************************************
函数功能:根据命令字,向1302写一个字节数据
入口参数:Cmd,储存命令字;dat,储存待写的数据
***************************************************/
void WriteSet1302(unsigned char Cmd,unsigned char dat)
{
RST=0; //禁止数据传递
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
delaynus(2); //稍微等待,使硬件做好准备
Write1302(Cmd); //写入命令字
Write1302(dat); //写数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
}
/*****************************************************
函数功能:从1302读一个字节数据
入口参数:x
***************************************************/
unsigned char Read1302(void)
{
unsigned char i,dat;
delaynus(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续读8个二进制位数据
{
dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位
if(DATA==1) //如果读出的数据是1
dat|=0x80; //将1取出,写在dat的最高位
SCLK=1; //将SCLK置于高电平,为下降沿读出
delaynus(2); //稍微等待
SCLK=0; //拉低SCLK,形成脉冲下降沿
delaynus(2); //稍微等待
}
return dat; //将读出的数据返回
}
/*****************************************************
函数功能:根据命令字,从1302读取一个字节数据
入口参数:Cmd
***************************************************/
unsigned char ReadSet1302(unsigned char Cmd)
{
unsigned char dat;
EA=0;
RST=0; //拉低RST
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
Write1302(Cmd); //写入命令字
dat=Read1302(); //读出数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
EA=1;
return dat; //将读出的数据返回
}
/*****************************************************
函数功能:DS1302是否写保护 =1,写保护 =0,不写保护
入口参数:flag
***************************************************/
void DS1302_SetProtect(bit flag) //是否写保护
{
if(flag)
WriteSet1302(0x8E,0x10); //WP=1,不能写入
else
WriteSet1302(0x8E,0x00);//WP=0,可以写入
}
/*****************************************************
函数功能:设置时间函数
入口参数:Address,Value
Address = 0x8c(年的地址) 0x88(月) 0x86(日)
0x84(时的地址) 0x82(月) 0x80(日)
***************************************************/
void DS1302_SetTime(unsigned char Address, unsigned char Value) // 设置时间函数
{
DS1302_SetProtect(0);
WriteSet1302(Address, ((Value/10)<<4 | (Value%10))); //高4位为十位,低4位为个位
}
/*****************************************************
函数功能: 1302进行初始化设置
***************************************************/
void Init_DS1302(void)
{ EA = 0;
WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令
WriteSet1302(0x80,((12/10)<<4|(12%10))); //根据写秒寄存器命令字,写入秒的初始值
WriteSet1302(0x82,((12/10)<<4|(12%10))); //根据写分寄存器命令字,写入分的初始值
WriteSet1302(0x84,((12/10)<<4|(12%10))); //根据写小时寄存器命令字,写入小时的初始值
WriteSet1302(0x86,((12/10)<<4|(12%10))); //根据写日寄存器命令字,写入日的初始值
WriteSet1302(0x88,((12/10)<<4|(12%10))); //根据写月寄存器命令字,写入月的初始值
WriteSet1302(0x8c,((12/10)<<4|(12%10))); //根据写小时寄存器命令字,写入小时的初始值
WriteSet1302(0x8E,0x10);
EA = 1;
}
/*********************************************
函数功能:设置初始时间2017年2月28 16点52分0秒
*********************************************/
void Init_DS1302_Time(void)
{ EA = 0;
WriteSet1302(0x8E,0x00);
DS1302_SetTime(0x8c,17);//17年
DS1302_SetTime(0x88,2);//2月
DS1302_SetTime(0x86,28);//28日
DS1302_SetTime(0x84,8);//16时
DS1302_SetTime(0x82,30);//50分
DS1302_SetTime(0x80,0);//0秒
WriteSet1302(0x8E,0x10);
EA = 1;
}
char ds1302_year()
{
char year;
EA = 0;
ReadValue = ReadSet1302(0x8d); //从年寄存器读
year=((ReadValue&0xf0)>>4)*10 + (ReadValue&0x0F); //将读出数据转化
EA = 1;
if(year)
return(year); //显示年
}
char ds1302_month()
{
char month;
EA = 0;
ReadValue = ReadSet1302(0x89); //从年寄存器读
month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化
EA = 1;
if(month)
return(month); //显示年
}
char ds1302_day()
{
char day;
EA = 0;
ReadValue = ReadSet1302(0x87); //从年寄存器读
day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化
EA = 1;
if(day)
return(day); //显示年
}
char ds1302_hour()
{
char hour;
EA = 0;
ReadValue = ReadSet1302(0x85); //从年寄存器读
hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化
EA = 1;
if(hour)
return(hour); //显示年
}
char ds1302_minute()
{
char minute;
EA=0;
ReadValue = ReadSet1302(0x83); //从年寄存器读
minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化
EA=1;
if(minute)
return(minute); //显示年
}
char ds1302_second()
{
char second;
EA=0;
ReadValue = ReadSet1302(0x81); //从年寄存器读
second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化
EA=1;
if(second)
return(second); //显示年
}
#ifndef _DS1302_H
#define _DS1302_H
#include <STC15F2K60S2.H>
sbit DATA=P2^3; //位定义1302芯片的接口,数据输出端定义在P1.1引脚
sbit RST=P1^3; //位定义1302芯片的接口,复位端口定义在P1.1引脚
sbit SCLK=P1^7; //位定义1302芯片的接口,时钟输出端口定义在P1.1引脚
void delaynus(unsigned char n);//延时若干微秒
void Write1302(unsigned char dat);//向1302写一个字节数据
void WriteSet1302(unsigned char Cmd,unsigned char dat);//根据命令字,向1302写一个字节数据
unsigned char Read1302(void);//从1302读一个字节数据
unsigned char ReadSet1302(unsigned char Cmd);//根据命令字,从1302读取一个字节数据
void DS1302_SetProtect(bit flag);//DS1302是否写保护 =1,写保护 =0,不写保护
void DS1302_SetTime(unsigned char Address, unsigned char Value);//设置时间函数
void Init_DS1302(void);//1302进行初始化设置
void Init_DS1302_Time(void);//设置初始时间2017年2月28 16点52分0秒
char ds1302_second();//秒
char ds1302_minute();//分
char ds1302_hour();//时
char ds1302_day();//日
char ds1302_month();//月
char ds1302_year();//年
#endif
#include "I2C.h"
#define somenop Delay5us()
void Delay5us() //@11.0592MHz
{
unsigned char i;
_nop_();
i = 11;
while (--i);
}
void lIC_Init()
{
// EA=0;
SCL=0;
IIC_Stop();
// EA=1;
}
//总线启动条件
void IIC_Start(void)
{
EA=0;
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
EA=1;
}
//总线停止条件
void IIC_Stop(void)
{
EA=0;
SCL = 0;
SDA = 0;
somenop;
SCL = 1;
somenop;
SDA = 1;
EA=1;
}
//应答位控制 //ackbit =1,应答 =0,非应答
void IIC_Ack(unsigned char ackbit)
{
if(ackbit)
{
SDA = 0;
}
else
{
SDA = 1;
}
somenop;
SCL = 1;
somenop;
SCL = 0;
SDA = 1;
somenop;
}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
if(SDA)
{
SCL = 0;
IIC_Stop();
return 1;
}
else
{
SCL = 0;
return 0;
}
}
//通过I2C总线发送数据 //eeprom专用 // 用于从机应答
bit IIC_SendByte_ep(unsigned char byt)
{
unsigned char i;
bit ack;
EA=0;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
SDA=1;
somenop;
SCL=1;
ack=SDA;
somenop;
SCL=0;
EA=1;
return (~ack);
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
EA=0;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
EA=1;
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
EA=0;
for(i=0;i<8;i++)
{
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}EA=1;
return da;
}
#ifndef I2C_H
#define I2C_H
#include <STC15F2K60S2.H>
#include <intrins.h>
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void Delay5us(); //延时5us
void lIC_Init();
void IIC_Start(void);//总线启动条件
void IIC_Stop(void);//总线停止条件
void IIC_Ack(unsigned char ackbit);//应答位控制 //ackbit =1,应答 =0,非应答
bit IIC_WaitAck(void);//等待应答 //返回值 =1,错误 =0,正常
bit IIC_SendByte_ep(unsigned char byt); //通过I2C总线发送数据 //eeprom专用 // 用于从机应答
void IIC_SendByte(unsigned char byt); //通过I2C总线发送数据
unsigned char IIC_RecByte(void);//从I2C总线上接收数据
#endif
|