注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

耳朵的博客

做自己想做的人

 
 
 

日志

 
 

AVR DS1302 程序源代码(原创)  

2010-10-09 22:35:03|  分类: AVR |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
发现网上一些程序在16M晶振下不能工作,自己写了个,按照2V的时序写的,但只在5V和3.3V下测试过.
恳请高人批评指教!
整个工程下载:

以下是两个主要的文件

DS1302.h:
/************ AVR DS1302程序 ************

* 版本.........: 1.0
* 作者.........: 陈利栋
* 目标.........: ATmega128
* 文件名.......: DS1302.h
* 编译器.......: IAR for AVR V5.5
* 创建时间.....: 2010.10.11
* 最后修改.....: 2010.10.11
****************************************/
#ifndef __DS1302_H__
#define __DS1302_H__

#include <ioavr.h>
#include <stdbool.h>
#include <stdio.h>
#include "delay.h"

#define RTC_SCAN_FREQ              5   // RTC 定时扫描频率 单位 Hz

#define DS1302_CE_DDR              DDRD
#define DS1302_CE_PORT             PORTD
#define DS1302_CE_BIT              5

#define DS1302_IO_DDR              DDRD
#define DS1302_IO_PORT             PORTD
#define DS1302_IO_PIN              PIND
#define DS1302_IO_BIT              4

#define DS1302_SCK_DDR             DDRD
#define DS1302_SCK_PORT            PORTD
#define DS1302_SCK_BIT             3

#define DS1302_CE_ENABLE           DS1302_CE_PORT |= (1 << DS1302_CE_BIT)
#define DS1302_CE_DISABLE          DS1302_CE_PORT &= ~(1 << DS1302_CE_BIT)

#define DS1302_IO_1                DS1302_IO_PORT |= (1 << DS1302_IO_BIT)
#define DS1302_IO_0                DS1302_IO_PORT &= ~(1 << DS1302_IO_BIT)
#define DS1302_IO_IN               DS1302_IO_DDR &= ~(1 << DS1302_IO_BIT)
#define DS1302_IO_OUT              DS1302_IO_DDR |= (1 << DS1302_IO_BIT)
#define DS1302_IO_VALUE            (DS1302_IO_PIN & (1 << DS1302_IO_BIT))

#define DS1302_SCK_1               DS1302_SCK_PORT |= (1 << DS1302_SCK_BIT)
#define DS1302_SCK_0               DS1302_SCK_PORT &= ~(1 << DS1302_SCK_BIT)

typedef enum
{
    _12_hours, _24_hours
}HourMode;

typedef enum
{
    am, pm
}AM_PM;

// DS1302 寄存器
typedef union
{
    unsigned char buf[8];
    struct
    {
        unsigned char Seconds;
        unsigned char Minutes;
        unsigned char Hour;
        unsigned char Date;
        unsigned char Month;
        unsigned char Day;
        unsigned char Year;
        unsigned char WriteProtect;
    }_struct;
}DS1302_Register;

// 十进制标准的时间和日期结构
typedef struct
{
    unsigned char Seconds;              // 秒 0 - 59
    unsigned char Minutes;              // 分 0 - 59
    unsigned char Hours;                // 时 1 - 12 或 0 - 23
    unsigned char Date;                 // 日 1 - 31
    unsigned char Month;                // 月 1 - 12
    unsigned char Year;                 // 年 0 - 99
    unsigned char Day;                  // 星期 1 - 7 星期天 = 7
    HourMode hour_mode;                 // 小时模式 _12_hours 或 _24_hours
    AM_PM am_pm;                        // 上午下午标志 12时制时有效 am 或 pm
}RTC_DateTime;

// 10进制转BCD码
#define DEC_TO_BCD(dec)                 ((((dec) / 10) << 4) + ((dec) % 10))
// BCD码转10进制
#define BCD_TO_DEC(bcd)                 ((((bcd) >> 4) * 10) + ((bcd) & 0x0f))


