| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690 |
- /******************************************************************************
- 版权所有:
- 文件名称: rtc_ds1338.c
- 文件版本: 01.01
- 创建作者: sunxi
- 创建日期: 2008-07-09
- 功能说明: DS1338 实时时钟驱动程序。
- 其它说明: DS1338中的年从2000年开始。
- 修改记录:
- */
- /*------------------------------- 头文件 --------------------------------------
- */
- #include "bspconfig.h"
- #include "i2c.h"
- #include "my_rtc.h"
- #include "watchdog.h"
- //#include "rt_ints.h"
- /*------------------------------- 宏定义 --------------------------------------
- */
- #if CFG_BSP_DEBUG
- #define _DEBUG_RTC
- #endif
- #define RTC_I2C_ID 0X64
- #define RTC_ADDR_EXT 0X0D
- #define RTC_ADDR_FLAG 0X0E
- #define RTC_ADDR_CONTROL 0X0F
- #define RTC_FLAG_VLF 0X02
- //rtc rx8025内部结构定义
- typedef struct
- {
- u8 second; //0~59
- u8 minute; //0~59
- u8 hour; //0~23
- u8 week; //每个星期用一个bit表示
- u8 date; //1~31
- u8 month; //1~12 *与tm结构范围不同
- u8 year; //0~99 *与tm结构范围不同
- }rtc_t;
- typedef struct
- {
- u8 ext_reg;
- u8 flg_reg;
- u8 ctl_reg; //
- }rtc_ctrl_t;
- // 此结构仅供参考,不可使用
- typedef struct
- {
- rtc_t rtc;
-
- u8 ram; // 可以任意读写
- u8 min_alm; //
- u8 hour_alm;
- u8 day_alm;
- u8 tim_cnt0;
- u8 tim_cnt1;
-
- rtc_ctrl_t rtc_ctrl;
- }rtc_all_t;
- /*------------------------------ 全局变量 -------------------------------------
- */
- int g_rtc_write_5ms; // 离实际写入时间还差多少个5ms
- rtc_t g_rtc_write_data; // 需要写入RTC芯片的时间
- /*------------------------------ 函数声明 -------------------------------------
- */
- int _rtc_read(uint32_t offset, unsigned char *buffer, uint32_t length);
- int _rtc_write(uint32_t offset, unsigned char *buffer, uint32_t length);
- /*------------------------------ 外部函数 -------------------------------------
- */
- /******************************************************************************
- 函数名称: rtc_init
- 函数版本: 01.01
- 创建作者: sunxi
- 创建日期: 2008-08-06
- 函数说明: rtc初始化。
- 参数说明: 无
- 返回值: 成功返回0.
- 修改记录:
- */
- int rtc_init(void)
- {
- return 0;
- }
- /******************************************************************************
- 函数名称: rtc_time_read
- 函数版本: 01.01
- 创建作者: sunxi
- 创建日期: 2008-08-06
- 函数说明: 从时钟芯片中读出时间。
- 参数说明:
- p_tm(out): 读出的时间存放在这个指针所指的结构中。
- 返回值:
- 0: 成功返回。
- 1: 成功返回,但是由于时钟芯片振荡器曾经停止过,所以时间可能不准。
- <0:读取失败。
-
- 修改记录:
- */
- int rtc_time_read(struct rtc_time_t *p_tm)
- {
- int ret;
- rtc_t rtc;
- u8 flag=0;
-
- //检查参数
- if(p_tm == 0)
- {
- return -1;
- }
-
- memset(&rtc, 0x00, sizeof(rtc_t));
- //读出数据
- ret = _rtc_read(0,(unsigned char *)&rtc,sizeof(rtc));
- if(ret != 0)
- {
- return -2;
- }
- ret = _rtc_read(RTC_ADDR_FLAG,&flag,1);
- if(ret != 0)
- {
- return -3;
- }
-
- //转换格式
- //清除不需要的标志
- rtc.second &= ~0x80;
- rtc.hour &= ~0xc0;
-
- //BCD转化为二进制
- p_tm->ms = (unsigned short)((rtc.second >> 4)*10 + (rtc.second & 0xf)); //秒
- p_tm->min = (unsigned char )((rtc.minute >> 4)*10 + (rtc.minute & 0xf)); //分
- p_tm->hour = (unsigned char )((rtc.hour >> 4)*10 + (rtc.hour & 0xf)); //时
- p_tm->day = (unsigned char )((rtc.date >> 4)*10 + (rtc.date & 0xf)); //日
- p_tm->month = (unsigned char )((rtc.month >> 4)*10 + (rtc.month & 0xf)); //月
- p_tm->year = (unsigned char )((rtc.year >> 4)*10 + (rtc.year & 0xf)); //年
- //s->ms
- p_tm->ms *= 1000;
-
- //如果时钟振荡器曾经停止过,时间有可能不准,返回1。
- if(flag&RTC_FLAG_VLF)
- {
- return 1;
- }
-
- return 0;
- }
- /******************************************************************************
- 函数名称: rtc_time_write
- 函数版本: 01.01
- 创建作者: sunxi
- 创建日期: 2008-08-06
- 函数说明: 将时间写入时钟芯片。
- 参数说明:
- p_tm(in): 要写入的时间存放在这个指针所指的结构中。
- 返回值:
- 0: 成功返回。
- <0:写入失败。
-
- 修改记录:
- */
- extern void sys_time_change(struct rtc_time_t *p_ct);
- int rtc_time_write(struct rtc_time_t *p_tm)
- {
- //uint32_t flags;
- int seccond,ms5;
- rtc_t rtc;
- // rt_printf("rtc_time_write.\r\n");
-
- //检查参数
- if(p_tm == 0)
- {
- return -11;
- }
-
- if(p_tm->ms > 59999)
- {
- return -12;
- }
-
- if(p_tm->min > 59)
- {
- return -13;
- }
-
- if(p_tm->hour > 23)
- {
- return -14;
- }
-
- if(p_tm->day <1 || p_tm->day > 31)
- {
- return -15;
- }
-
- if(p_tm->month <1 || p_tm->month > 12)
- {
- return -16;
- }
-
- if(p_tm->year > 99)
- {
- return -17;
- }
- //ms->s,使用下一秒作为要写入的秒值
- seccond = p_tm->ms/1000 + 1;
- ms5 = (seccond*1000 - p_tm->ms)/5;
- if(ms5 <1)
- {
- ms5 = 1;
- }
-
- if(seccond>=60)
- {
- seccond-=60;
- sys_time_change(p_tm);
- }
-
- //二进制转换为BCD
- rtc.second = (unsigned char)(((seccond /10)<<4) | (seccond %10));
- rtc.minute = (unsigned char)(((p_tm->min /10)<<4) | (p_tm->min %10));
- rtc.hour = (unsigned char)(((p_tm->hour /10)<<4) | (p_tm->hour %10));
- rtc.date = (unsigned char)(((p_tm->day /10)<<4) | (p_tm->day %10));
- rtc.month = (unsigned char)(((p_tm->month/10)<<4) | (p_tm->month %10));
- rtc.year = (unsigned char)(((p_tm->year /10)<<4) | (p_tm->year %10));
-
- //星期不使用直接赋值1
- rtc.week = 1;
-
- //写入数据
- rt_irq_save(flags);
- g_rtc_write_data = rtc;
- g_rtc_write_5ms = ms5;
- rt_irq_restore(flags);
- return 0;
- }
- void rtc_time_write_5ms(void)
- {
- int ret = 0;
- rtc_ctrl_t rtc_ctrl;
-
- if(g_rtc_write_5ms == 0)
- {
- return;
- }
-
- if(g_rtc_write_5ms == 1)
- {
- // 写入时间数据
- //ret = _rtc_write(0,(unsigned char *)&g_rtc_write_data,sizeof(g_rtc_write_data)); //jack.liu 20200921 读写RTC失能
- if(ret)
- {
- rt_printf("rtc_write_5ms0:ret=%d)\r\n",ret);
- }
- // 写入控制数据
- rtc_ctrl.ext_reg = 0x00;
- rtc_ctrl.flg_reg = 0x00;
- rtc_ctrl.ctl_reg = 0x40;// 默认2.0s温度补偿
- //ret = _rtc_write(RTC_ADDR_EXT,(unsigned char *)&rtc_ctrl,sizeof(rtc_ctrl)); //jack.liu 20200921 读写RTC失能
- if(ret)
- {
- rt_printf("rtc_write_5ms1:ret=%d)\r\n",ret);
- }
- }
-
- g_rtc_write_5ms--;
- }
- /******************************************************************************
- 函数名称: rtc_nvram_read
- 函数版本: 01.01
- 创建作者: sunxi
- 创建日期: 2008-08-07
- 函数说明: 从时钟芯片的NVRAM中读出数据。
- 参数说明:
- offset(in):需要读的数据在NVRAM中的偏移量,和length之和必须小于CFG_RTC_NVRAM_SIZE.
- buffer(out):读出数据的buffer。
- length(in): 需要读出数据的长度,和offset之和必须小于CFG_RTC_NVRAM_SIZE。
- 返回值: 成功返回0.
- 修改记录:
- */
- int rtc_nvram_read(uint32_t offset, unsigned char *buffer, uint32_t length)
- {
- //检查参数
- if(buffer == 0 || (offset + length) > CFG_RTC_NVRAM_SIZE)
- {
- return -1;
- }
- if(length == 0)
- {
- return 0;
- }
-
- return _rtc_read(offset+7,buffer,length);
- }
- /******************************************************************************
- 函数名称: rtc_nvram_write
- 函数版本: 01.01
- 创建作者: sunxi
- 创建日期: 2008-08-07
- 函数说明: 将数据写入时钟芯片的NVRAM中。
- 参数说明:
- offset(in):需要写入的数据在NVRAM中的偏移量,和length之和必须小于CFG_RTC_NVRAM_SIZE.
- buffer(in):写入数据的buffer。
- length(in): 需要写入数据的长度,和offset之和必须小于CFG_RTC_NVRAM_SIZE。
- 返回值: 成功返回0.
- 修改记录:
- */
- int rtc_nvram_write(uint32_t offset, unsigned char *buffer, uint32_t length)
- {
- //检查参数
- if(buffer == 0 || (offset + length) > CFG_RTC_NVRAM_SIZE)
- {
- return -1;
- }
- if(length == 0)
- {
- return 0;
- }
-
- return _rtc_write(offset+7, buffer, length);
- }
- /*------------------------------ 内部函数 -------------------------------------
- */
- /******************************************************************************
- 函数名称: _rtc_read
- 函数版本: 01.01
- 创建作者: sunxi
- 创建日期: 2008-08-07
- 函数说明: 从时钟芯片中读出数据。
- 参数说明:
- offset(in):需要读的数据在时钟芯片的偏移量.
- buffer(out):读出数据的buffer。
- length(in): 需要读出数据的长度。
- 返回值: 成功返回0.
- 修改记录:
- */
- int _rtc_read(uint32_t offset, unsigned char *buffer, uint32_t length)
- {
- #if 0
- unsigned char c;
- int h_i2c,ret;
- h_i2c = i2c_open(I2C_ID_RTC);
- if(h_i2c < 0)
- {
- return -1;
- }
-
- ret = -2;
-
- //等待总线释放
- I2C_WAIT_BUS_IDLE();
-
- //发送模式
- MCF_I2CR |= MCF_I2C_I2CR_MTX;
-
- //发送START信号
- MCF_I2CR |= MCF_I2C_I2CR_MSTA;
-
- //发送控制字节
- MCF_I2DR = RTC_I2C_ID;
- I2C_WAIT_COMPLETION();
- I2C_CHECK_ACK();
-
- //发送地址
- MCF_I2DR = (unsigned char)(offset);
- I2C_WAIT_COMPLETION();
- I2C_CHECK_ACK();
-
- //发送重开始信号,方向改为读
- MCF_I2CR |= MCF_I2C_I2CR_RSTA;
- MCF_I2DR = RTC_I2C_ID | 0x01;
- I2C_WAIT_COMPLETION();
- I2C_CHECK_ACK();
-
-
- //接收模式
- MCF_I2CR &= ~MCF_I2C_I2CR_MTX;
-
- //接收数据,最后一个字节不发ACK.
- if(length == 1)
- {
- MCF_I2CR |= MCF_I2C_I2CR_TXAK; //不发ACK
- c = MCF_I2DR; //空读,启动下一个字节的读
- I2C_WAIT_COMPLETION();
- *buffer++ = MCF_I2DR;
- I2C_WAIT_COMPLETION();
-
- }
- else
- {
- //循环接收length个字节。
- MCF_I2CR &= ~MCF_I2C_I2CR_TXAK; //发送ACK
- c = MCF_I2DR; //空读,启动下一个字节的读
- I2C_WAIT_COMPLETION();
-
- while(length--)
- {
- if(length == 1)
- {
-
- MCF_I2CR |= MCF_I2C_I2CR_TXAK; //不发ACK
- }
- *buffer++ = MCF_I2DR; //读数据,并启动下一个字节的读。
- I2C_WAIT_COMPLETION();
- }
- }
-
- ret = 0;
-
- LABEL_END:
- //发送STOP信号
- MCF_I2CR &= ~MCF_I2C_I2CR_MSTA;
-
- i2c_close(h_i2c);
-
- return ret;
- #endif
- return 0;
- }
- /******************************************************************************
- 函数名称: _rtc_write
- 函数版本: 01.01
- 创建作者: sunxi
- 创建日期: 2008-08-07
- 函数说明: 将数据写入时钟芯片中。
- 参数说明:
- offset(in):需要写入的数据在时钟芯片中的偏移量.
- buffer(in):写入数据的buffer。
- length(in): 需要写入数据的长度。
- 返回值: 成功返回0.
- 修改记录:
- */
- int _rtc_write(uint32_t offset, unsigned char *buffer, uint32_t length)
- {
- #if 0
- int h_i2c,ret;
-
- h_i2c = i2c_open(I2C_ID_RTC);
- if(h_i2c < 0)
- {
-
- return -1;
- }
-
- ret = -2;
-
- //等待总线释放
- I2C_WAIT_BUS_IDLE();
-
- //发送模式
- // MCF_I2CR |= MCF_I2C_I2CR_MTX;
-
- //发送START信号
- // MCF_I2CR |= MCF_I2C_I2CR_MSTA;
-
- //发送控制字节
- MCF_I2DR = RTC_I2C_ID;
- I2C_WAIT_COMPLETION();
- I2C_CHECK_ACK();
-
- //发送地址
- MCF_I2DR = (unsigned char)(offset);
- I2C_WAIT_COMPLETION();
- I2C_CHECK_ACK();
-
- //发送数据
- while(length--)
- {
- MCF_I2DR = *buffer++;
- I2C_WAIT_COMPLETION();
- I2C_CHECK_ACK();
- }
-
- ret = 0;
-
- LABEL_END:
- //发送STOP信号
- // MCF_I2CR &= ~MCF_I2C_I2CR_MSTA;
- i2c_close(h_i2c);
-
- return ret;
- #endif
- return 0;
- }
- /*------------------------------ 测试函数 -------------------------------------
- */
- #ifdef _DEBUG_RTC
- #include "ustimer.h"
- #include "rt.h"
- #define RTC_TEST_SIZE 1
- int rtc_test(void)
- {
- int ret;
- uint32_t us0,us;
- uint32_t i,offset,length;
- unsigned char buffer[CFG_RTC_BUFFER_SIZE];
- struct rtc_time_t tm0;
-
- rt_printf("rtc_test start...\r\n");
-
- offset = 0;
- while(offset < CFG_RTC_NVRAM_SIZE)
- {
- //写
- length = (CFG_RTC_NVRAM_SIZE - offset) > RTC_TEST_SIZE ? RTC_TEST_SIZE : (CFG_RTC_NVRAM_SIZE - offset);
- for(i=0;i<length;i++)
- {
-
- buffer[i] = (unsigned char)(offset + i + 0x37);
- }
- us0 = ustimer_get_origin();
- ret = rtc_nvram_write(offset,(unsigned char *)buffer,length);
- us = ustimer_get_duration(us0);
- // rt_printf("rtc_nvram_write:(offset=%d,ret=%d,us=%d)\r\n",offset,ret,us);
- if(ret != 0)
- {
-
- break;
- }
-
- offset += length;
- }
-
- offset = 0;
- while(offset < CFG_RTC_NVRAM_SIZE)
- {
- //读
- length = (CFG_RTC_NVRAM_SIZE - offset) > RTC_TEST_SIZE ? RTC_TEST_SIZE : (CFG_RTC_NVRAM_SIZE - offset);
- memset(buffer,0,RTC_TEST_SIZE);
- us0 = ustimer_get_origin();
- ret = rtc_nvram_read(offset,(unsigned char *)buffer,length);
- us = ustimer_get_duration(us0);
- // rt_printf("rtc_nvram_read:(offset=%d,ret=%d,us=%d)\r\n",offset,ret,us);
-
- if(ret != 0)
- {
-
- break;
- }
-
- //比较
- for(i=0;i<length;i++)
- {
- if(buffer[i] != (unsigned char)(offset + i + 0x37))
- {
-
- break;
- }
- }
- if(i!= length)
- {
- rt_printf("compare error(offset=%lu,i=%lu)!\r\n",offset,i);
- break;
- }
-
- offset += length;
-
- }
-
- if(offset == CFG_RTC_NVRAM_SIZE)
- {
-
- rt_printf("rtc_nvram ok!\r\n\n");
- }
- else
- {
-
- rt_printf("rtc_nvram fail!\r\n\n");
- }
-
- //开始测试时间
- ret = rtc_time_read(&tm0);
- if(ret == 1)
- {
-
- rt_printf("rtc was stoped!\r\n");
- }
- else if(ret == 0)
- {
-
- rt_printf("rtc is running!\r\n");
- }
- else
- {
-
- rt_printf("rtc_time_read test fail!");
- }
- tm0.ms = 8000;
- tm0.min = 28;
- tm0.hour = 14;
- tm0.day = 19;
- tm0.month = 10;
- tm0.year = 2010 - 2000;
- #if 0
- ret = rtc_time_write(&tm0);
- if(ret == 0)
- {
-
- rt_printf("rtc_time_write ok!\r\n\n");
- }
- else
- {
-
- rt_printf("rtc_time_write fail(ret=%d)!\r\n\n",ret);
- }
- #endif
-
- us0 = ustimer_get_origin();
- while(1)
- {
- ret = rtc_time_read(&tm0);
- if(ret == 0 || ret == 1)
- {
-
- rt_printf("date(ret=%d): %04d-%02d-%02d time: %02d:%02d:%05d!\r\n",
- ret,
- tm0.year + 2000,
- tm0.month,
- tm0.day,
- tm0.hour,
- tm0.min,
- tm0.ms
- );
- }
- else
- {
-
- rt_printf("rtc_time_read fail(ret=%d)!\r\n\n",ret);
- }
- watchdog_feed_mainloop();
-
- //精确间隔1S循环。
- ustimer_delay_origin(us0,USTIMER_SEC);
- us0 += USTIMER_SEC;
- }
-
- return 0;
- }
- #endif
|