#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
|