// 寄存器地址定义
#define DS1302_SECONDS_ADDR             0x80
#define DS1302_MINUTES_ADDR             0x82
#define DS1302_HOUR_ADDR                0x84
#define DS1302_DATE_ADDR                0x86
#define DS1302_MONTH_ADDR               0x88
#define DS1302_DAY_ADDR                 0x8a
#define DS1302_YEAR_ADDR                0x8c
#define DS1302_WRITE_PROTECT_ADDR       0x8e     // 写保护
#define DS1302_TRICKLE_CHARGE_ADDR      0x90     // 涓流充电
#define DS1302_CLOCK_BURST_ADDR         0xbe     // 连续读写


#define RTC_SECONDS                     (My_RTC_DateTime.Seconds)
#define RTC_MINUTES                     (My_RTC_DateTime.Minutes)
#define RTC_HOURS                       (My_RTC_DateTime.Hours)
#define RTC_DATE                        (My_RTC_DateTime.Date)
#define RTC_MONTH                       (My_RTC_DateTime.Month)
#define RTC_YEAR                        (My_RTC_DateTime.Year)
#define RTC_DAY                         (My_RTC_DateTime.Day)
#define RTC_HOUR_MODE                   (My_RTC_DateTime.hour_mode)
#define RTC_AM_PM                       (My_RTC_DateTime.am_pm)

#define RTC_INIT                        DS1302_Init()         // 初始化
#define RTC_SET_DATE_TIME               DS1302_SetDateTime()  // 设置日期和时间
#define RTC_GET_DATE_TIME               DS1302_GetDateTime()  // 获取期和时间

extern RTC_DateTime My_RTC_DateTime;
extern volatile bool RTC_Update;        // RTC更新标志
extern void DS1302_Init(void);           
extern void DS1302_GetDateTime(void);
extern void DS1302_SetDateTime(void);

#endif /* __DS1302_H__ */



DS1302.c:
/************ AVR DS1302程序 ************
* 版本.........: 1.0
* 作者.........: 陈利栋
* 目标.........: ATmega128
* 文件名.......: DS1302.c
* 编译器.......: IAR for AVR V5.5
* 创建时间.....: 2010.10.11
* 最后修改.....: 2010.10.11
****************************************/
#include "DS1302.h"

RTC_DateTime My_RTC_DateTime;
DS1302_Register My_DS1302_Register;
volatile bool RTC_Update = false;   // RTC时间更新标志
volatile unsigned char second_last = 0;

unsigned char GetDayFromDate(unsigned char year,unsigned char month,unsigned char date);

// 发送一个字节,不操作CE
static void DS1302_TxByte(unsigned char b)
{
    unsigned char i = 0;

    DS1302_IO_OUT;
    for (i = 0i < 8i++)
    {
        DS1302_SCK_0;
        _delay_us(1);         // CLK Low Time
        if (b & 0x01)
        {
            DS1302_IO_1;
        }
        else
        {
            DS1302_IO_0;
        }
        _delay_us(1);         // Data to CLK Setup
        DS1302_SCK_1;
        _delay_us(1);         // CLK High Time
        b >>= 1;
    }
}

// 接收一个字节,不操作CE
static unsigned char DS1302_RxByte(void)
{
    unsigned char i = 0;
    unsigned char b = 0;

    DS1302_IO_IN;
    DS1302_IO_1;              // 上拉
    for (i = 0i < 8i++)
    {
        DS1302_SCK_0;
        _delay_us(1);         // CLK to Data Delay
        b >>= 1;
        if (DS1302_IO_VALUE)
        {
            b |= 0x80;
        }
        DS1302_SCK_1;
        _delay_us(1);
    }

    return b;
}

static void DS1302_WriteByte(unsigned char address, unsigned char _data)
{
    DS1302_CE_ENABLE;
    _delay_us(4);             // CE to CLK Setup
    DS1302_TxByte(address);
    DS1302_TxByte(_data);
    DS1302_SCK_0;
    _delay_us(1);             // CLK to CE Hold
    DS1302_CE_DISABLE;
    _delay_us(4);             // CE Inactive Time      
}

