#include <avr/io.h>
#include <util/delay.h>
#include "DS1302.h"
/* DS1302 IO口定义 */
#define CLK PC0
#define DATA PC1
#define RST PC6
#define DS1302_DATA_DDR_OUT() DDRC |= (1<<DATA)
#define DS1302_DATA_DDR_IN() DDRC &= ~(1<<DATA)
#define DS1302_DATA_SET() PORTC |= (1<<DATA)
#define DS1302_DATA_CLE() PORTC &= ~(1<<DATA)
#define DS1302_GET_DATA() PINC & (1<<DATA)
#define DS1302_CLK_SET() PORTC |= (1<<CLK)
#define DS1302_CLK_CLE() PORTC &= ~(1<<CLK)
#define DS1302_RST_SET() PORTC |= (1<<RST)
#define DS1302_RST_CLE() PORTC &= ~(1<<RST)
//时钟 命令
#define CMD_SECOND 0x80 //秒
#define CMD_MINUTE 0x82 //分
#define CMD_HOUR 0x84 //时
#define CMD_DAY 0x86 //日
#define CMD_MONTH 0x88 //月
#define CMD_WEEK 0x8A //星期 DATE
#define CMD_YEAR 0x8C //年
#define CMD_CONTROL 0x8E //控制(写保护)
#define CMD_TRICKLE_CHARGE 0x90 //涓流充电
#define CMD_CLOCK_BURST 0xBE //连续读取
//时钟配置常量
#define CFG_CLOCK 0x00 //开始时钟控制位 SECOND bit7
#define CFG_UNCLOCK 0x80 //停止时钟控制位 SECOND bit7
#define CFG_12H 0x80 //12/24小时值选择位 HOUR bit7
#define CFG_24H 0x00 //12/24小时值选择位 HOUR bit7
#define CFG_PROTECT 0x80 //写保护控制位 CONTROL bit7
#define CFG_UNPROTECT 0x00 //写保护控制位 CONTROL bit7
//涓流充电控制常量
#define CFG_TC_D1R2 0xA5 //high 1 Diode +2K Resistors
#define CFG_TC_D2R8 0xAB //low 2 Diodes+8K Resistors
#define CFG_TC_DISABLED 0x00 //Disabled(TCS<>1010 or DS=00 or RS=00)
//RAM 命令
#define CMD_RAM_BASE 0xC0 //RAM0~RAM30<<1 地址需左移一位
#define CMD_RAM_BURST 0xFE //连续读取
#define DS1302_WP_DIS DS1302_Write_Data(CMD_CONTROL,CFG_UNPROTECT)
#define DS1302_WP_EN DS1302_Write_Data(CMD_CONTROL,CFG_PROTECT)
#define DS1302_CH_DIS DS1302_Write_Data(CMD_SECOND,CFG_UNCLOCK)
#define DS1302_CH_EN DS1302_Write_Data(CMD_SECOND,CFG_CLOCK)
#define DS1302_24H DS1302_Write_Data(CMD_HOUR,CFG_24H)
#define DS1302_TRICKLE(x) DS1302_Write_Data(CMD_TRICKLE_CHARGE,x)
/* BCD换成十进制数 */
unsigned char BCD_D(unsigned char x)
{
unsigned char y,z;
y = x;
z = (y&0x70)>>4;
z *= 10;
y = y&0x0f;
y += z;
return y;
}
/* 十进制转换成BCD */
unsigned char D_BCD(unsigned char x)
{
unsigned char y;
y=(x/10)<<4|x%10;
return y;
}
/* DS1302写一位 */
static void DS1302_Write_Byte(unsigned char data)
{
unsigned char temp = 0;
unsigned char i = 0;
temp = data;
DS1302_RST_SET();
for(i=0;i<8;i++)
{
if((temp & 0x01) == 0x01)
{
DS1302_DATA_SET();
}
else
{
DS1302_DATA_CLE();
}
temp = temp >> 1;
DS1302_CLK_SET();
_delay_us(2);
DS1302_CLK_CLE();
_delay_us(2);
}
}
/* DS1302读一位 */
static unsigned char DS1302_Read_Byte(void)
{
unsigned char temp = 0;
unsigned char i = 0;
DS1302_RST_SET();
DS1302_DATA_DDR_IN();
for(i=0;i<8;i++)
{
temp = temp >> 1;
if(DS1302_GET_DATA())
{
temp |= 0x80;
}
DS1302_CLK_SET();
_delay_us(2);
DS1302_CLK_CLE();
_delay_us(2);
}
DS1302_DATA_DDR_OUT();
return temp;
}
/* DS1302写一位数据 */
static void DS1302_Write_Data(unsigned char cmd,unsigned char data)
{
DS1302_CLK_CLE();
DS1302_RST_SET();
DS1302_Write_Byte(cmd|0x00);
DS1302_Write_Byte(data);
DS1302_CLK_SET();
DS1302_RST_CLE();
}
/* DS1302读一位数据 */
static unsigned char DS1302_Read_Data(unsigned char cmd)
{
unsigned char temp;
DS1302_CLK_CLE();
DS1302_RST_SET();
DS1302_Write_Byte(cmd|0x01);
temp = DS1302_Read_Byte();
DS1302_CLK_SET();
DS1302_RST_CLE();
return temp;
}
/* DS1302读时间 */
void DS1302_Read_Time(volatile unsigned char *pbuf)
{
*pbuf++ = BCD_D(DS1302_Read_Data(CMD_SECOND) & 0x7f);
*pbuf++ = BCD_D(DS1302_Read_Data(CMD_MINUTE) & 0x7f);
*pbuf++ = BCD_D(DS1302_Read_Data(CMD_HOUR) & 0x3f);
*pbuf++ = BCD_D(DS1302_Read_Data(CMD_DAY) & 0x3f);
*pbuf++ = BCD_D(DS1302_Read_Data(CMD_MONTH) & 0x1f);
*pbuf++ = BCD_D(DS1302_Read_Data(CMD_WEEK) & 0x07);
*pbuf = BCD_D(DS1302_Read_Data(CMD_YEAR) & 0xff);
}
/* DS1302写时间 */
void DS1302_Write_Time(volatile unsigned char *pbuf)
{
unsigned char i = 0;
unsigned char j = CMD_SECOND;
DS1302_WP_DIS;
DS1302_CH_DIS;
for(i=0;i<7;i++)
{
DS1302_Write_Data(j,D_BCD(*pbuf));
j = j+2;
pbuf++;
}
DS1302_CH_EN;
DS1302_WP_EN;
DS1302_Init();
}
/* 初始化DS1302 */
void DS1302_Init(void)
{
DS1302_WP_DIS;
DS1302_CH_DIS;
DS1302_TRICKLE(CFG_TC_D2R8);
DS1302_CH_EN;
DS1302_WP_EN;
}
#ifndef _DS1302_H_
#define _DS1302_H_
/* 初始化DS1302 */
void DS1302_Init(void);
/* 检测DS1302 */
unsigned char DS1302_Check(void);
/* DS1302读时间 */
void DS1302_Read_Time(volatile unsigned char *pbuf);
/* DS1302写时间 */
void DS1302_Write_Time(volatile unsigned char *pbuf);
/* BCD换成十进制数 */
unsigned char BCD_D(unsigned char x);
/* 十进制转换成BCD */
unsigned char D_BCD(unsigned char x);
#endif