发现网上一些程序在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 */
上一篇:IAR for AVR delay函数
下一篇:基于无线传感器网络的煤矿安全监控系统的研究
推荐阅读最新更新时间:2024-03-16 15:21