static unsigned char DS1302_ReadByte(unsigned char address)
{
    unsigned char _data = 0;

    DS1302_CE_ENABLE;
    _delay_us(4);             // CE to CLK Setup
    DS1302_TxByte(address | 0x01);
    _data = DS1302_RxByte();
    DS1302_SCK_0;
    _delay_us(1);             // CLK to CE Hold
    DS1302_CE_DISABLE;
    _delay_us(4);             // CE Inactive Time      
    
    return _data;
}

void DS1302_SetDateTime(void)
{
    unsigned char i = 0;
    
    DS1302_WriteByte(DS1302_WRITE_PROTECT_ADDR, 0x00);         // 关闭写保护

    // 配置将要写入的数据
    My_DS1302_Register._struct.Seconds = DEC_TO_BCD(RTC_SECONDS);
    My_DS1302_Register._struct.Minutes = DEC_TO_BCD(RTC_MINUTES);
    My_DS1302_Register._struct.Hour = DEC_TO_BCD(RTC_HOURS);
    My_DS1302_Register._struct.Date = DEC_TO_BCD(RTC_DATE);
    My_DS1302_Register._struct.Month = DEC_TO_BCD(RTC_MONTH);
    My_DS1302_Register._struct.Year = DEC_TO_BCD(RTC_YEAR);
    RTC_DAY = GetDayFromDate(RTC_YEAR, RTC_MONTH, RTC_DATE);
    My_DS1302_Register._struct.Day = DEC_TO_BCD(RTC_DAY);
    
    if (RTC_HOUR_MODE == _12_hours)
    {
        My_DS1302_Register._struct.Hour |= 0x80;
        My_DS1302_Register._struct.Hour |= (RTC_AM_PM == pm ? 0x20 : 0);
    }

    My_DS1302_Register._struct.WriteProtect = 0x80;             // 写入完毕后设置写保护

    // 连续写入
    DS1302_CE_ENABLE;
    _delay_us(4);             // CE to CLK Setup
    DS1302_TxByte(DS1302_CLOCK_BURST_ADDR);
    DS1302_SCK_0;
    for (i = 0i < 8i++)
    {
        DS1302_TxByte(My_DS1302_Register.buf[i]);
    }
    DS1302_SCK_0;
    _delay_us(1);             // CLK to CE Hold
    DS1302_CE_DISABLE;
    _delay_us(4);             // CE Inactive Time
}

