搜索
bottom↓
回复: 31

发一个DS1302的AVR程序,含(2000年~2099年的星期自动计算功能)。

[复制链接]

出0入0汤圆

发表于 2006-7-4 09:34:59 | 显示全部楼层 |阅读模式
前言:

最近在做DS1302,上网搜了一堆程序出来,好用得没几个:(。

调了半天终于弄出个程序好用的,可以自动计算2000年~2099年中任意一天是星期几。

经过MEGA128上的测试,目前没发现问题,现在发上来,请各位大虾帮忙测试一下。

另外我现在的程序只能做2000年~2099年中的星期计算,现在想做个任意年份的星期计算,一直没找到合适的算法,(有一个叫“蔡勒公式”的,但我按他写的程序就是不好用,可能是我太苯了)还望各位大虾不吝赐教。



虽然是在MEGA128上调的但适用于所有AVR芯片,改下管脚设置就行了。



程序不是我原创,我只是把我找到的DS1302程序和星期计算程序做了下修改使他们能适应我的系统能一起工作而已,在此向写这些程序的原作者表示敬意。



struct timechar

{

uchar nowyear;

uchar nowmonth;

uchar nowday;

uchar nowhour;

uchar nowminute;

uchar nowsecond;

uchar nowweek;

};

struct timechar nowtime;///这里存时间       





#define ds1302_rst   7                                                        /*!PORTB7 DS1302实时时钟复位线引脚 */

#define ds1302_io   6                                                         /*!PORTB6 DS1302实时时钟数据线引脚 */       

#define ds1302_sclk  5                                                         /*!PORTB5 DS1302实时时钟时钟线引脚 */



#define set_ds1302_rst_ddr()  DDRB|=1<<ds1302_rst

#define set_ds1302_rst()             PORTB|=1<<ds1302_rst

#define clr_ds1302_rst()             PORTB&=~(1<<ds1302_rst)



#define set_ds1302_io_ddr()   DDRB|=1<<ds1302_io

#define clr_ds1302_io_ddr()    DDRB&=~(1<<ds1302_io)

#define set_ds1302_io()               PORTB|=1<<ds1302_io

#define clr_ds1302_io()               PORTB&=~(1<<ds1302_io)

#define in_ds1302_io()               PINB&(1<<ds1302_io)



#define set_ds1302_sclk_ddr() DDRB|=1<<ds1302_sclk

#define set_ds1302_sclk()             PORTB|=1<<ds1302_sclk

#define clr_ds1302_sclk()              PORTB&=~(1<<ds1302_sclk)



#define ds1302_sec_reg             0x80

#define ds1302_min_reg             0x82

#define ds1302_hr_reg                     0x84

#define ds1302_date_reg              0x86

#define ds1302_month_reg            0x88

#define ds1302_day_reg             0x8a

#define ds1302_year_reg             0x8c

#define ds1302_control_reg           0x8e

#define ds1302_charger_reg    0x90

#define ds1302_clkburst_reg   0xbe



uchar BcdToBin(uchar val)

  {

  val = (val >> 4) *10+(val &0x0f); ///将BCD码转换为10进制数

  return val; ///返回10进制数

  }



uchar BinToBcd(uchar val)

  {

  return ((val / 10) *16+val % 10);

  }



void ds1302_write(uchar reg, uchar data)

  {

  uchar i = 0;

  set_ds1302_io_ddr();

  nop();

  nop();

  clr_ds1302_rst();

  nop();

  nop();

  clr_ds1302_sclk();

  nop();

  nop();

  set_ds1302_rst();

  nop();

  nop();

  for (i = 8; i > 0; i--)

    {

    if (reg &0x01)

    {

      set_ds1302_io();

    }

    else

    {

      clr_ds1302_io();

    }

    nop();

    nop();

    set_ds1302_sclk();

    nop();

    nop();

    clr_ds1302_sclk();

    nop();

    nop();

    reg >>= 1;

    }

  for (i = 8; i > 0; i--)

    {

    if (data &0x01)

    {

      set_ds1302_io();

    }

    else

    {

      clr_ds1302_io();

    }

    nop();

    nop();

    set_ds1302_sclk();

    nop();

    nop();

    clr_ds1302_sclk();

    nop();

    nop();

    data >>= 1;

    }

  clr_ds1302_rst();

  nop();

  nop();

  clr_ds1302_io_ddr();

  nop();

  nop();

  }

uchar ds1302_read(uchar reg)

  {

  uchar data = 0;

  uchar i = 0;

  reg += 1; ///读标志

  set_ds1302_io_ddr();

  nop();

  nop();

  clr_ds1302_rst();

  nop();

  nop();

  clr_ds1302_sclk();

  nop();

  nop();

  set_ds1302_rst();

  nop();

  nop();

  for (i = 8; i > 0; i--)

    {

    if (reg &0x01)

    {

      set_ds1302_io();

    }

    else

    {

      clr_ds1302_io();

    }

    nop();

    nop();

    set_ds1302_sclk();

    nop();

    nop();

    clr_ds1302_sclk();

    nop();

    nop();

    reg >>= 1;

    }

  clr_ds1302_io_ddr();

  nop();

  nop();

  for (i = 8; i > 0; i--)

    {

    data >>= 1;

    if (in_ds1302_io())

    {

      data |= 0x80;

    }

    nop();

    nop();

    set_ds1302_sclk();

    nop();

    nop();

    clr_ds1302_sclk();

    nop();

    nop();

    }

  clr_ds1302_rst();

  nop();

  nop();

  return (data);

  }

uchar check_ds1302(void)

  {

  ds1302_write(ds1302_control_reg, 0x80);

  if (ds1302_read(ds1302_control_reg) == 0x80)

  {

    return 1;

  }

  return 0;

  }

void ds1302_read_time(void)

  {

  uchar tmphour;

  nowtime.nowyear = BcdToBin(ds1302_read(ds1302_year_reg)); ///年

  nowtime.nowmonth = BcdToBin(ds1302_read(ds1302_month_reg)); ///月

  nowtime.nowday = BcdToBin(ds1302_read(ds1302_date_reg)); ///日

  nowtime.nowweek = BcdToBin(ds1302_read(ds1302_day_reg)); ///周

  tmphour = ds1302_read(ds1302_hr_reg); ///时

  nowtime.nowhour = (tmphour &0b00100000) / 32 * 20+(tmphour &0x10) / 16 * 10+(tmphour &0x0F);

  nowtime.nowminute = BcdToBin(ds1302_read(ds1302_min_reg)); ///分

  nowtime.nowsecond = BcdToBin(ds1302_read(ds1302_sec_reg)); ///秒

  }



const unsigned char WeekTab[] = {

        //闰年月星期表

  (3 << 5) + 31,///1月

  (6 << 5) + 29,///2月

  (0 << 5) + 31,///3月

  (3 << 5) + 30,///4月

  (5 << 5) + 31,//5月

  (1 << 5) + 30,//6月

  (3 << 5) + 31,//7月

  (6 << 5) + 31,//8月

  (1 << 5) + 30,//9月

  (4 << 5) + 31,//10月

  (0 << 5) + 30,//11月

  (2 << 5) + 31 //12月

};



/*!------------------------------------------------------------------------------

                                2000年~2099年星期算法

-------------------------------------------------------------------------------*/

unsigned char WeekDay20(unsigned char y, unsigned char m, unsigned char d)

{

unsigned char week, day;

  day = WeekTab[m - 1];///月表

  week = day >> 5;///月星期数

  day &= 0x1f;//月天数

  if ((m < 3) && (y & 0x03))

                {///平年

    if (m == 2) day--;///平年月天数

    week++;///平年月表+1

  }

  y = y + (y >> 2);//年+年/4

  week = (week +  y + d + 2) % 7;///(星期=年+年/4+月表+2日)%7

  return week;///返回星期

}



void ds1302_write_time(void)

  {

  uchar bcdyear;

  uchar bcdmonth;

  uchar bcdday;

  uchar bcdhour;

  uchar bcdminute;

  uchar bcdsecond;

  uchar bcdweek;



  bcdyear = BinToBcd(nowtime.nowyear);

  bcdmonth = BinToBcd(nowtime.nowmonth);

  bcdday = BinToBcd(nowtime.nowday);

  bcdhour = BinToBcd(nowtime.nowhour);

  bcdminute = BinToBcd(nowtime.nowminute);

  bcdsecond = BinToBcd(nowtime.nowsecond);

       

  nowtime.nowweek=WeekDay20(nowtime.nowyear,nowtime.nowmonth,nowtime.nowday);

  bcdweek = BinToBcd(nowtime.nowweek);

       

  ds1302_write(ds1302_control_reg, 0x00); ///关闭写保护

  ds1302_write(ds1302_sec_reg, 0x80); ///暂停

  ds1302_write(ds1302_day_reg, bcdweek); ///周       

  ds1302_write(ds1302_charger_reg, 0xa9); ///涓流充电

  ds1302_write(ds1302_year_reg, bcdyear); ///年

  ds1302_write(ds1302_month_reg, bcdmonth); ///月

  ds1302_write(ds1302_date_reg, bcdday); ///日

  ds1302_write(ds1302_hr_reg, bcdhour); ///时

  ds1302_write(ds1302_min_reg, bcdminute); ///分

  ds1302_write(ds1302_sec_reg, bcdsecond); ///秒

  ds1302_write(ds1302_control_reg, 0x80); ///打开写保护

  }
-----此内容被igoal于2006-07-04,09:41:13编辑过

出0入0汤圆

发表于 2006-7-4 09:55:27 | 显示全部楼层
不好意思。是GCC的吗

出0入0汤圆

 楼主| 发表于 2006-7-4 11:08:06 | 显示全部楼层
ICC 6.31编译

出0入0汤圆

 楼主| 发表于 2006-7-6 15:12:54 | 显示全部楼层
程序里发现点小问题,就是在读取星期信息得时候在读出当天是星期日时会读出

nowtime.nowweek=7;

需要转换一下把nowtime.nowweek=7变成nowtime.nowweek=0;这样程序就没什么问题了。

nowtime.nowweek=0 对应于 星期日

nowtime.nowweek=1 对应于 星期一

nowtime.nowweek=2 对应于 星期二

nowtime.nowweek=3 对应于 星期三

nowtime.nowweek=4 对应于 星期四

nowtime.nowweek=5 对应于 星期五

nowtime.nowweek=6 对应于 星期六

出0入0汤圆

发表于 2008-12-19 16:28:46 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-1-5 17:26:45 | 显示全部楼层
把原理图发上来呀

出0入0汤圆

发表于 2008-12-19 20:23:12 | 显示全部楼层
年月周,都可以DS1302里面自动累的,也可以读出来的,只是遇到闰年的时候,你的程序里没有自动调整芯片内部年月周的部分哦!
应该是遇到闰年就改正2月分的DATE&nbsp;,WEEK,MONTH.这三个参数,然后再自动void&nbsp;ds1302_write_time(***);这三个参数。就更好了!

出0入0汤圆

发表于 2008-12-19 18:38:36 | 显示全部楼层
星期是可以直接从1302里面读的

出0入0汤圆

发表于 2008-12-19 17:03:26 | 显示全部楼层
好像星期是能直接从DS1302里读取的出来的。。。

出0入0汤圆

发表于 2009-8-10 22:28:23 | 显示全部楼层
mark!!!

出0入42汤圆

发表于 2009-8-11 12:19:11 | 显示全部楼层
【8楼】 ww7805
这个还要原理图,,,汗

出0入0汤圆

发表于 2010-3-14 00:03:39 | 显示全部楼层
tmphour = ds1302_read(ds1302_hr_reg); ///时
  nowtime.nowhour = (tmphour &0b00100000) / 32 * 20+(tmphour &0x10) / 16 * 10+(tmphour &0x0F);
小时为什么要这么做?

出0入0汤圆

发表于 2010-8-16 00:33:47 | 显示全部楼层
顶一下.

出0入0汤圆

发表于 2010-9-8 22:09:51 | 显示全部楼层

出0入0汤圆

发表于 2010-11-5 08:28:39 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-9 21:21:43 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-1-15 09:34:12 | 显示全部楼层

出0入0汤圆

发表于 2011-1-15 10:11:13 | 显示全部楼层
回复【7楼】yunlong 飞翔
-----------------------------------------------------------------------

是吗

出0入0汤圆

发表于 2011-1-15 11:18:06 | 显示全部楼层
nowtime.nowhour = (tmphour &0b00100000) / 32 * 20+(tmphour &0x10) / 16 * 10+(tmphour &0x0F);

这一句处理的没有问题吗
假如时间用12小时表示,则下午11点,BCD为0b1011,0001,经过此句装换为nowtime.nowhour = 20+80+1=101;
假如使用24小时表示,23点,0b0010,0011 nowtime.nowhour = 20+0+3;
没有通用性,这一句很不好

出0入0汤圆

发表于 2011-1-18 11:06:04 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-1-20 13:27:38 | 显示全部楼层
好帖

出0入0汤圆

发表于 2011-3-31 11:14:02 | 显示全部楼层
不错

出0入0汤圆

发表于 2011-3-31 12:59:43 | 显示全部楼层
大家集思广议啊,我没有注意过DS1302有没有闰年的功能。

出0入0汤圆

发表于 2011-4-10 11:55:03 | 显示全部楼层
mark

出0入25汤圆

发表于 2011-6-12 14:13:06 | 显示全部楼层
顶了

出0入0汤圆

发表于 2011-6-25 14:25:33 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-6-25 15:28:42 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-6-25 18:49:46 | 显示全部楼层
/*!------------------------------------------------------------------------------
                                2000年~2099年星期算法
-------------------------------------------------------------------------------*/
unsigned char WeekDay20(unsigned char y, unsigned char m, unsigned char d)
{
unsigned char week, day;
  day = WeekTab[m - 1];///月表
  week = day >> 5;///月星期数
  day &= 0x1f;//月天数
  if ((m < 3) && (y & 0x03))
{///平年
    if (m == 2) day--;///平年月天数
    week++;///平年月表+1
  }
  y = y + (y >> 2);//年+年/4
  week = (week +  y + d + 2) % 7;///(星期=年+年/4+月表+2日)%7
  return week;///返回星期
}

下面这两句好像不用也可以,看不出这两句对计算星期有什么用,请高手指点?
day &= 0x1f;//月天数
if (m == 2) day--;///平年月天数

出0入0汤圆

发表于 2011-6-25 19:48:54 | 显示全部楼层
我试了一下,9月份算出的星期慢一天。

出0入0汤圆

发表于 2011-6-25 21:25:01 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-6-26 08:03:14 | 显示全部楼层

出0入0汤圆

发表于 2011-7-4 14:03:51 | 显示全部楼层
mark~~
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-6 07:00

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表