ds1302.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. //ds1302.c:
  2. /************ DS1302程序 ************
  3. * 版本.........: 1.0
  4. * 作者.........: 陈利栋
  5. * 文件名.......: ds1302.c
  6. * 创建时间.....: 2010.11.11
  7. * 最后修改.....: 2010.11.11
  8. ************************************/
  9. #include "ds1302.h"
  10. #include "ds1302_config.h"
  11. volatile unsigned char DS1302_Update = 0;
  12. DS1302_DateTime_t DS1302_DateTime;
  13. // 发送一个字节,不操作CE
  14. static void DS1302_TxByte ( unsigned char byte )
  15. {
  16. unsigned char i = 0;
  17. DS1302_IO_OUT;
  18. for ( i = 0; i < 8; i++ )
  19. {
  20. DS1302_SCLK_0;
  21. DS1302_DELAY_T_CL;
  22. if ( byte & 0x01 )
  23. {
  24. DS1302_IO_1;
  25. }
  26. else
  27. {
  28. DS1302_IO_0;
  29. }
  30. DS1302_DELAY_T_DC;
  31. DS1302_SCLK_1;
  32. DS1302_DELAY_T_CH;
  33. byte >>= 1;
  34. }
  35. }
  36. // 接收一个字节,不操作CE
  37. static unsigned char DS1302_RxByte ( void )
  38. {
  39. unsigned char i = 0;
  40. unsigned char byte = 0;
  41. DS1302_IO_IN;
  42. DS1302_IO_1;
  43. for ( i = 0; i < 8; i++ )
  44. {
  45. DS1302_SCLK_0;
  46. DS1302_DELAY_T_CDD;
  47. byte >>= 1;
  48. if ( DS1302_IO_VALUE )
  49. {
  50. byte |= 0x80;
  51. }
  52. DS1302_SCLK_1;
  53. DS1302_DELAY_T_CH;
  54. }
  55. return byte;
  56. }
  57. static void DS1302_WriteByte ( unsigned char address, unsigned char _data )
  58. {
  59. DS1302_SCLK_0;
  60. DS1302_CE_1;
  61. DS1302_DELAY_T_CC;
  62. DS1302_TxByte ( address );
  63. DS1302_TxByte ( _data );
  64. DS1302_SCLK_0;
  65. DS1302_DELAY_T_CCH;
  66. DS1302_CE_0;
  67. DS1302_DELAY_T_CWH;
  68. }
  69. static unsigned char DS1302_ReadByte ( unsigned char address )
  70. {
  71. unsigned char _data = 0;
  72. DS1302_SCLK_0;
  73. DS1302_CE_1;
  74. DS1302_DELAY_T_CC;
  75. DS1302_TxByte ( address | 0x01 );
  76. _data = DS1302_RxByte();
  77. DS1302_SCLK_0;
  78. DS1302_DELAY_T_CCH;
  79. DS1302_CE_0;
  80. DS1302_DELAY_T_CWH;
  81. return _data;
  82. }
  83. #if DS1302_AUTO_TO_DEC == 1
  84. static unsigned char DecToBcd ( unsigned char d )
  85. {
  86. return ( ( ( ( d ) / 10 ) << 4 ) + ( ( d ) % 10 ) );
  87. }
  88. static unsigned char BcdToDec ( unsigned char b )
  89. {
  90. return ( ( ( ( b ) >> 4 ) * 10 ) + ( ( b ) & 0x0f ) );
  91. }
  92. #endif /* DS1302_AUTO_TO_DEC == 1 */
  93. void DS1302_SetDateTime ( void )
  94. {
  95. unsigned char temp = 0;
  96. DS1302_WriteByte ( DS1302_WRITE_PROTECT_ADDR, 0x00 ); // 关闭写保护
  97. DS1302_WriteByte ( DS1302_YEAR_ADDR, DEC_TO_BCD ( DS1302_DateTime.Year ) );
  98. DS1302_WriteByte ( DS1302_MONTH_ADDR, DEC_TO_BCD ( DS1302_DateTime.Month ) );
  99. DS1302_WriteByte ( DS1302_DATE_ADDR, DEC_TO_BCD ( DS1302_DateTime.Date ) );
  100. DS1302_WriteByte ( DS1302_MINUTE_ADDR, DEC_TO_BCD ( DS1302_DateTime.Minute ) );
  101. DS1302_WriteByte ( DS1302_SECOND_ADDR, DEC_TO_BCD ( DS1302_DateTime.Second ) );
  102. DS1302_WriteByte ( DS1302_DAY_ADDR, DEC_TO_BCD ( GetDayFromDate ( DS1302_DateTime.Year, DS1302_DateTime.Month, DS1302_DateTime.Date ) ) );
  103. temp = DEC_TO_BCD ( DS1302_DateTime.Hour );
  104. if ( DS1302_DateTime.HourMode == _12_hours )
  105. {
  106. temp |= 0x80;
  107. temp |= ( DS1302_DateTime.AM_PM == pm ? 0x20 : 0 );
  108. }
  109. DS1302_WriteByte ( DS1302_HOUR_ADDR, temp );
  110. DS1302_WriteByte ( DS1302_WRITE_PROTECT_ADDR, 0x80 ); // 写入完毕后设置写保护
  111. }
  112. void DS1302_GetDateTime ( void )
  113. {
  114. unsigned char temp = 0;
  115. DS1302_Update = 0;
  116. DS1302_DateTime.Year = BCD_TO_DEC ( DS1302_ReadByte ( DS1302_YEAR_ADDR ) );
  117. DS1302_DateTime.Month = BCD_TO_DEC ( DS1302_ReadByte ( DS1302_MONTH_ADDR ) );
  118. DS1302_DateTime.Date = BCD_TO_DEC ( DS1302_ReadByte ( DS1302_DATE_ADDR ) );
  119. DS1302_DateTime.Minute = BCD_TO_DEC ( DS1302_ReadByte ( DS1302_MINUTE_ADDR ) );
  120. DS1302_DateTime.Second = BCD_TO_DEC ( DS1302_ReadByte ( DS1302_SECOND_ADDR ) );
  121. DS1302_DateTime.Day = BCD_TO_DEC ( DS1302_ReadByte ( DS1302_DAY_ADDR ) );
  122. temp = DS1302_ReadByte ( DS1302_HOUR_ADDR );
  123. if ( temp & 0x80 )
  124. {
  125. DS1302_DateTime.HourMode = _12_hours;
  126. DS1302_DateTime.AM_PM = ( ( temp & 0x20 ) ? pm : am );
  127. temp &= 0x1f;
  128. }
  129. DS1302_DateTime.Hour = BCD_TO_DEC ( temp );
  130. }
  131. void DS1302_Scan ( void )
  132. {
  133. static unsigned second_last = 0;
  134. DS1302_DateTime.Second = BCD_TO_DEC ( DS1302_ReadByte ( DS1302_SECOND_ADDR ) );
  135. if ( second_last != DS1302_DateTime.Second )
  136. {
  137. second_last = DS1302_DateTime.Second;
  138. DS1302_Update = 1;
  139. }
  140. }
  141. void DS1302_Init ( void )
  142. {
  143. #if DS1302_def
  144. // 端口初始化
  145. DS1302_CE_0;
  146. DS1302_CE_OUT;
  147. DS1302_SCLK_0;
  148. DS1302_SCLK_OUT;
  149. DS1302_WriteByte ( DS1302_WRITE_PROTECT_ADDR, 0x00 ); // 关闭写保护
  150. DS1302_WriteByte ( DS1302_TRICKLE_CHARGE_ADDR, 0xa7 ); // 使能涓流充电 1 Diode, 8kΩ
  151. if ( DS1302_ReadByte ( DS1302_SECOND_ADDR ) & 0x80 ) // 振荡器未启动
  152. DS1302_WriteByte ( DS1302_SECOND_ADDR, 0x00 ); // 启动振荡器
  153. DS1302_WriteByte ( DS1302_WRITE_PROTECT_ADDR, 0x80 ); // 打开写保护
  154. #endif
  155. }
  156. void DS1302_Key_Handler ( void )
  157. {
  158. if ( Keys[14].Res == LONG_KEY_FLAG )
  159. {
  160. Keys[14].Res = NO_KEY_FLAG;
  161. DS1302_DateTime.Year = 14;
  162. DS1302_DateTime.Month = 10;
  163. DS1302_DateTime.Date = 5;
  164. DS1302_DateTime.Hour = 22;
  165. DS1302_DateTime.Minute = 35;
  166. DS1302_DateTime.Second = 0;
  167. DS1302_DateTime.Day = 7;
  168. DS1302_DateTime.HourMode = _24_hours;
  169. DS1302_DateTime.AM_PM = pm;
  170. #if DS1302_def
  171. DS1302_SetDateTime();
  172. #endif
  173. }
  174. }
  175. // 计算2000~2099年任一天星期几
  176. // year : 00-99
  177. // month : 01-12
  178. // day : 01-31
  179. // 返回 1 -> 7 : 星期一 -> 星期天
  180. unsigned char GetDayFromDate ( unsigned char year, unsigned char month, unsigned char date )
  181. {
  182. if ( month == 1 || month == 2 )
  183. {
  184. month += 12;
  185. if ( year > 0 )
  186. year--;
  187. else
  188. year = 4;
  189. }
  190. return ( 1 + ( ( date + 2 * month + 3 * ( month + 1 ) / 5 + year + year / 4 ) % 7 ) );
  191. }
  192. /////////////////////
  193. //平年的月份日期表,月份缩写表
  194. const u8 Days_Table[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  195. const u8 Month_Table[12][3] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  196. const u8* Week_Table[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
  197. //月修正数据表
  198. u8 const _Week[12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
  199. //判断是否是闰年函数
  200. //
  201. //判断方法:
  202. // 普通年能整除4且不能整除100的为闰年。(如2004年就是闰年,1900年不是闰年)
  203. // 世纪年能整除400的是闰年。(如2000年是闰年,1900年不是闰年)
  204. //
  205. //返回: 1,是闰年 0,不是闰年
  206. u8 Is_LeapYear ( u16 year )
  207. {
  208. if ( ( ( year % 4 == 0 ) && ( year % 100 != 0 ) ) || ( year % 400 == 0 ) )
  209. return 1;
  210. else
  211. return 0;
  212. }
  213. //将时间转化为到1970年1月1日的总秒数
  214. //Bugs:此函数秒数会多20左右,所以函数返回值做了校正,校正后没有问题
  215. //待优化
  216. u32 Date_TO_Sec ( u16 year, u8 month, u8 date, u8 hour, u8 minute, u8 second )
  217. {
  218. u16 t = 0;
  219. u32 sec = 0;
  220. year += 2000;
  221. if ( ( year >= 1970 ) && ( year <= 2106 ) ) //判断是否为合法年份,RTC的时间是从1970开始,只能由32位表示秒数,最大只能到2106年左右
  222. {
  223. for ( t = 1970 ; t < year; t++ ) //所有年份秒数累加
  224. {
  225. if ( Is_LeapYear ( t ) ) //判断是否为闰年
  226. {
  227. sec += 366 * 24 * 60 * 60;
  228. }
  229. else
  230. {
  231. sec += 365 * 24 * 60 * 60;
  232. }
  233. }
  234. for ( t = 0; t < month - 1; t++ ) //月份秒数累加
  235. {
  236. sec += ( u32 ) Days_Table[t] * 24 * 60 * 60;
  237. if ( Is_LeapYear ( year ) && ( t == 1 ) ) //闰年加一天的秒钟数
  238. {
  239. sec += 24 * 60 * 60;
  240. }
  241. }
  242. sec += ( u32 ) ( date - 1 ) * 24 * 60 * 60; //本月日期的秒数累加
  243. sec += ( u32 ) ( hour ) * 60 * 60;
  244. sec += ( u32 ) ( minute ) * 60;
  245. sec += second;
  246. }
  247. return sec;//-20; //校正20秒,原因不详
  248. }
  249. //获取RTC时间
  250. void Sec_TO_Date ( u32 secs )
  251. {
  252. u32 days = 0, temp = 0, years = 1970, months = 0;
  253. #if 0
  254. secs = RTC->CNTH; //读取RTC的当前时间值(距1970年的总秒数)
  255. secs <<= 16;
  256. secs += RTC->CNTL;
  257. #else
  258. #endif
  259. //printf("\nRtc_Get Sec = %x\n",secs);
  260. days = secs / ( 24 * 60 * 60 );
  261. if ( days > 0 ) //超过一天
  262. {
  263. temp = days;
  264. while ( temp >= 365 )
  265. {
  266. if ( Is_LeapYear ( years ) ) //是闰年
  267. {
  268. if ( temp >= 366 )
  269. {
  270. temp -= 366; //闰年的天数
  271. }
  272. else
  273. {
  274. break;
  275. }
  276. }
  277. else
  278. {
  279. temp -= 365;
  280. }
  281. years++;
  282. }
  283. DS1302_DateTime.Year = years - 2000; //得到年份
  284. while ( days >= 28 )
  285. {
  286. if ( Is_LeapYear ( years ) && ( months == 1 ) ) //判断是否为闰年的第二月
  287. {
  288. if ( temp >= 29 )
  289. temp -= 29;
  290. else
  291. break;
  292. }
  293. else
  294. {
  295. if ( temp >= Days_Table[months] )
  296. temp -= Days_Table[months];
  297. else
  298. break;
  299. }
  300. months++;
  301. }
  302. DS1302_DateTime.Month = months + 1; //得到月数
  303. DS1302_DateTime.Date = temp + 1; //得到日期
  304. }
  305. temp = secs % ( 24 * 60 * 60 ); //得到剩余秒数
  306. DS1302_DateTime.Hour = temp / ( 60 * 60 ); //得到小时
  307. DS1302_DateTime.Minute = ( temp % ( 60 * 60 ) ) / 60;
  308. DS1302_DateTime.Second = ( temp % ( 60 * 60 ) ) % 60;
  309. DS1302_DateTime.Day = GetDayFromDate ( DS1302_DateTime.Year, DS1302_DateTime.Month, DS1302_DateTime.Date );
  310. DS1302_DateTime.HourMode = _24_hours;
  311. DS1302_DateTime.AM_PM = pm;
  312. }
  313. //计算今天是一年中的第多少天
  314. int sum_Yday ( int a, int b, int c )
  315. {
  316. int i;
  317. char h1[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  318. char h2[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  319. for ( i = 1; i < b; i++ )
  320. {
  321. if ( a % 4 == 0 && a % 100 != 0 || a % 400 == 0 )
  322. c = h1[i] + c;
  323. else
  324. c = h2[i] + c;
  325. }
  326. return ( c );
  327. }