void DS1302_GetDateTime(void)
{
    unsigned char i = 0;

    DS1302_CE_ENABLE;
    _delay_us(4);             // CE to CLK Setup
    DS1302_TxByte(DS1302_CLOCK_BURST_ADDR | 0x01);
    for (i = 0i < 8i++)
    {
        My_DS1302_Register.buf[i] = DS1302_RxByte();
    }
    DS1302_SCK_0;
    _delay_us(1);             // CLK to CE Hold
    DS1302_CE_DISABLE;
    _delay_us(4);             // CE Inactive Time

    RTC_SECONDS = BCD_TO_DEC(My_DS1302_Register._struct.Seconds);
    RTC_MINUTES = BCD_TO_DEC(My_DS1302_Register._struct.Minutes);
    RTC_DATE = BCD_TO_DEC(My_DS1302_Register._struct.Date);
    RTC_MONTH = BCD_TO_DEC(My_DS1302_Register._struct.Month);
    RTC_YEAR = BCD_TO_DEC(My_DS1302_Register._struct.Year);
    RTC_DAY = BCD_TO_DEC(My_DS1302_Register._struct.Day);

    if ((My_DS1302_Register._struct.Hour& 0x80)
    {
        RTC_HOUR_MODE = _12_hours;
        RTC_AM_PM = (((My_DS1302_Register._struct.Hour& 0x20? pm : am);
        RTC_HOURS = BCD_TO_DEC(My_DS1302_Register._struct.Hour & 0x1f);
    }
    else
    {
        RTC_HOURS = BCD_TO_DEC(My_DS1302_Register._struct.Hour);
    }
}

#ifdef DEBUG
void DS1302_WriteBuildDateTime(void);
#endif /* DEBUG */ 

void DS1302_Init(void)
{
    // 端口初始化
    DS1302_CE_DISABLE;
    DS1302_CE_DDR |= (1 << DS1302_CE_BIT);
    DS1302_SCK_0;
    DS1302_SCK_DDR |= (1 << DS1302_SCK_BIT);

    DS1302_WriteByte(DS1302_WRITE_PROTECT_ADDR, 0x00);        // 关闭写保护
    
    // 初始配置
    DS1302_WriteByte(DS1302_TRICKLE_CHARGE_ADDR, 0xa7);       // 使能涓流充电 1 Diode, 8kΩ

    DS1302_WriteByte(DS1302_WRITE_PROTECT_ADDR, 0x80);        // 打开写保护

    // 配置定时器1 (用于RTC时间定时扫描)
    TCCR1B_WGM12 = 1;      // CTC 模式 TOP : OCR1A
    TCCR1B_CS10 = 1;       // 1024 分频
    TCCR1B_CS12 = 1;       // 1024 分频
    TCNT1 = 0;
    OCR1A = F_CPU / 1024 / RTC_SCAN_FREQ;
    TIMSK_OCIE1A = 1;      // 输出比较 A 匹配中断使能

#ifdef DEBUG
    DS1302_WriteBuildDateTime();
#endif /* DEBUG */ 
}


#pragma vector = TIMER1_COMPA_vect
__interrupt void RTC_Scan(void)
{
    My_DS1302_Register._struct.Seconds = DS1302_ReadByte(DS1302_SECONDS_ADDR);
    if (second_last != My_DS1302_Register._struct.Seconds)
    {
        second_last = My_DS1302_Register._struct.Seconds;
        RTC_Update = true;
    }
}

// 计算2000~2099年任一天星期几 
// year        : 00-99 
// month       : 01-12 
// day         : 01-31 
// 返回 1 -> 7 : 星期一 -> 星期天
unsigned char GetDayFromDate(unsigned char year,unsigned char month,unsigned char date)
{ 
    if (month == 1 || month == 2)  
    { 
        month += 12;
        if (year > 0
            year--
        else 
            year = 4;
    } 
    return (1 + ((date + 2 * month + 3 * (month + 1/ 5 + year + year / 4% 7)); 
}

#ifdef DEBUG    /* Debug 模式 在 C/C++ Compiler -> Preprocessor -> Defined symbols 自己定义 */

typedef struct
{
    unsigned int Year;
    unsigned int Month;
    unsigned int Date;
    unsigned int Hours;
    unsigned int Minutes;
    unsigned int Seconds;
}BuildDateTime;

__flash unsigned char MonthStr[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov","Dec"};

void GetBuildDateTime(BuildDateTime *p_BuildDateTime)
{
    unsigned char temp_str[4] = {0, 0, 0, 0}, i = 0;

    sscanf(__DATE__, "%s %2d %4d", temp_str, &(p_BuildDateTime->Date), &(p_BuildDateTime->Year));
    sscanf(__TIME__, "%2d:%2d:%2d", &(p_BuildDateTime->Hours), &(p_BuildDateTime->Minutes), &(p_BuildDateTime->Seconds));
    for (i = 0i < 12i++)
    {
        if (temp_str[0] == MonthStr[i][0] && temp_str[1] == MonthStr[i][1] && temp_str[2] == MonthStr[i][2])
        {
            p_BuildDateTime->Month = i + 1;
            break;
        }
    }
}

// 写入编译时间(便于调试)
void DS1302_WriteBuildDateTime(void)
{
    BuildDateTime MyBuildDateTime;

    GetBuildDateTime(&MyBuildDateTime);

    RTC_YEAR = (MyBuildDateTime.Year% 100;
    RTC_MONTH = MyBuildDateTime.Month;
    RTC_DATE = MyBuildDateTime.Date;
    RTC_HOURS = MyBuildDateTime.Hours;
    RTC_MINUTES = MyBuildDateTime.Minutes;
    RTC_SECONDS = MyBuildDateTime.Seconds;

    RTC_HOUR_MODE = _12_hours;
    RTC_AM_PM = (RTC_HOURS > 12 ? pm : am);
    RTC_HOURS -= (RTC_HOURS > 12 ? 12 : 0);

    DS1302_SetDateTime();
}

#endif /* DEBUG */
  评论这张
 
阅读(2009)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017