📄 ds1302.c
字号:
// ******************************************************************************************
// 文件名称 :DS1302.C
// 模块名称 :实时时钟芯片DS1302设置及驱动函数
// author : steven
// time :2009-1-9
// version:V0.0
//////////////////////////////////////////////////////////////////
#include "DS1302.h"
#include "PIOA.h"
RTC_STRUCT RTCInfo; // 实时时钟信息
RTC_STRUCT rtcinfo;
// 每月天数定义 Null, Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
uchar const RTC_Month[] = {Over, 0x31, 0x29, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31};
uchar value;
uchar DS1302_temp[7];
// ================= == RTC 基本变量类型说用部分====================
//////////////////////////////////////////
//function name: uchar RTC_check(RTC_STRUCT Dummy_RTC)
//author:steven
//time :2009-1-9
//vesion:0.0
////////////////////////////////////////
uchar RTC_Check(RTC_STRUCT Dummy_RTC)
{
uchar check_temp = Ok;
// 年(含世纪位)合法性判断
if (Dummy_RTC.Date.Century != 0x20)
check_temp = Error;
// 月合法性判断
if ( (Dummy_RTC.Date.Month == 0x00)|| (Dummy_RTC.Date.Month > 0x12) )
check_temp = Error;
// 日期合法性判断考虑闰年
if ((Dummy_RTC.Date.Day == 0x00)|| (Dummy_RTC.Date.Day > (RTC_Month[BCD_To_Hex(Dummy_RTC.Date.Month)])))
check_temp = Error;
// 小时合法性判断
if (Dummy_RTC.Time.Hour >= 0x24)
check_temp = Error;
// 分钟合法性判断
if (Dummy_RTC.Time.Minute >= 0x60)
check_temp = Error;
// 秒合法性判断
if (Dummy_RTC.Time.Second >= 0x60)
check_temp = Error;
return (check_temp);
}
//////////////////////////////////////////
//function name: uchar DS1302_modify(RTC_STRUCT Dummy_RTC)
//author:steven
//time :2009-1-9
//vesion:0.0
////////////////////////////////////////
uchar DS1302_modify(RTC_STRUCT Dummy_RTC)
{
// 判断输入数据的合法性
if (RTC_check(Dummy_RTC) != Ok)
return (Error);
DS1302_write_bytes(DS1302_Control,0x00);//关闭写保护
//写入年、月、日、周、时、分、秒(00)
DS1302_write_bytes(DS1302_Year,Dummy_RTC.Date.Year);
DS1302_write_bytes(DS1302_Week,Dummy_RTC.Date.week);
DS1302_write_bytes(DS1302_Month,Dummy_RTC.Date.Month);
DS1302_write_bytes(DS1302_Day,Dummy_RTC.Date.Day);
DS1302_write_bytes(DS1302_Hour,Dummy_RTC.Time.Hour);//最高位为0,24小时模式
DS1302_write_bytes(DS1302_Minute,Dummy_RTC.Time.Minute);
DS1302_write_bytes(DS1302_Second,Dummy_RTC.Time.Second);//最高位为0,启动秒计数器
//打开写保护
DS1302_write_bytes(DS1302_Control,0x80);
return 0;
}
//////////////////////////////////////////
//function name: void DS1302_init(void)
//author:steven
//time :2009-1-9
//vesion:0.0
////////////////////////////////////////
void DS1302_init(void)
{
DS1302_write_bytes(DS1302_Control,0x00);//关闭写保护
DS1302_write_bytes(DS1302_Second,0x80); //秒暂停
DS1302_write_bytes(DS1302_Charger,0xa9);//浚流充电
//写入年、月、日、周、时、分、秒(00)
DS1302_write_bytes(DS1302_Year,0x09);
DS1302_write_bytes(DS1302_Week,0x07);
DS1302_write_bytes(DS1302_Month,0x01);
DS1302_write_bytes(DS1302_Day,0x11);
DS1302_write_bytes(DS1302_Hour,0x15);//最高位为0,24小时模式
DS1302_write_bytes(DS1302_Minute,0x41);
DS1302_write_bytes(DS1302_Second,0x00);//最高位为0,启动秒计数器
//打开写保护
DS1302_write_bytes(DS1302_Control,0x80);
}
////////////////////////////////////////////////////////////////
//function name: uchar DS1302_write_bytes(uchar Addr,uchar value)
//author:steven
//time :2009-1-9
//vesion:0.0
////////////////////////////////////////////////////////////////
uchar DS1302_write_bytes(uchar Addr,uchar value)
{
uchar I2C_Loop;
//复位操作
AT91C_BASE_PIOA->PIO_CODR |=DS1302_RST;//将RST=0
AT91C_BASE_PIOA->PIO_CODR |=DS1302_SCL;//将SCL=0
AT91C_BASE_PIOA->PIO_SODR |=DS1302_RST;//将RST=1
I2C_delay(40);
// 按位发送地址数据
for (I2C_Loop = 0; I2C_Loop < 8; I2C_Loop++)
{
if((Addr & 0x01) == 0x01)//查询最低位,端口为1置1,为0置0
AT91C_BASE_PIOA->PIO_SODR |=I2C_SDA;
else
AT91C_BASE_PIOA->PIO_CODR |=I2C_SDA;
I2C_delay(10);
AT91C_BASE_PIOA->PIO_SODR |=I2C_SCL;//将SCL = 1 __|``````|__
AT91C_BASE_PIOA->PIO_CODR |=I2C_SCL;//将SCL = 0
Addr=Addr>>1;//地址右移1位,要先发送低位
}
//在上升沿按位发送数据
for(I2C_Loop = 0; I2C_Loop < 8; I2C_Loop++)
{
if((value & 0x01) == 0x01)
AT91C_BASE_PIOA->PIO_SODR |=I2C_SDA;
else
AT91C_BASE_PIOA->PIO_CODR |=I2C_SDA;
I2C_delay(10);
AT91C_BASE_PIOA->PIO_SODR |=I2C_SCL;//将SCL = 1 __|``````|__
AT91C_BASE_PIOA->PIO_CODR |=I2C_SCL;//将SCL = 0
value=value>>1;//地址左移1位
}
I2C_delay(100);
AT91C_BASE_PIOA->PIO_SODR |=I2C_SCL;// SCL = High
AT91C_BASE_PIOA->PIO_CODR |=DS1302_RST;//将RST=0
return 0;
}
/////////////////////////////////////////////////////
//function name: uchar DS1302_read_bytes(uchar Addr)
//author:steven
//time :2009-1-9
//vesion:0.0
/////////////////////////////////////////////////////
uchar DS1302_read_bytes(uchar Addr)
{
uchar I2C_Loop;
uchar value;
//复位操作
AT91C_BASE_PIOA->PIO_CODR |=DS1302_RST;//将RST=0
AT91C_BASE_PIOA->PIO_CODR |=DS1302_SCL;//将SCL=0
I2C_delay(10);
AT91C_BASE_PIOA->PIO_SODR |=DS1302_RST;//将RST=1
I2C_delay(40);
// 按位发送要读取的地址数据
for (I2C_Loop = 0; I2C_Loop < 8; I2C_Loop++)
{
AT91C_BASE_PIOA->PIO_CODR |=I2C_SCL;//将SCL = 0
if((Addr & 0x01) == 0x01)//查询最低位,端口为1置1,为0置0
AT91C_BASE_PIOA->PIO_SODR |=I2C_SDA;
else
AT91C_BASE_PIOA->PIO_CODR |=I2C_SDA;
I2C_delay(10);
AT91C_BASE_PIOA->PIO_SODR |=I2C_SCL;//将SCL = 1 __|``````|__
I2C_delay(10);
Addr=Addr>>1;//地址左移1位
}
AT91C_BASE_PIOA->PIO_ODR|= I2C_SDA;//将I/O口改成输入口
//在下降沿接收数据
for(I2C_Loop = 0; I2C_Loop < 8; I2C_Loop++)
{
if(((AT91C_BASE_PIOA->PIO_PDSR) & I2C_SDA)==I2C_SDA)//读取引脚数据
value |=0x80;//为1,置最高位为1
else value &=0x7F;//为0,置最高位为0
I2C_delay(10);
AT91C_BASE_PIOA->PIO_SODR |=I2C_SCL;//将SCL = 1
I2C_delay(10);
AT91C_BASE_PIOA->PIO_CODR |=I2C_SCL;//将SCL = 0,下降沿
value=value>>1;//将数据右移一位
}
I2C_delay(100);
AT91C_BASE_PIOA->PIO_OER|= I2C_SDA;//将I/O口改成输出口
I2C_delay(10);
AT91C_BASE_PIOA->PIO_CODR |=DS1302_RST;//将RST=0
I2C_delay(10);
return (value);
}
////////////////////////////////////////////////////////////////////////////
//function name: RTC_STRUCT DS1302_read_bytes_continue(uchar Addr,uchar num)
//author:steven
//time :2009-1-9
//vesion:0.0
////////////////////////////////////////////////////////////////////////////
RTC_STRUCT DS1302_read_bytes_continue(uchar Addr,uchar num)
{
RTC_STRUCT Dummy_RTC;
uchar i;
for(i=num;i>0;i--)
{//读回来的是BCD码
DS1302_temp[7-i]=DS1302_read_bytes(Addr);
Addr=Addr+2;
}
Dummy_RTC.Time.Second = DS1302_temp[0]; // 读" 秒"
Dummy_RTC.Time.Minute = DS1302_temp[1]; // 读" 分钟"
Dummy_RTC.Time.Hour = DS1302_temp[2]; // 读" 小时"
Dummy_RTC.Date.Day = DS1302_temp[3]; // 读" 日期"
Dummy_RTC.Date.Month = DS1302_temp[4]; // 读" 月份"
Dummy_RTC.Date.week = DS1302_temp[5]; // 读“星期”
Dummy_RTC.Date.Year = DS1302_temp[6]; // 读" 年份"
Dummy_RTC.Date.Century = 0x20;
return(Dummy_RTC);
}
/////////////////////end/////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -