参考文档:

https://blog.csdn.net/cp1300/article/details/77915975
https://www.stmcu.org.cn/module/forum/thread-611941-1-1.html
中文数据手册:
PCF8563.pdf

bsp_pcf8563.h

  1. /*************************************************************************************************************
  2. * 文件名: PCF8563.h
  3. * 功能: STM32 PCF8563 高精度 RTC 芯片驱动
  4. * 作者: cp1300@139.com
  5. * 创建时间: 2017-07-10
  6. * 最后修改时间: 2017-07-10
  7. * 详细: 使用软件IIC接口驱动
  8. *************************************************************************************************************/
  9. #ifndef _PCF8563_H_
  10. #define _PCF8563_H_
  11. #include "system.h"
  12. #if(BOARD_SUPPORT) //需要板级支持
  13. #include "board.h"
  14. #else //默认支持
  15. #endif
  16. //时间结构体
  17. typedef struct
  18. {
  19. u8 hour; //小时
  20. u8 min; //分钟
  21. u8 sec; //秒
  22. u8 month; //月
  23. u8 date; //日
  24. u8 week; //星期
  25. u16 year; //年
  26. }rtc_timer;
  27. extern rtc_timer ext_timer; //外部RTC时钟
  28. //PCF8563 寄存器
  29. typedef enum
  30. {
  31. PCF8563_REG_CONTROL1 = 0x00, //控制寄存器1
  32. PCF8563_REG_CONTROL2 = 0x01, //控制寄存器2
  33. PCF8563_REG_SECONDS = 0x02, //秒 seconds 00 to 59 coded in BCD
  34. PCF8563_REG_MINUTES = 0x03, //分 minutes 00 to 59 coded in BCD
  35. PCF8563_REG_HOURS = 0x04, //小时 hours 00 to 23 coded in BCD
  36. PCF8563_REG_DAYS = 0x05, //日 days 01 to 31 coded in BCD
  37. PCF8563_REG_WEEK = 0x06, //星期 weekdays 0 to 6 in BCD
  38. PCF8563_REG_MONTHS = 0x07, //月份 months 01 to 12 coded in BCD
  39. PCF8563_REG_YEARS = 0x08, //年份 years 00 to 99 coded in BCD
  40. PCF8563_REG_ALARM_MINUTE = 0x09, //闹钟,分钟 minute alarm 00 to 59 coded in BCD
  41. PCF8563_REG_ALARM_HOUR = 0x0A, //闹钟,小时 hour alarm 00 to 23 coded in BCD
  42. PCF8563_REG_ALARM_DAY = 0x0B, //闹钟,日 day alarm 01 to 31 coded in BCD
  43. PCF8563_REG_ALARM_WEEK = 0x0C, //闹钟,星期 weekday alarm 0 to 6 in BCD
  44. PCF8563_REG_CLKOUT = 0x0D, //时钟输出设置
  45. PCF8563_REG_TIME_CONTROL = 0x0E, //定时器设置
  46. PCF8563_REG_TIME = 0x0F, //定时器倒计数值
  47. }PCF8563_REG_TYPE;
  48. bool PCF8563_Init(void); //PCF8563初始化
  49. bool PCF8563_SetTimer(u16 year,u8 month,u8 date,u8 hour,u8 min,u8 sec); //PCF8563时间设置
  50. bool PCF8563_GetTimer(void); //更新时间
  51. u32 PCF8563_TimeToSec(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec); //时间转换为秒,注意:不可重入,请注意调用冲突
  52. //使能系统命令行
  53. #if SYS_CMD_EN_
  54. #include "cmd.h"
  55. #include "string.h"
  56. extern const CMD_TYPE CMD_GET_ExtTIME;
  57. extern const CMD_TYPE CMD_GET_ExtDATE;
  58. extern const CMD_TYPE CMD_SET_ExtTIME;
  59. extern const CMD_TYPE CMD_SET_ExtDATE;
  60. //获取时间
  61. void CMD_ExtGetTime(char *pStr);
  62. //获取日期
  63. void CMD_ExtGetDate(char *pStr);
  64. //设置时间
  65. void CMD_ExtSetTime(char *pStr);
  66. //设置日期
  67. void CMD_ExtSetDate(char *pStr);
  68. #endif //SYS_CMD_EN_
  69. #endif /*_PCF8563_H_*/

