rtc_rx8025.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. /******************************************************************************
  2. 版权所有:
  3. 文件名称: rtc_ds1338.c
  4. 文件版本: 01.01
  5. 创建作者: sunxi
  6. 创建日期: 2008-07-09
  7. 功能说明: DS1338 实时时钟驱动程序。
  8. 其它说明: DS1338中的年从2000年开始。
  9. 修改记录:
  10. */
  11. /*------------------------------- 头文件 --------------------------------------
  12. */
  13. #include "bspconfig.h"
  14. #include "i2c.h"
  15. #include "my_rtc.h"
  16. #include "watchdog.h"
  17. //#include "rt_ints.h"
  18. /*------------------------------- 宏定义 --------------------------------------
  19. */
  20. #if CFG_BSP_DEBUG
  21. #define _DEBUG_RTC
  22. #endif
  23. #define RTC_I2C_ID 0X64
  24. #define RTC_ADDR_EXT 0X0D
  25. #define RTC_ADDR_FLAG 0X0E
  26. #define RTC_ADDR_CONTROL 0X0F
  27. #define RTC_FLAG_VLF 0X02
  28. //rtc rx8025内部结构定义
  29. typedef struct
  30. {
  31. u8 second; //0~59
  32. u8 minute; //0~59
  33. u8 hour; //0~23
  34. u8 week; //每个星期用一个bit表示
  35. u8 date; //1~31
  36. u8 month; //1~12 *与tm结构范围不同
  37. u8 year; //0~99 *与tm结构范围不同
  38. }rtc_t;
  39. typedef struct
  40. {
  41. u8 ext_reg;
  42. u8 flg_reg;
  43. u8 ctl_reg; //
  44. }rtc_ctrl_t;
  45. // 此结构仅供参考,不可使用
  46. typedef struct
  47. {
  48. rtc_t rtc;
  49. u8 ram; // 可以任意读写
  50. u8 min_alm; //
  51. u8 hour_alm;
  52. u8 day_alm;
  53. u8 tim_cnt0;
  54. u8 tim_cnt1;
  55. rtc_ctrl_t rtc_ctrl;
  56. }rtc_all_t;
  57. /*------------------------------ 全局变量 -------------------------------------
  58. */
  59. int g_rtc_write_5ms; // 离实际写入时间还差多少个5ms
  60. rtc_t g_rtc_write_data; // 需要写入RTC芯片的时间
  61. /*------------------------------ 函数声明 -------------------------------------
  62. */
  63. int _rtc_read(uint32_t offset, unsigned char *buffer, uint32_t length);
  64. int _rtc_write(uint32_t offset, unsigned char *buffer, uint32_t length);
  65. /*------------------------------ 外部函数 -------------------------------------
  66. */
  67. /******************************************************************************
  68. 函数名称: rtc_init
  69. 函数版本: 01.01
  70. 创建作者: sunxi
  71. 创建日期: 2008-08-06
  72. 函数说明: rtc初始化。
  73. 参数说明: 无
  74. 返回值: 成功返回0.
  75. 修改记录:
  76. */
  77. int rtc_init(void)
  78. {
  79. return 0;
  80. }
  81. /******************************************************************************
  82. 函数名称: rtc_time_read
  83. 函数版本: 01.01
  84. 创建作者: sunxi
  85. 创建日期: 2008-08-06
  86. 函数说明: 从时钟芯片中读出时间。
  87. 参数说明:
  88. p_tm(out): 读出的时间存放在这个指针所指的结构中。
  89. 返回值:
  90. 0: 成功返回。
  91. 1: 成功返回,但是由于时钟芯片振荡器曾经停止过,所以时间可能不准。
  92. <0:读取失败。
  93. 修改记录:
  94. */
  95. int rtc_time_read(struct rtc_time_t *p_tm)
  96. {
  97. int ret;
  98. rtc_t rtc;
  99. u8 flag=0;
  100. //检查参数
  101. if(p_tm == 0)
  102. {
  103. return -1;
  104. }
  105. memset(&rtc, 0x00, sizeof(rtc_t));
  106. //读出数据
  107. ret = _rtc_read(0,(unsigned char *)&rtc,sizeof(rtc));
  108. if(ret != 0)
  109. {
  110. return -2;
  111. }
  112. ret = _rtc_read(RTC_ADDR_FLAG,&flag,1);
  113. if(ret != 0)
  114. {
  115. return -3;
  116. }
  117. //转换格式
  118. //清除不需要的标志
  119. rtc.second &= ~0x80;
  120. rtc.hour &= ~0xc0;
  121. //BCD转化为二进制
  122. p_tm->ms = (unsigned short)((rtc.second >> 4)*10 + (rtc.second & 0xf)); //秒
  123. p_tm->min = (unsigned char )((rtc.minute >> 4)*10 + (rtc.minute & 0xf)); //分
  124. p_tm->hour = (unsigned char )((rtc.hour >> 4)*10 + (rtc.hour & 0xf)); //时
  125. p_tm->day = (unsigned char )((rtc.date >> 4)*10 + (rtc.date & 0xf)); //日
  126. p_tm->month = (unsigned char )((rtc.month >> 4)*10 + (rtc.month & 0xf)); //月
  127. p_tm->year = (unsigned char )((rtc.year >> 4)*10 + (rtc.year & 0xf)); //年
  128. //s->ms
  129. p_tm->ms *= 1000;
  130. //如果时钟振荡器曾经停止过,时间有可能不准,返回1。
  131. if(flag&RTC_FLAG_VLF)
  132. {
  133. return 1;
  134. }
  135. return 0;
  136. }
  137. /******************************************************************************
  138. 函数名称: rtc_time_write
  139. 函数版本: 01.01
  140. 创建作者: sunxi
  141. 创建日期: 2008-08-06
  142. 函数说明: 将时间写入时钟芯片。
  143. 参数说明:
  144. p_tm(in): 要写入的时间存放在这个指针所指的结构中。
  145. 返回值:
  146. 0: 成功返回。
  147. <0:写入失败。
  148. 修改记录:
  149. */
  150. extern void sys_time_change(struct rtc_time_t *p_ct);
  151. int rtc_time_write(struct rtc_time_t *p_tm)
  152. {
  153. //uint32_t flags;
  154. int seccond,ms5;
  155. rtc_t rtc;
  156. // rt_printf("rtc_time_write.\r\n");
  157. //检查参数
  158. if(p_tm == 0)
  159. {
  160. return -11;
  161. }
  162. if(p_tm->ms > 59999)
  163. {
  164. return -12;
  165. }
  166. if(p_tm->min > 59)
  167. {
  168. return -13;
  169. }
  170. if(p_tm->hour > 23)
  171. {
  172. return -14;
  173. }
  174. if(p_tm->day <1 || p_tm->day > 31)
  175. {
  176. return -15;
  177. }
  178. if(p_tm->month <1 || p_tm->month > 12)
  179. {
  180. return -16;
  181. }
  182. if(p_tm->year > 99)
  183. {
  184. return -17;
  185. }
  186. //ms->s,使用下一秒作为要写入的秒值
  187. seccond = p_tm->ms/1000 + 1;
  188. ms5 = (seccond*1000 - p_tm->ms)/5;
  189. if(ms5 <1)
  190. {
  191. ms5 = 1;
  192. }
  193. if(seccond>=60)
  194. {
  195. seccond-=60;
  196. sys_time_change(p_tm);
  197. }
  198. //二进制转换为BCD
  199. rtc.second = (unsigned char)(((seccond /10)<<4) | (seccond %10));
  200. rtc.minute = (unsigned char)(((p_tm->min /10)<<4) | (p_tm->min %10));
  201. rtc.hour = (unsigned char)(((p_tm->hour /10)<<4) | (p_tm->hour %10));
  202. rtc.date = (unsigned char)(((p_tm->day /10)<<4) | (p_tm->day %10));
  203. rtc.month = (unsigned char)(((p_tm->month/10)<<4) | (p_tm->month %10));
  204. rtc.year = (unsigned char)(((p_tm->year /10)<<4) | (p_tm->year %10));
  205. //星期不使用直接赋值1
  206. rtc.week = 1;
  207. //写入数据
  208. rt_irq_save(flags);
  209. g_rtc_write_data = rtc;
  210. g_rtc_write_5ms = ms5;
  211. rt_irq_restore(flags);
  212. return 0;
  213. }
  214. void rtc_time_write_5ms(void)
  215. {
  216. int ret = 0;
  217. rtc_ctrl_t rtc_ctrl;
  218. if(g_rtc_write_5ms == 0)
  219. {
  220. return;
  221. }
  222. if(g_rtc_write_5ms == 1)
  223. {
  224. // 写入时间数据
  225. //ret = _rtc_write(0,(unsigned char *)&g_rtc_write_data,sizeof(g_rtc_write_data)); //jack.liu 20200921 读写RTC失能
  226. if(ret)
  227. {
  228. rt_printf("rtc_write_5ms0:ret=%d)\r\n",ret);
  229. }
  230. // 写入控制数据
  231. rtc_ctrl.ext_reg = 0x00;
  232. rtc_ctrl.flg_reg = 0x00;
  233. rtc_ctrl.ctl_reg = 0x40;// 默认2.0s温度补偿
  234. //ret = _rtc_write(RTC_ADDR_EXT,(unsigned char *)&rtc_ctrl,sizeof(rtc_ctrl)); //jack.liu 20200921 读写RTC失能
  235. if(ret)
  236. {
  237. rt_printf("rtc_write_5ms1:ret=%d)\r\n",ret);
  238. }
  239. }
  240. g_rtc_write_5ms--;
  241. }
  242. /******************************************************************************
  243. 函数名称: rtc_nvram_read
  244. 函数版本: 01.01
  245. 创建作者: sunxi
  246. 创建日期: 2008-08-07
  247. 函数说明: 从时钟芯片的NVRAM中读出数据。
  248. 参数说明:
  249. offset(in):需要读的数据在NVRAM中的偏移量,和length之和必须小于CFG_RTC_NVRAM_SIZE.
  250. buffer(out):读出数据的buffer。
  251. length(in): 需要读出数据的长度,和offset之和必须小于CFG_RTC_NVRAM_SIZE。
  252. 返回值: 成功返回0.
  253. 修改记录:
  254. */
  255. int rtc_nvram_read(uint32_t offset, unsigned char *buffer, uint32_t length)
  256. {
  257. //检查参数
  258. if(buffer == 0 || (offset + length) > CFG_RTC_NVRAM_SIZE)
  259. {
  260. return -1;
  261. }
  262. if(length == 0)
  263. {
  264. return 0;
  265. }
  266. return _rtc_read(offset+7,buffer,length);
  267. }
  268. /******************************************************************************
  269. 函数名称: rtc_nvram_write
  270. 函数版本: 01.01
  271. 创建作者: sunxi
  272. 创建日期: 2008-08-07
  273. 函数说明: 将数据写入时钟芯片的NVRAM中。
  274. 参数说明:
  275. offset(in):需要写入的数据在NVRAM中的偏移量,和length之和必须小于CFG_RTC_NVRAM_SIZE.
  276. buffer(in):写入数据的buffer。
  277. length(in): 需要写入数据的长度,和offset之和必须小于CFG_RTC_NVRAM_SIZE。
  278. 返回值: 成功返回0.
  279. 修改记录:
  280. */
  281. int rtc_nvram_write(uint32_t offset, unsigned char *buffer, uint32_t length)
  282. {
  283. //检查参数
  284. if(buffer == 0 || (offset + length) > CFG_RTC_NVRAM_SIZE)
  285. {
  286. return -1;
  287. }
  288. if(length == 0)
  289. {
  290. return 0;
  291. }
  292. return _rtc_write(offset+7, buffer, length);
  293. }
  294. /*------------------------------ 内部函数 -------------------------------------
  295. */
  296. /******************************************************************************
  297. 函数名称: _rtc_read
  298. 函数版本: 01.01
  299. 创建作者: sunxi
  300. 创建日期: 2008-08-07
  301. 函数说明: 从时钟芯片中读出数据。
  302. 参数说明:
  303. offset(in):需要读的数据在时钟芯片的偏移量.
  304. buffer(out):读出数据的buffer。
  305. length(in): 需要读出数据的长度。
  306. 返回值: 成功返回0.
  307. 修改记录:
  308. */
  309. int _rtc_read(uint32_t offset, unsigned char *buffer, uint32_t length)
  310. {
  311. #if 0
  312. unsigned char c;
  313. int h_i2c,ret;
  314. h_i2c = i2c_open(I2C_ID_RTC);
  315. if(h_i2c < 0)
  316. {
  317. return -1;
  318. }
  319. ret = -2;
  320. //等待总线释放
  321. I2C_WAIT_BUS_IDLE();
  322. //发送模式
  323. MCF_I2CR |= MCF_I2C_I2CR_MTX;
  324. //发送START信号
  325. MCF_I2CR |= MCF_I2C_I2CR_MSTA;
  326. //发送控制字节
  327. MCF_I2DR = RTC_I2C_ID;
  328. I2C_WAIT_COMPLETION();
  329. I2C_CHECK_ACK();
  330. //发送地址
  331. MCF_I2DR = (unsigned char)(offset);
  332. I2C_WAIT_COMPLETION();
  333. I2C_CHECK_ACK();
  334. //发送重开始信号,方向改为读
  335. MCF_I2CR |= MCF_I2C_I2CR_RSTA;
  336. MCF_I2DR = RTC_I2C_ID | 0x01;
  337. I2C_WAIT_COMPLETION();
  338. I2C_CHECK_ACK();
  339. //接收模式
  340. MCF_I2CR &= ~MCF_I2C_I2CR_MTX;
  341. //接收数据,最后一个字节不发ACK.
  342. if(length == 1)
  343. {
  344. MCF_I2CR |= MCF_I2C_I2CR_TXAK; //不发ACK
  345. c = MCF_I2DR; //空读,启动下一个字节的读
  346. I2C_WAIT_COMPLETION();
  347. *buffer++ = MCF_I2DR;
  348. I2C_WAIT_COMPLETION();
  349. }
  350. else
  351. {
  352. //循环接收length个字节。
  353. MCF_I2CR &= ~MCF_I2C_I2CR_TXAK; //发送ACK
  354. c = MCF_I2DR; //空读,启动下一个字节的读
  355. I2C_WAIT_COMPLETION();
  356. while(length--)
  357. {
  358. if(length == 1)
  359. {
  360. MCF_I2CR |= MCF_I2C_I2CR_TXAK; //不发ACK
  361. }
  362. *buffer++ = MCF_I2DR; //读数据,并启动下一个字节的读。
  363. I2C_WAIT_COMPLETION();
  364. }
  365. }
  366. ret = 0;
  367. LABEL_END:
  368. //发送STOP信号
  369. MCF_I2CR &= ~MCF_I2C_I2CR_MSTA;
  370. i2c_close(h_i2c);
  371. return ret;
  372. #endif
  373. return 0;
  374. }
  375. /******************************************************************************
  376. 函数名称: _rtc_write
  377. 函数版本: 01.01
  378. 创建作者: sunxi
  379. 创建日期: 2008-08-07
  380. 函数说明: 将数据写入时钟芯片中。
  381. 参数说明:
  382. offset(in):需要写入的数据在时钟芯片中的偏移量.
  383. buffer(in):写入数据的buffer。
  384. length(in): 需要写入数据的长度。
  385. 返回值: 成功返回0.
  386. 修改记录:
  387. */
  388. int _rtc_write(uint32_t offset, unsigned char *buffer, uint32_t length)
  389. {
  390. #if 0
  391. int h_i2c,ret;
  392. h_i2c = i2c_open(I2C_ID_RTC);
  393. if(h_i2c < 0)
  394. {
  395. return -1;
  396. }
  397. ret = -2;
  398. //等待总线释放
  399. I2C_WAIT_BUS_IDLE();
  400. //发送模式
  401. // MCF_I2CR |= MCF_I2C_I2CR_MTX;
  402. //发送START信号
  403. // MCF_I2CR |= MCF_I2C_I2CR_MSTA;
  404. //发送控制字节
  405. MCF_I2DR = RTC_I2C_ID;
  406. I2C_WAIT_COMPLETION();
  407. I2C_CHECK_ACK();
  408. //发送地址
  409. MCF_I2DR = (unsigned char)(offset);
  410. I2C_WAIT_COMPLETION();
  411. I2C_CHECK_ACK();
  412. //发送数据
  413. while(length--)
  414. {
  415. MCF_I2DR = *buffer++;
  416. I2C_WAIT_COMPLETION();
  417. I2C_CHECK_ACK();
  418. }
  419. ret = 0;
  420. LABEL_END:
  421. //发送STOP信号
  422. // MCF_I2CR &= ~MCF_I2C_I2CR_MSTA;
  423. i2c_close(h_i2c);
  424. return ret;
  425. #endif
  426. return 0;
  427. }
  428. /*------------------------------ 测试函数 -------------------------------------
  429. */
  430. #ifdef _DEBUG_RTC
  431. #include "ustimer.h"
  432. #include "rt.h"
  433. #define RTC_TEST_SIZE 1
  434. int rtc_test(void)
  435. {
  436. int ret;
  437. uint32_t us0,us;
  438. uint32_t i,offset,length;
  439. unsigned char buffer[CFG_RTC_BUFFER_SIZE];
  440. struct rtc_time_t tm0;
  441. rt_printf("rtc_test start...\r\n");
  442. offset = 0;
  443. while(offset < CFG_RTC_NVRAM_SIZE)
  444. {
  445. //写
  446. length = (CFG_RTC_NVRAM_SIZE - offset) > RTC_TEST_SIZE ? RTC_TEST_SIZE : (CFG_RTC_NVRAM_SIZE - offset);
  447. for(i=0;i<length;i++)
  448. {
  449. buffer[i] = (unsigned char)(offset + i + 0x37);
  450. }
  451. us0 = ustimer_get_origin();
  452. ret = rtc_nvram_write(offset,(unsigned char *)buffer,length);
  453. us = ustimer_get_duration(us0);
  454. // rt_printf("rtc_nvram_write:(offset=%d,ret=%d,us=%d)\r\n",offset,ret,us);
  455. if(ret != 0)
  456. {
  457. break;
  458. }
  459. offset += length;
  460. }
  461. offset = 0;
  462. while(offset < CFG_RTC_NVRAM_SIZE)
  463. {
  464. //读
  465. length = (CFG_RTC_NVRAM_SIZE - offset) > RTC_TEST_SIZE ? RTC_TEST_SIZE : (CFG_RTC_NVRAM_SIZE - offset);
  466. memset(buffer,0,RTC_TEST_SIZE);
  467. us0 = ustimer_get_origin();
  468. ret = rtc_nvram_read(offset,(unsigned char *)buffer,length);
  469. us = ustimer_get_duration(us0);
  470. // rt_printf("rtc_nvram_read:(offset=%d,ret=%d,us=%d)\r\n",offset,ret,us);
  471. if(ret != 0)
  472. {
  473. break;
  474. }
  475. //比较
  476. for(i=0;i<length;i++)
  477. {
  478. if(buffer[i] != (unsigned char)(offset + i + 0x37))
  479. {
  480. break;
  481. }
  482. }
  483. if(i!= length)
  484. {
  485. rt_printf("compare error(offset=%lu,i=%lu)!\r\n",offset,i);
  486. break;
  487. }
  488. offset += length;
  489. }
  490. if(offset == CFG_RTC_NVRAM_SIZE)
  491. {
  492. rt_printf("rtc_nvram ok!\r\n\n");
  493. }
  494. else
  495. {
  496. rt_printf("rtc_nvram fail!\r\n\n");
  497. }
  498. //开始测试时间
  499. ret = rtc_time_read(&tm0);
  500. if(ret == 1)
  501. {
  502. rt_printf("rtc was stoped!\r\n");
  503. }
  504. else if(ret == 0)
  505. {
  506. rt_printf("rtc is running!\r\n");
  507. }
  508. else
  509. {
  510. rt_printf("rtc_time_read test fail!");
  511. }
  512. tm0.ms = 8000;
  513. tm0.min = 28;
  514. tm0.hour = 14;
  515. tm0.day = 19;
  516. tm0.month = 10;
  517. tm0.year = 2010 - 2000;
  518. #if 0
  519. ret = rtc_time_write(&tm0);
  520. if(ret == 0)
  521. {
  522. rt_printf("rtc_time_write ok!\r\n\n");
  523. }
  524. else
  525. {
  526. rt_printf("rtc_time_write fail(ret=%d)!\r\n\n",ret);
  527. }
  528. #endif
  529. us0 = ustimer_get_origin();
  530. while(1)
  531. {
  532. ret = rtc_time_read(&tm0);
  533. if(ret == 0 || ret == 1)
  534. {
  535. rt_printf("date(ret=%d): %04d-%02d-%02d time: %02d:%02d:%05d!\r\n",
  536. ret,
  537. tm0.year + 2000,
  538. tm0.month,
  539. tm0.day,
  540. tm0.hour,
  541. tm0.min,
  542. tm0.ms
  543. );
  544. }
  545. else
  546. {
  547. rt_printf("rtc_time_read fail(ret=%d)!\r\n\n",ret);
  548. }
  549. watchdog_feed_mainloop();
  550. //精确间隔1S循环。
  551. ustimer_delay_origin(us0,USTIMER_SEC);
  552. us0 += USTIMER_SEC;
  553. }
  554. return 0;
  555. }
  556. #endif