pcf8563t.lua 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. --[[
  2. @module pcf8563t
  3. @summary pcf8563t时钟模块
  4. @version 1.0
  5. @date 2023.11.02
  6. @author wendal
  7. @usage
  8. -- 数据手册 https://www.nxp.com.cn/docs/zh/data-sheet/PCF8563.pdf
  9. local pcf8563t = require "pcf8563t"
  10. local i2cid = 1
  11. i2c.setup(i2cid, i2c.FAST)
  12. pcf8563t.setup(i2cid) -- 选一个i2c, 也可以是软件i2c对象
  13. -- 设置时间
  14. local time = {year=2023,mon=11,day=2,wday=5,hour=13,min=14,sec=15}
  15. pcf8563t.write(time)
  16. -- 读取时间
  17. local time = pcf8563t.read()
  18. log.info("time",time.year,time.mon,time.day, time.hour,time.min,time.sec, "week=".. time.wday)
  19. -- 设置闹钟, 并自动清除中断标志,开启alarm功能
  20. alarm = {day=2,hour=13,min=14,sec=15}
  21. pcf8563t.alarm(alarm)
  22. local alarm_int = 1 -- 选一个GPIO,接时钟模块的INT脚
  23. gpio.setup(1, function()
  24. log.info("alarm!!!")
  25. pcf8563t.control(nil, nil, 0, nil)
  26. end, gpio.PULLUP)
  27. -- 主动清除中断标志
  28. pcf8563t.control(nil, nil, 0, nil)
  29. -- 关闭alarm
  30. pcf8563t.control(0, nil, 0, nil)
  31. ]]
  32. local pcf8563t = {}
  33. local i2cid = 1 --i2cid
  34. local i2cslaveaddr = 0X51 --slave address
  35. local baseyear = 2000
  36. local REG_SEC = 0X02
  37. local REG_ALARM = 0x09
  38. local function bcd_to_hex(data)
  39. return bit.rshift(data,4)*10+bit.band(data,0x0f)
  40. end
  41. local function hex_to_bcd(data)
  42. return bit.lshift(data//10,4)+data%10
  43. end
  44. --[[
  45. 初始化
  46. @api pcf8563t.setup(id, by)
  47. @int i2c设备的id, 或者软件i2c的对象,必须填
  48. @int 年份基准,默认是2000, 可以不填
  49. @return boolean 成功返回true, 否则返回false
  50. ]]
  51. function pcf8563t.setup(id, by)
  52. i2cid = id
  53. local t = pcf8563t.read()
  54. if by then
  55. baseyear = by
  56. end
  57. return t and t.year ~= nil
  58. end
  59. --[[
  60. 读出时间
  61. @api pcf8563t.read()
  62. @return table 时间信息,如果读取失败会返回空的表
  63. @usage
  64. local time = pcf8563t.read()
  65. if time and time.year then
  66. log.info("time", json.encode(time))
  67. end
  68. -- time 是个table, 有以下字段, 与os.date是兼容的
  69. -- time.year 年份
  70. -- time.mon 月份
  71. -- time.day 月内的天数
  72. -- time.hour 小时, 24进制
  73. -- time.min 分钟
  74. -- time.sec 秒
  75. -- time.wday 周N, 周日为1, 周六为7
  76. ]]
  77. function pcf8563t.read()
  78. -- read time
  79. local time_data = {}
  80. local data = i2c.readReg(i2cid, i2cslaveaddr, REG_SEC, 7)
  81. if not data or #data ~= 7 then
  82. return time_data
  83. end
  84. time_data.year = bcd_to_hex(data:byte(7)) + baseyear
  85. time_data.mon = bcd_to_hex(data:byte(6) & 0x9F)
  86. time_data.wday = bcd_to_hex(data:byte(5) & 0x07) + 1
  87. time_data.day = bcd_to_hex(data:byte(4) & 0x3F)
  88. time_data.hour = bcd_to_hex(data:byte(3) & 0x3F)
  89. time_data.min = bcd_to_hex(data:byte(2) & 0x7F)
  90. time_data.sec = bcd_to_hex(data:byte(1) & 0x7F)
  91. return time_data
  92. end
  93. --[[
  94. 设置时间
  95. @api pcf8563t.write(time)
  96. @table 时间信息,与pcf8563t.read的字段规则是一样的
  97. @return nil 无返回值
  98. @usage
  99. local time = {year=2023,mon=11,day=2,wday=5,hour=13,min=14,sec=15}
  100. pcf8563t.write(time)
  101. ]]
  102. function pcf8563t.write(time)
  103. -- set time
  104. local data7 = hex_to_bcd(time.year - baseyear)
  105. local data6 = hex_to_bcd(time.mon)
  106. local data5 = hex_to_bcd(time.wday - 1)
  107. local data4 = hex_to_bcd(time.day)
  108. local data3 = hex_to_bcd(time.hour)
  109. local data2 = hex_to_bcd(time.min)
  110. local data1 = hex_to_bcd(time.sec)
  111. i2c.writeReg(i2cid, i2cslaveaddr, REG_SEC, string.char(data1,data2,data3,data4,data5,data6,data7))
  112. end
  113. --[[
  114. 设置闹钟
  115. @api pcf8563t.alarm(time)
  116. @table 时间信息
  117. @return nil 无返回值
  118. @usage
  119. -- 设置闹钟, 并自动清除中断标志,开启alarm功能
  120. -- 注意只能设置天(wday)/小时(hour)/分钟(min)/周天(wday), 无法设置年月
  121. alarm = {day=2,hour=13,min=14}
  122. pcf8563t.alarm(alarm)
  123. local alarm_int = 1 -- 选一个GPIO,接时钟模块的INT脚
  124. gpio.setup(1, function()
  125. log.info("alarm!!!")
  126. pcf8563t.control(nil, nil, 0, nil)
  127. end, gpio.PULLUP)
  128. -- 注意规则!!! 传入的值,需要全部匹配才会触发
  129. -- 例如, 每当min=1时触发, 不判断hour/day/wday
  130. alarm = {min=1}
  131. -- 例如, 每当min=1且hour=0时触发, 不判断day/wday
  132. alarm = {min=1, hour=0}
  133. -- 全部day/hour/min都满足才触发
  134. alarm = {day=2,hour=13,min=14}
  135. -- 全部day/hour/min/wday都满足才触发
  136. alarm = {day=2,hour=13,min=14,wday=2}
  137. ]]
  138. function pcf8563t.alarm(time)
  139. -- set time
  140. local data5 = time.wday and hex_to_bcd(time.wday - 1) or 0x80
  141. local data4 = time.day and hex_to_bcd(time.day) or 0x80
  142. local data3 = time.hour and hex_to_bcd(time.hour) or 0x80
  143. local data2 = time.min and hex_to_bcd(time.min) or 0x80
  144. -- local data1 = time.sec and hex_to_bcd(time.sec) or 0
  145. i2c.writeReg(i2cid, i2cslaveaddr, REG_ALARM, string.char(data2,data3,data4,data5))
  146. local dataN = i2c.readReg(i2cid, i2cslaveaddr, REG_ALARM, 4)
  147. log.info("数据对比", string.char(data2,data3,data4,data5):toHex(), dataN:toHex())
  148. pcf8563t.control(1, nil, 0, nil)
  149. end
  150. --[[
  151. 设置闹钟
  152. @api pcf8563t.control(AIE, TIE, AF, TF)
  153. @int 闹钟开关, 0 关闭, 1 开始, nil保持原样
  154. @int 定时器开关, 0 关闭, 1 开始, nil保持原样
  155. @int 清除闹钟中断, 0 清除, nil保持原样
  156. @int 清除定时器中断, 0 清除, nil保持原样
  157. @return nil 无返回值
  158. @usage
  159. -- 主动清除中断标志
  160. pcf8563t.control(nil, nil, 0, nil)
  161. -- 关闭alarm
  162. pcf8563t.control(0, nil, 0, nil)
  163. ]]
  164. function pcf8563t.control(AIE, TIE, AF, TF)
  165. local data = i2c.readReg(i2cid, i2cslaveaddr, 0x01, 1)
  166. if data and #data == 1 then
  167. data = data:byte()
  168. if AIE then
  169. data = data | ((AIE & 0x01) << 1)
  170. end
  171. if TIE then
  172. data = data | (TIE & 0x01)
  173. end
  174. if AF then
  175. data = data | ((AF & 0x01) << 3)
  176. end
  177. if TF then
  178. data = data | ((TF & 0x01) << 2)
  179. end
  180. i2c.writeReg(i2cid, i2cslaveaddr, 0x01, string.char(data))
  181. local data2 = i2c.readReg(i2cid, i2cslaveaddr, 0x01, 1)
  182. log.info("数据对比", string.char(data):toHex(), data2:toHex())
  183. end
  184. end
  185. return pcf8563t