bsp_pcf8563.c

  1. /*************************************************************************************************************
  2. * 文件名: PCF8563.c
  3. * 功能: STM32 PCF8563 高精度 RTC 芯片驱动
  4. * 作者: cp1300@139.com
  5. * 创建时间: 2017-07-10
  6. * 最后修改时间: 2017-07-10
  7. * 详细: 使用软件IIC接口驱动
  8. 2017-07-13:通过写入PCF8563_REG_CLKOUT与读取PCF8563_REG_CLKOUT寄存器,发现某些不用的位会乱跳,最终发现时间寄存器也有同样的问题,需要把不用的位都屏蔽掉
  9. *************************************************************************************************************/
  10. #include "system.h"
  11. #include "delay.h"
  12. #include "PCF8563.h"
  13. #include "stdio.h"
  14. #include "SoftwareIIC.h"
  15. //月修正数据表
  16. static u8 const table_week[12] = {0,3,3,6,1,4,6,2,5,0,3,5};
  17. //平年的月份日期表
  18. static u8 const mon_table[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
  19. static bool Is_Leap_Year(u16 year);
  20. rtc_timer ext_timer; //外部RTC时钟
  21. static SIIC_HANDLE IIC_Handel;
  22. #define PCF8563_SDA_GPIOx GPIOC
  23. #define PCF8563_SCL_GPIOx GPIOC
  24. #define PCF8563_SDA_Bit 1
  25. #define PCF8563_SCL_Bit 13
  26. //调试宏开关
  27. #define PCF8563_DBUG 1
  28. #if PCF8563_DBUG
  29. #include "system.h"
  30. #define PCF8563_Debug(format,...) uart_printf(format,##__VA_ARGS__)
  31. #else
  32. #define PCF8563_Debug(format,...) /\
  33. /
  34. #endif //PCF8563_DBUG
  35. //PCF8563 iic总线地址
  36. #define PCF8563_IIC_W_ADDR 0xA2
  37. #define PCF8563_IIC_R_ADDR 0xA3
  38. static u8 GetWeek(u16 year,u8 month,u8 day); //获取2000-2099年之间的日期对应的星期
  39. static u32 DECtoBCD( u8 DEC); //将数字转换为压缩BCD格式,最大支持99
  40. static u32 BCDtoDEC(u8 BCD); //将压缩BCD转为DEC,最大支持99
  41. bool PCF8563_ReadReg(PCF8563_REG_TYPE RegIndex, u8 *pData, u8 RegNum) ; //读取PCF8563寄存器
  42. bool PCF8563_WriteReg(PCF8563_REG_TYPE RegIndex, u8 *pData, u8 RegNum) ; //写入PCF8563寄存器
  43. bool PCF8563_WriteOneReg(PCF8563_REG_TYPE RegIndex, u8 Data); //写单个寄存器
  44. /*************************************************************************************************************************
  45. *函数 : bool PCF8563_Init(void)
  46. *功能 : 初始化PCF8563
  47. *参数 : 无
  48. *返回 : FALSE:失败;TRUE:成功
  49. *依赖 : 底层宏定义
  50. *作者 : cp1300@139.com
  51. *时间 : 2017-07-10
  52. *最后修改时间 : 2017-07-10
  53. *说明 : 无
  54. *************************************************************************************************************************/
  55. bool PCF8563_Init(void)
  56. {
  57. u8 data;
  58. memset(&ext_timer,0,sizeof(rtc_timer));
  59. if(SIIC_Init(&IIC_Handel,PCF8563_SDA_GPIOx, PCF8563_SCL_GPIOx, PCF8563_SDA_Bit, PCF8563_SCL_Bit, 1) == FALSE)
  60. {
  61. PCF8563_Debug("**********************PCF8563 初始化失败,IIC接口初始化失败!\r\n");
  62. return FALSE;
  63. }
  64. if(PCF8563_WriteOneReg(PCF8563_REG_CONTROL1, 0x08) == FALSE) //启动时钟,开启掉电检测
  65. {
  66. PCF8563_Debug("**********************PCF8563 初始化失败,开启掉电监测功能失败!\r\n");
  67. return FALSE;
  68. }
  69. if(PCF8563_ReadReg(PCF8563_REG_SECONDS, &data, 1) == FALSE)
  70. {
  71. PCF8563_Debug("**********************PCF8563 初始化失败,读取秒寄存器失败!\r\n");
  72. return FALSE;
  73. }
  74. if(data & 0x80) //秒 最高位为1,时钟芯片没有初始化 integrity of the clock information is no longer guaranteed
  75. {
  76. //初始化时钟芯片与时间
  77. PCF8563_Debug("时钟芯片没有初始化,需要重新初始化时钟!\r\n");
  78. if(PCF8563_SetTimer(2017,6,6,6,6,6)==FALSE)
  79. {
  80. PCF8563_Debug("时钟芯片没有初始化,需要重新初始化时钟!\r\n");
  81. }
  82. }
  83. PCF8563_GetTimer(); //更新时间
  84. return TRUE;
  85. }
  86. /*************************************************************************************************************************
  87. *函数 : bool PCF8563_ReadReg(PCF8563_REG_TYPE RegIndex, u8 *pData, u8 RegNum)
  88. *功能 : 读取PCF8563多个寄存器
  89. *参数 : RegIndex:寄存器地址,pData:读取到的值,RegNum:读取的寄存器数量
  90. *返回 : TRUE:通信成功;FALSE:通信失败
  91. *依赖 : 底层宏定义
  92. *作者 : cp1300@139.com
  93. *时间 : 2017-07-10
  94. *最后修改时间 : 2017-07-10
  95. *说明 : 无
  96. *************************************************************************************************************************/
  97. bool PCF8563_ReadReg(PCF8563_REG_TYPE RegIndex, u8 *pData, u8 RegNum)
  98. {
  99. u8 i;
  100. if(RegNum < 1) RegNum = 1;
  101. if(RegNum > 16) RegNum = 16; //限制读取的最大数量
  102. SIIC_Start(&IIC_Handel); //发送起始信号
  103. if(SIIC_SendByte(&IIC_Handel, PCF8563_IIC_W_ADDR)==FALSE) //发送写地址
  104. {
  105. PCF8563_Debug("PCF8563 发送写地址 ACK错误\r\n");
  106. return FALSE;
  107. }
  108. if(SIIC_SendByte(&IIC_Handel, RegIndex)==FALSE) //发送要读取的寄存器地址
  109. {
  110. PCF8563_Debug("PCF8563 发送要读取的寄存器地址2 ACK错误\r\n");
  111. return FALSE;
  112. }
  113. SIIC_Start(&IIC_Handel); //发送起始信号
  114. if(SIIC_SendByte(&IIC_Handel, PCF8563_IIC_R_ADDR)==FALSE) //发送读取地址
  115. {
  116. PCF8563_Debug("PCF8563 发送读取地址 ACK错误\r\n");
  117. return FALSE;
  118. }
  119. for(i = 0;i < RegNum;i ++)
  120. {
  121. if(i == (RegNum-1)) //最后一字节
  122. {
  123. pData[i] = SIIC_ReadByte(&IIC_Handel, FALSE); //读取数据-最后一字节不发送ACK
  124. }
  125. else
  126. {
  127. pData[i] = SIIC_ReadByte(&IIC_Handel, TRUE); //读取数据
  128. }
  129. }
  130. SIIC_Stop(&IIC_Handel); //发送结束
  131. return TRUE;
  132. }
  133. /*************************************************************************************************************************
  134. *函数 : bool PCF8563_ReadOneReg(PCF8563_REG_TYPE RegIndex, u8 *pData)
  135. *功能 : 读取PCF8563单个寄存器
  136. *参数 : RegIndex:寄存器地址,pData:读取到的值
  137. *返回 : TRUE:通信成功;FALSE:通信失败
  138. *依赖 : 底层宏定义
  139. *作者 : cp1300@139.com
  140. *时间 : 2017-07-10
  141. *最后修改时间 : 2017-07-13
  142. *说明 : 无
  143. *************************************************************************************************************************/
  144. bool PCF8563_ReadOneReg(PCF8563_REG_TYPE RegIndex, u8 *pData)
  145. {
  146. SIIC_Start(&IIC_Handel); //发送起始信号
  147. if(SIIC_SendByte(&IIC_Handel, PCF8563_IIC_W_ADDR)==FALSE) //发送写地址
  148. {
  149. PCF8563_Debug("PCF8563 发送写地址 ACK错误\r\n");
  150. return FALSE;
  151. }
  152. if(SIIC_SendByte(&IIC_Handel, RegIndex)==FALSE) //发送要读取的寄存器地址
  153. {
  154. PCF8563_Debug("PCF8563 发送要读取的寄存器地址2 ACK错误\r\n");
  155. return FALSE;
  156. }
  157. SIIC_Start(&IIC_Handel); //发送起始信号
  158. if(SIIC_SendByte(&IIC_Handel, PCF8563_IIC_R_ADDR)==FALSE) //发送读取地址
  159. {
  160. PCF8563_Debug("PCF8563 发送读取地址 ACK错误\r\n");
  161. return FALSE;
  162. }
  163. *pData = SIIC_ReadByte(&IIC_Handel, FALSE); //读取数据-最后一字节不发送ACK
  164. SIIC_Stop(&IIC_Handel); //发送结束
  165. return TRUE;
  166. }
  167. /*************************************************************************************************************************
  168. *函数 : bool PCF8563_WriteReg(PCF8563_REG_TYPE RegIndex, u8 *pData, u8 RegNum)
  169. *功能 : 写PCF8563多个寄存器
  170. *参数 : RegIndex:寄存器地址,pData:写入的值,RegNum:写入的寄存器数量
  171. *返回 : TRUE:通信成功;FALSE:通信失败
  172. *依赖 : 底层宏定义
  173. *作者 : cp1300@139.com
  174. *时间 : 2017-07-10
  175. *最后修改时间 : 2017-07-10
  176. *说明 : 无
  177. *************************************************************************************************************************/
  178. bool PCF8563_WriteReg(PCF8563_REG_TYPE RegIndex, u8 *pData, u8 RegNum)
  179. {
  180. u8 i;
  181. SIIC_Start(&IIC_Handel); //发送起始信号
  182. if(SIIC_SendByte(&IIC_Handel, PCF8563_IIC_W_ADDR)==FALSE) //发送写地址
  183. {
  184. PCF8563_Debug("PCF8563 发送写地址 ACK错误\r\n");
  185. return FALSE;
  186. }
  187. /*if(SIIC_SendByte(&IIC_Handel, 0)==FALSE) //发送要读取的寄存器地址
  188. {
  189. PCF8563_Debug("PCF8563 发送要读取的寄存器地址2 ACK错误\r\n");
  190. return FALSE;
  191. }*/
  192. if(SIIC_SendByte(&IIC_Handel, RegIndex)==FALSE) //发送要写的寄存器地址
  193. {
  194. PCF8563_Debug("PCF8563 发送要读取的寄存器地址2 ACK错误\r\n");
  195. return FALSE;
  196. }
  197. /*SIIC_Start(&IIC_Handel); //发送起始信号
  198. if(SIIC_SendByte(&IIC_Handel, PCF8563_IIC_W_ADDR)==FALSE) //发送写地址
  199. {
  200. PCF8563_Debug("PCF8563 发送读取地址 ACK错误\r\n");
  201. return FALSE;
  202. }*/
  203. for(i = 0;i < RegNum;i ++)
  204. {
  205. SIIC_SendByte(&IIC_Handel, pData[i]); //发送数据
  206. }
  207. SIIC_Stop(&IIC_Handel); //发送结束
  208. return TRUE;
  209. }
  210. /*************************************************************************************************************************
  211. *函数 : bool PCF8563_WriteOneReg(PCF8563_REG_TYPE RegIndex, u8 Data)
  212. *功能 : 写PCF8563单个寄存器
  213. *参数 : RegIndex:寄存器地址,Data:写入的值
  214. *返回 : TRUE:通信成功;FALSE:通信失败
  215. *依赖 : 底层宏定义
  216. *作者 : cp1300@139.com
  217. *时间 : 2017-07-10
  218. *最后修改时间 : 2017-07-13
  219. *说明 : 无
  220. *************************************************************************************************************************/
  221. bool PCF8563_WriteOneReg(PCF8563_REG_TYPE RegIndex, u8 Data)
  222. {
  223. SIIC_Start(&IIC_Handel); //发送起始信号
  224. if(SIIC_SendByte(&IIC_Handel, PCF8563_IIC_W_ADDR)==FALSE) //发送写地址
  225. {
  226. PCF8563_Debug("PCF8563 发送写地址 ACK错误\r\n");
  227. return FALSE;
  228. }
  229. if(SIIC_SendByte(&IIC_Handel, RegIndex)==FALSE) //发送要写的寄存器地址
  230. {
  231. PCF8563_Debug("PCF8563 发送要读取的寄存器地址2 ACK错误\r\n");
  232. return FALSE;
  233. }
  234. SIIC_SendByte(&IIC_Handel, Data); //发送数据
  235. SIIC_Stop(&IIC_Handel); //发送结束
  236. return TRUE;
  237. }
  238. /*************************************************************************************************************************
  239. * 函数 : bool PCF8563_GetTimer(void)
  240. * 功能 : PCF8563获取时间
  241. * 参数 : 无
  242. * 返回 : TRUE:成功,FALSE:失败
  243. * 依赖 : 底层宏定义
  244. * 作者 : cp1300@139.com
  245. * 时间 : 2017-07-11
  246. * 最后修改时间 : 2017-07-11
  247. * 说明 : 获取到的时间会更新到全局ext_timer
  248. *************************************************************************************************************************/
  249. bool PCF8563_GetTimer(void)
  250. {
  251. u8 data[7];
  252. u8 retry;
  253. u8 temp;
  254. for(retry = 0;retry < 3;retry ++)
  255. {
  256. if(PCF8563_ReadReg(PCF8563_REG_SECONDS, data, 7) == TRUE) //设置时间
  257. {
  258. if(data[0] & 0x80) //时间无效
  259. {
  260. PCF8563_Debug("PCF8563 时间无效,需要重新初始化!\r\n");
  261. PCF8563_SetTimer(2017,6,6,6,6,6); //初始化设置时间
  262. }
  263. else
  264. {
  265. //uart_printf("%02X,%02X,%02X,%02X,%02X,%02X,%02X\r\n",data[0],data[1],data[2],data[3],data[4],data[5],data[6]);
  266. temp = BCDtoDEC(data[0]&0x7F);
  267. if(temp > 59) continue; //秒钟范围不对
  268. ext_timer.sec = temp;
  269. temp = BCDtoDEC(data[1]&0x7F);
  270. if(temp > 59) continue; //分钟范围不对
  271. ext_timer.min = temp;
  272. temp = BCDtoDEC(data[2]&0x3F);
  273. if(temp > 23) continue; //小时范围不对
  274. ext_timer.hour = temp;
  275. temp = BCDtoDEC(data[3]&0x3F);
  276. if(temp > 31||temp==0) continue; //日期范围不对
  277. ext_timer.date = temp;
  278. temp = BCDtoDEC(data[4]&0x07);
  279. if(temp > 6) continue; //星期范围不对
  280. ext_timer.week = temp+1;
  281. temp = BCDtoDEC(data[5]&0x1F);
  282. if(temp > 12||temp==0) continue; //月份范围不对
  283. ext_timer.month = temp;
  284. ext_timer.year = BCDtoDEC(data[6])+2000;
  285. return TRUE;
  286. }
  287. }
  288. else
  289. {
  290. PCF8563_Debug("PCF8563 读取时间失败!\r\n");
  291. }
  292. }
  293. return FALSE;
  294. }
  295. /*************************************************************************************************************************
  296. * 函数 : bool PCF8563_SetTimer(u16 year,u8 month,u8 date,u8 hour,u8 min,u8 sec)
  297. * 功能 : PCF8563时间设置
  298. * 参数 : year,month,date:年(2000~2099),月(1~12),日(1~31),hour,min,sec:小时24小时,分钟,秒钟
  299. * 返回 : TRUE:成功,FALSE:失败
  300. * 依赖 : 底层宏定义
  301. * 作者 : cp1300@139.com
  302. * 时间 : 2017-07-11
  303. * 最后修改时间 : 2017-07-11
  304. * 说明 :
  305. *************************************************************************************************************************/
  306. bool PCF8563_SetTimer(u16 year,u8 month,u8 date,u8 hour,u8 min,u8 sec)
  307. {
  308. u8 data[7];
  309. if(year < 2000) year = 2000;
  310. if(year > 2099) year = 2099;
  311. data[0] = DECtoBCD(sec); //秒
  312. data[1] = DECtoBCD(min); //分
  313. data[2] = DECtoBCD(hour); //小时
  314. data[3] = DECtoBCD(date); //日
  315. data[4] = GetWeek(year, month, date)-1; //星期
  316. year -= 2000;
  317. data[5] = DECtoBCD(month); //月
  318. data[6] = DECtoBCD(year); //年
  319. PCF8563_WriteReg(PCF8563_REG_SECONDS, &data[0], 7); //设置时间
  320. if(PCF8563_WriteOneReg(PCF8563_REG_CONTROL1, 0x08) == FALSE) //启动时钟,开启掉电检测
  321. {
  322. PCF8563_Debug("**********************PCF8563 设置失败,启动时钟失败!\r\n");
  323. return FALSE;
  324. }
  325. return TRUE;
  326. }
  327. /*************************************************************************************************************************
  328. * 函数 : u32 PCF8563_TimeToSec(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
  329. * 功能 : PCF8563时间转换为秒(从1970开始)(注意:不可重入,请注意调用冲突)
  330. * 参数 : year,month,date:年(2000~2099),月(1~12),日(1~31),hour,min,sec:小时24小时,分钟,秒钟
  331. * 返回 : TRUE:成功,FALSE:失败
  332. * 依赖 : 底层宏定义
  333. * 作者 : cp1300@139.com
  334. * 时间 : 2017-07-11
  335. * 最后修改时间 : 2017-07-17
  336. * 说明 : 只能计算从2000年之后的秒,修改如果年,月,日不变,则无需重新计算,提高效率
  337. 注意:不可重入,请注意调用冲突
  338. *************************************************************************************************************************/
  339. u32 PCF8563_TimeToSec(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
  340. {
  341. u16 t;
  342. u32 seccount = 0;
  343. static u32 LastYearSec = 0; //之前年对应的秒,如果年不变,则不用重新计算
  344. static u32 LastMonSec = 0; //当前年月份对应的秒数,如果月份不变,则不需要重新计算
  345. static u32 LastDaySec = 0; //当前日期对应的秒,如果日期不变,则不需要重新计算
  346. static u16 LastYear = 0; //之前的年如果不变,则只计算今年的秒
  347. static u8 LastMon = 0; //当前年之前的月份
  348. static u8 LastDay = 0; //之前的日期
  349. if(syear < 2000 || syear > 2099)
  350. return 0;
  351. //年变化了才重新计算
  352. if(LastYear != syear) //年发生了变化,重新计算
  353. {
  354. LastYear = syear; //记录本次的年
  355. LastYearSec = 0;
  356. for(t = 1970;t < syear;t ++) //把所有年份的秒钟相加
  357. {
  358. if(Is_Leap_Year(t))
  359. LastYearSec += 31622400; //闰年的秒钟数
  360. else
  361. LastYearSec += 31536000; //平年的秒钟数
  362. }
  363. }
  364. //月变化了才重新计算
  365. if(LastMon != smon) //月份有变化
  366. {
  367. LastMon = smon; //记录本次的月份
  368. smon -= 1;
  369. LastMonSec = 0;
  370. for(t = 0;t < smon;t ++) //把前面月份的秒钟数相加
  371. {
  372. LastMonSec += (u32)mon_table[t] * 86400; //月份秒钟数相加
  373. if(Is_Leap_Year(syear) && t == 1)
  374. LastMonSec += 86400; //闰年2月份增加一天的秒钟数
  375. }
  376. }
  377. //日期变化了才重新计算
  378. if(LastDay != sday)
  379. {
  380. LastDay = sday; //记录本次的日期
  381. LastDaySec = (u32)(sday - 1) * 86400; //把前面日期的秒钟数相加
  382. }
  383. seccount = LastYearSec+LastMonSec+LastDaySec; //直接获取年对应的秒,不用每次计算
  384. seccount += (u32)hour * 3600; //小时秒钟数
  385. seccount += (u32)min * 60; //分钟秒钟数
  386. seccount += sec; //最后的秒钟加上去
  387. return seccount;
  388. }
  389. /*************************************************************************************************************************
  390. * 函数 : bool Is_Leap_Year(u16 year)
  391. * 功能 : 判断是否是闰年函数
  392. * 参数 : year:年份
  393. * 返回 : TRUE:是闰年,FALSE:不是闰年
  394. * 依赖 : 无
  395. * 作者 : cp1300@139.com
  396. * 时间 : 2014-05-30
  397. * 最后修改时间 : 2014-05-30
  398. * 说明 :
  399. 月份 1 2 3 4 5 6 7 8 9 10 11 12
  400. 闰年 31 29 31 30 31 30 31 31 30 31 30 31
  401. 非闰年 31 28 31 30 31 30 31 31 30 31 30 31
  402. *************************************************************************************************************************/
  403. static bool Is_Leap_Year(u16 year)
  404. {
  405. if(year % 4 == 0) //必须能被4整除
  406. {
  407. if(year % 100 == 0)
  408. {
  409. if(year % 400 == 0)
  410. return TRUE;//如果以00结尾,还要能被400整除
  411. else
  412. return FALSE;
  413. }else
  414. return TRUE;
  415. }else
  416. return FALSE;
  417. }
  418. //获取2000-2099年之间的日期对应的星期
  419. //功能描述:输入公历日期得到星期(只允许1901-2099年)
  420. //year,month,day:公历年月日
  421. //返回值:星期号(1~7,代表周1~周日)
  422. static u8 GetWeek(u16 year,u8 month,u8 day)
  423. {
  424. u16 temp2;
  425. u8 yearH,yearL;
  426. yearH=year/100; yearL=year%100;
  427. // 如果为21世纪,年份数加100
  428. if (yearH>19)yearL+=100;
  429. // 所过闰年数只算1900年之后的
  430. temp2=yearL+yearL/4;
  431. temp2=temp2%7;
  432. temp2=temp2+day+table_week[month-1];
  433. if (yearL%4==0&&month<3)temp2--;
  434. temp2%=7;
  435. if(temp2==0)temp2=7;
  436. return temp2;
  437. }
  438. //将数字转换为压缩BCD格式,最大支持99
  439. static u32 DECtoBCD( u8 DEC)
  440. {
  441. return ((u8)(DEC/10)<<4)+(DEC%10);
  442. }
  443. //将压缩BCD转为DEC,最大支持99
  444. static u32 BCDtoDEC(u8 BCD)
  445. {
  446. return (u8)(BCD>>4)*10+(BCD&0x0f);
  447. }
  448. //使能系统命令行
  449. #if SYS_CMD_EN_
  450. #include "cmd.h"
  451. #include "string.h"
  452. const CMD_TYPE CMD_GET_ExtTIME = {"TIME?", 0xCC5C410A, CMD_ExtGetTime, "\t\t获取系统时间"};
  453. const CMD_TYPE CMD_GET_ExtDATE = {"DATE?", 0xB2704461, CMD_ExtGetDate, "\t\t获取系统日期"};
  454. const CMD_TYPE CMD_SET_ExtTIME = {"TIME=", 0xCC5C4108, CMD_ExtSetTime, "\t\t设置系统时间 如(12:32:54):TIME=12 32 54"};
  455. const CMD_TYPE CMD_SET_ExtDATE = {"DATE=", 0xB270445F, CMD_ExtSetDate, "\t\t设置系统日期 如(2014 6 8):TIME=2014 6 8"};
  456. //获取时间
  457. void CMD_ExtGetTime(char *pStr)
  458. {
  459. //PCF8563_GetTimer(); //更新时间
  460. cmd_printf("[获取时间成功]:%02d:%02d:%02d\r\n",ext_timer.hour, ext_timer.min, ext_timer.sec);
  461. }
  462. //获取日期
  463. void CMD_ExtGetDate(char *pStr)
  464. {
  465. //PCF8563_GetTimer(); //更新时间
  466. cmd_printf("[获取日期成功]:%04d-%02d-%02d\r\n",ext_timer.year, ext_timer.month, ext_timer.date);
  467. }
  468. //设置时间
  469. void CMD_ExtSetTime(char *pStr)
  470. {
  471. u8 hour,min,sec;
  472. u8 len;
  473. char *p;
  474. u8 num;
  475. len = strlen(pStr); //获取长度
  476. if(isStrNumAndSpc(pStr, len, 2) == FALSE)
  477. {
  478. cmd_printf("[时间设置错误]:格式不对或非法参数!\r\n");
  479. return;
  480. }
  481. //小时
  482. p = strstr(pStr," "); //搜索空格
  483. if(p == NULL)
  484. {
  485. cmd_printf("[时间设置错误]:格式不对或非法参数!\r\n");
  486. return;
  487. }
  488. num = p - pStr;
  489. if((num > 2) || (num == 0))
  490. {
  491. cmd_printf("[时间设置错误]:格式不对或非法参数!\r\n");
  492. return;
  493. }
  494. hour = CMD_StringToDec(pStr, num);
  495. if(hour>23)
  496. {
  497. cmd_printf("[时间设置错误]:格式不对或非法参数!\r\n");
  498. return;
  499. }
  500. //分钟
  501. pStr = p+1;
  502. p = strstr(pStr," "); //搜索空格
  503. if(p == NULL)
  504. {
  505. cmd_printf("[时间设置错误]:格式不对或非法参数!\r\n");
  506. return;
  507. }
  508. num = p - pStr;
  509. if((num > 2) || (num == 0))
  510. {
  511. cmd_printf("[时间设置错误]:格式不对或非法参数!\r\n");
  512. return;
  513. }
  514. min = CMD_StringToDec(pStr, num);
  515. if(min>59)
  516. {
  517. cmd_printf("[时间设置错误]:格式不对或非法参数!\r\n");
  518. return;
  519. }
  520. //秒钟
  521. pStr = p+1;
  522. num = strlen(pStr);
  523. if((num > 2) || (num == 0))
  524. {
  525. cmd_printf("[时间设置错误]:格式不对或非法参数!\r\n");
  526. return;
  527. }
  528. sec = CMD_StringToDec(pStr, num);
  529. if(sec>59)
  530. {
  531. cmd_printf("[时间设置错误]:格式不对或非法参数!\r\n");
  532. return;
  533. }
  534. PCF8563_GetTimer(); //更新时间
  535. if(PCF8563_SetTimer(ext_timer.year, ext_timer.month, ext_timer.date,hour, min, sec) == FALSE)
  536. {
  537. PCF8563_GetTimer(); //更新时间
  538. cmd_printf("[时间设置失败]:%02d:%02d:%02d\r\n",ext_timer.hour, ext_timer.min, ext_timer.sec);
  539. }
  540. else
  541. {
  542. PCF8563_GetTimer(); //更新时间
  543. cmd_printf("[时间设置成功]:%02d:%02d:%02d\r\n",ext_timer.hour, ext_timer.min, ext_timer.sec);
  544. }
  545. }
  546. //设置日期
  547. void CMD_ExtSetDate(char *pStr)
  548. {
  549. u16 year;
  550. u8 month, date;
  551. u8 len;
  552. char *p;
  553. u8 num;
  554. len = strlen(pStr); //获取长度
  555. if(isStrNumAndSpc(pStr, len, 2) == FALSE)
  556. {
  557. cmd_printf("[日期设置错误]:格式不对或非法参数!\r\n");
  558. return;
  559. }
  560. //年
  561. p = strstr(pStr," "); //搜索空格
  562. if(p == NULL)
  563. {
  564. cmd_printf("[日期设置错误]:格式不对或非法参数!\r\n");
  565. return;
  566. }
  567. num = p - pStr;
  568. if((num > 4) || (num == 0))
  569. {
  570. cmd_printf("[日期设置错误]:格式不对或非法参数!\r\n");
  571. return;
  572. }
  573. year = CMD_StringToDec(pStr, num);
  574. if(year>9999)
  575. {
  576. cmd_printf("[日期设置错误]:格式不对或非法参数!\r\n");
  577. return;
  578. }
  579. //月
  580. pStr = p+1;
  581. p = strstr(pStr," "); //搜索空格
  582. if(p == NULL)
  583. {
  584. cmd_printf("[日期设置错误]:格式不对或非法参数!\r\n");
  585. return;
  586. }
  587. num = p - pStr;
  588. if((num > 2) || (num == 0))
  589. {
  590. cmd_printf("[日期设置错误]:格式不对或非法参数!\r\n");
  591. return;
  592. }
  593. month = CMD_StringToDec(pStr, num);
  594. if(month>12)
  595. {
  596. cmd_printf("[日期设置错误]:格式不对或非法参数!\r\n");
  597. return;
  598. }
  599. //日
  600. pStr = p+1;
  601. num = strlen(pStr);
  602. if((num > 2) || (num == 0))
  603. {
  604. cmd_printf("[日期设置错误]:格式不对或非法参数!\r\n");
  605. return;
  606. }
  607. date = CMD_StringToDec(pStr, num);
  608. if(date>31)
  609. {
  610. cmd_printf("[日期设置错误]:格式不对或非法参数!\r\n");
  611. return;
  612. }
  613. PCF8563_GetTimer(); //更新时间
  614. if(PCF8563_SetTimer(year, month, date, ext_timer.hour, ext_timer.min, ext_timer.sec) == FALSE)
  615. {
  616. PCF8563_GetTimer(); //更新时间
  617. cmd_printf("[日期设置失败]:%04d-%02d-%02d\r\n",ext_timer.year, ext_timer.month, ext_timer.date);
  618. }
  619. else
  620. {
  621. PCF8563_GetTimer(); //更新时间
  622. cmd_printf("[日期设置成功]:%04d-%02d-%02d\r\n",ext_timer.year, ext_timer.month, ext_timer.date);
  623. }
  624. }
  625. #endif //SYS_CMD_EN_