AVR DS1302 程序源代码

发布者:温柔微笑最新更新时间:2016-11-22 来源: eefocus关键字:AVR  DS1302  程序源代码 手机看文章 扫描二维码
随时随地手机看文章

发现网上一些程序在16M晶振下不能工作,自己写了个,按照2V的时序写的,但只在5V和3.3V下测试过.

以下是两个主要的文件

DS1302.h:

/************ AVR DS1302程序 ************
* 目标.........: ATmega128
* 文件名.......: DS1302.h
* 编译器.......: IAR for AVR V5.5
****************************************/
#ifndef __DS1302_H__
#define __DS1302_H__

#include




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 = 0; i < 8; i++)
    {
        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 = 0; i < 8; i++)
    {
        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 = 0; i < 8; i++)
    {
        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 = 0; i < 8; i++)
    {
        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 = 0; i < 12; i++)
    {
        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 */


关键字:AVR  DS1302  程序源代码 引用地址:AVR DS1302 程序源代码

上一篇:IAR for AVR delay函数
下一篇:基于无线传感器网络的煤矿安全监控系统的研究

推荐阅读最新更新时间:2024-03-16 15:21

avr proteus仿真第一课:安装设置avr studio和winavr
avr的开发环境需要安装两个软件: WinAVR+AVR Studio 新手入门必读 1. 获得必须的软件 请从Atmel官方获得最新版本的AVR Studio 下载地址参见: http://www.cnblogs.com/proteus/archive/2011/11/09/2242583.html 请从WinAVR官方获得最新版本的WinAVR 下载地址: http://sourceforge.net/projects/winavr/files/WinAVR/ 注意:WinAVR和AVR Studio是2个不同的软件,前者是开源项目,不属于Atmel所有,后者是Atmel版权所有的。 2. 安装步骤 1)安装WinAVR 2
[单片机]
算法器之AVR的ISP烧录
总的电子线路如下: 这里先介绍一下这个芯片: 74HC244是一款高速CMOS器件,74HC244引脚兼容低功耗肖特基TTL(LSTTL)系列。74HC244是八路正相缓冲器/线路驱动器,具有三态输出。该三态输出由输出使能端1OE和2OE控制。任意nOE上的高电平将使输出端呈现高阻态。74HC244与74HC240逻辑功能相似,只不过74HC244带有正相输出。 用来作计算机并口和单片机的缓冲隔离。注意是连接到LPT打印口 其他必需知识点: LPT的⑦脚输出编程命令和数据到单片机的MOSI端(MOSI在这里表示计算机输出、单片机输 入) LPT的⑥脚输出串行编程时钟信号到单片机的SCK端,SCK是IIC时钟
[单片机]
算法器之<font color='red'>AVR</font>的ISP烧录
AVR单片机集成CAN总线控制器分析与应用
引言 CAN总线应用中,总线节点是CAN总线的基本组成部分。CAN总线节点有两种典型设计方法,第一种方法采用MCU结合独立CAN控制器组成总线节点 ;第二种方法采用独立的MCU,这时MCU需要内部集成CAN控制器。由于第二种设计方法所用的器件少,电路关系简单,已得到广泛应用。本文重点分析AVR系列单片机内部集成的CAN控制器及其应用方法。 AT90CAN集成CAN总线控制器分析 AVR内部集成CAN控制器的芯片主要包括AT90CAN32/64/128三种单片机,它们之间的主要区别是存储空间不同。 AT90CAN32/64/128内部集成的CAN总线控制器由CAN通道和邮箱组成,其工作参数通过寄存器设置,工作过程也通过寄存器监控
[单片机]
<font color='red'>AVR</font>单片机集成CAN总线控制器分析与应用
avr单片机电源管理及其睡眠模式配置说明
睡眠模式可以使应用程序关闭 MCU 中没有使用的模块,从而降低功耗。AVR 具有不同 的睡眠模式,允许用户根据自己的应用要求实施剪裁。 /* 状态寄存器SREG bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 I T H S V N Z C I:全局中断使能位。 在I置位后,单独的中断使能由不同的中断寄存器控制。若I为0,则禁止中断。 MCU控制寄存器MCUCR bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 SM2 SE S
[单片机]
第15章 实时时钟DS1302
在前面的课程中我们已经了解到了不少关于时钟的概念,比如我们用的单片机的主时钟是11.0592M、I2C总线有一条时钟信号线SCL等,这些时钟本质上都是一个某一频率的方波信号。那么除了这些在前面新学到的时钟概念外,还有一个我们早已熟悉的不能再熟悉的时钟概念——年-月-日 时:分:秒,就是我们的钟表和日历给出的时间,它的重要程度我想就不需要多说了吧,在单片机系统里我们把它称作实时时钟,以区别于前面提到的几种方波时钟信号。实时时钟,有时也被称作墙上时钟,很形象的一个名词,对吧,大家知道他们讲的一回事就行了。本章,我们将学习实时时钟的应用,有了它,你的单片机系统就能在漫漫历史长河中找到自己的时间定位啦,可以在指定时间干某件事,或者
[单片机]
第15章 实时时钟<font color='red'>DS1302</font>
avr调试熔丝位说明,以及引脚失效
且先看数据手册里面一个很微小的段子,可能新手看的时候会不注意 数据手册208页有 在 JTAGEN 熔丝位没有被编程的情况下,四个 TAP 引脚为正常的端口引脚, TAP 控制 器处于复位状态。 一旦 JTAGEN 被编程,且 MCUCSR 寄存器的 JTD 清零,TAP 输入信 号即被拉高, JTAG 边界扫描和编程功能使能。此时 TAP 输出 (TDO) 处于悬空挂态, JTAG TAP 控制器不移位数据,因此必须连接一个上拉电阻或有上拉电阻的硬件(如扫描 链中下一个器件的 TDI 输入)。芯片付运时这个熔丝位被编程。 这个具体到最近的调试,就是说JTAG占用了PC4个端口。很恐怖吧! 最近发现PC里面两
[单片机]
解决“检测到 #include 错误
配置好VSCode的Arduino环境后可能会在编写代码时出现以下错误 检测到 #include 错误。请更新 includePath。已为此翻译单元(E:abc.ino)禁用波形曲线。C/C++(1696) 无法打开 源 文件 avr/pgmspace.h (dependency of C:Program Files (x86)ArduinohardwarearduinoavrcoresarduinoArduino.h )C/C++(1696) 这个问题是由于VSCode找不到对应的文件导致的,解决方法是,进入项目文件夹中的.vscode文件夹(用VSCode打开项目文件夹会自动新建),将c_cpp_properti
[单片机]
解决“检测到 #include 错误
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved