Procházet zdrojové kódy

add: pcf8563t时钟模块的驱动及demo

https://gitee.com/openLuat/LuatOS/issues/I8BUHP
Wendal Chen před 2 roky
rodič
revize
599bee7292
2 změnil soubory, kde provedl 238 přidání a 0 odebrání
  1. 36 0
      demo/pcf8563t/main.lua
  2. 202 0
      script/libs/pcf8563t.lua

+ 36 - 0
demo/pcf8563t/main.lua

@@ -0,0 +1,36 @@
+
+PROJECT = "pcf8563t"
+VERSION = "2.0.0"
+
+_G.sys = require "sys"
+
+_G.pcf8563t = require "pcf8563t"
+
+local function PCF8563T()
+
+    sys.wait(3000)
+    
+    local i2cid = 1
+    i2c.setup(i2cid, i2c.FAST)
+    pcf8563t.setup(i2cid) -- 选一个i2c, 也可以是软件i2c对象
+    
+    -- 设置时间
+    local time = {year=2023,mon=11,day=2,wday=5,hour=13,min=14,sec=15}
+    pcf8563t.write(time)
+    
+    -- 读取时间
+    local time = pcf8563t.read()
+    log.info("time",time.year,time.mon,time.day, time.hour,time.min,time.sec, "week", time.wday)
+    
+    -- 设置闹钟, 并自动清除中断标志,开启alarm功能
+    alarm = {day=2,hour=13,min=14,sec=15}
+    pcf8563t.alarm(alarm)
+    local alarm_int = 1 -- 选一个GPIO,接时钟模块的INT脚
+    gpio.setup(1, function()
+        log.info("alarm!!!")
+        pcf8563t.control(nil, nil, 0, nil)
+    end, gpio.PULLUP)
+end
+sys.taskInit(PCF8563T)
+
+sys.run()

+ 202 - 0
script/libs/pcf8563t.lua

@@ -0,0 +1,202 @@
+--[[
+@module pcf8563t
+@summary pcf8563t时钟模块
+@version 1.0
+@date    2023.11.02
+@author  wendal
+@usage
+-- 数据手册 https://www.nxp.com.cn/docs/zh/data-sheet/PCF8563.pdf
+local pcf8563t = require "pcf8563t"
+
+local i2cid = 1
+i2c.setup(i2cid, i2c.FAST)
+pcf8563t.setup(i2cid) -- 选一个i2c, 也可以是软件i2c对象
+
+-- 设置时间
+local time = {year=2023,mon=11,day=2,wday=5,hour=13,min=14,sec=15}
+pcf8563t.write(time)
+
+-- 读取时间
+local time = pcf8563t.read()
+log.info("time",time.year,time.mon,time.day, time.hour,time.min,time.sec, "week=".. time.wday)
+
+-- 设置闹钟, 并自动清除中断标志,开启alarm功能
+alarm = {day=2,hour=13,min=14,sec=15}
+pcf8563t.alarm(alarm)
+local alarm_int = 1 -- 选一个GPIO,接时钟模块的INT脚
+gpio.setup(1, function()
+    log.info("alarm!!!")
+    pcf8563t.control(nil, nil, 0, nil)
+end, gpio.PULLUP)
+
+-- 主动清除中断标志
+pcf8563t.control(nil, nil, 0, nil)
+-- 关闭alarm
+pcf8563t.control(0, nil, 0, nil)
+]]
+local pcf8563t = {}
+
+local i2cid = 1             --i2cid
+local i2cslaveaddr =   0X51 --slave address
+local baseyear = 2000
+
+local REG_SEC = 0X02 
+local REG_ALARM = 0x09
+
+local function bcd_to_hex(data)
+    return bit.rshift(data,4)*10+bit.band(data,0x0f)
+ 
+end
+
+local function hex_to_bcd(data)
+    return bit.lshift(data//10,4)+data%10
+end
+
+--[[
+初始化
+@api pcf8563t.setup(id, by)
+@int i2c设备的id, 或者软件i2c的对象,必须填
+@int 年份基准,默认是2000, 可以不填
+@return boolean 成功返回true, 否则返回false
+]]
+function pcf8563t.setup(id, by)
+    i2cid = id
+    local t = pcf8563t.read()
+    if by then
+        baseyear = by
+    end
+    return t and t.year ~= nil
+end
+
+--[[
+读出时间
+@api pcf8563t.read()
+@return table 时间信息,如果读取失败会返回空的表
+@usage
+local time = pcf8563t.read()
+if time and time.year then
+    log.info("time", json.encode(time))
+end
+-- time 是个table, 有以下字段, 与os.date是兼容的
+-- time.year 年份
+-- time.mon  月份
+-- time.day  月内的天数
+-- time.hour 小时, 24进制
+-- time.min  分钟
+-- time.sec  秒
+-- time.wday 周N, 周日为1, 周六为7
+]]
+function pcf8563t.read()
+    -- read time
+    local time_data = {}
+    local data = i2c.readReg(i2cid, i2cslaveaddr, REG_SEC, 7)
+    if not data or #data ~= 7 then
+        return time_data
+    end
+    time_data.year  = bcd_to_hex(data:byte(7)) + baseyear
+    time_data.mon   = bcd_to_hex(bit.band(data:byte(6),0x7f))
+    time_data.wday  = bcd_to_hex(data:byte(5)) + 1
+    time_data.day   = bcd_to_hex(data:byte(4))
+    time_data.hour  = bcd_to_hex(data:byte(3))
+    time_data.min   = bcd_to_hex(data:byte(2))
+    time_data.sec   = bcd_to_hex(data:byte(1) & 0x7F)
+	return time_data
+end
+
+--[[
+设置时间
+@api pcf8563t.write(time)
+@table 时间信息,与pcf8563t.read的字段规则是一样的
+@return nil 无返回值
+@usage
+local time = {year=2023,mon=11,day=2,wday=5,hour=13,min=14,sec=15}
+pcf8563t.write(time)
+]]
+function pcf8563t.write(time)
+    -- set time
+    local data7 = hex_to_bcd(time.year - baseyear)
+    local data6 = hex_to_bcd(time.mon)
+    local data5 = hex_to_bcd(time.wday - 1)
+    local data4 = hex_to_bcd(time.day)
+    local data3 = hex_to_bcd(time.hour)
+    local data2 = hex_to_bcd(time.min)
+    local data1 = hex_to_bcd(time.sec)
+    i2c.writeReg(i2cid, i2cslaveaddr, REG_SEC, string.char(data1,data2,data3,data4,data5,data6,data7))
+end
+
+--[[
+设置闹钟
+@api pcf8563t.alarm(time)
+@table 时间信息
+@return nil 无返回值
+@usage
+-- 设置闹钟, 并自动清除中断标志,开启alarm功能
+-- 注意只能设置天(wday)/小时(hour)/分钟(min)/周天(wday), 无法设置年月
+alarm = {day=2,hour=13,min=14}
+pcf8563t.alarm(alarm)
+local alarm_int = 1 -- 选一个GPIO,接时钟模块的INT脚
+gpio.setup(1, function()
+    log.info("alarm!!!")
+    pcf8563t.control(nil, nil, 0, nil)
+end, gpio.PULLUP)
+
+-- 注意规则!!! 传入的值,需要全部匹配才会触发
+-- 例如, 每当min=1时触发, 不判断hour/day/wday
+alarm = {min=1}
+-- 例如, 每当min=1且hour=0时触发, 不判断day/wday
+alarm = {min=1, hour=0}
+-- 全部day/hour/min都满足才触发
+alarm = {day=2,hour=13,min=14}
+-- 全部day/hour/min/wday都满足才触发
+alarm = {day=2,hour=13,min=14,wday=2}
+]]
+function pcf8563t.alarm(time)
+    -- set time
+    local data5 = time.wday and hex_to_bcd(time.wday - 1) or  0x80
+    local data4 = time.day and hex_to_bcd(time.day) or  0x80
+    local data3 = time.hour and hex_to_bcd(time.hour) or  0x80
+    local data2 = time.min and hex_to_bcd(time.min) or  0x80
+    -- local data1 = time.sec and hex_to_bcd(time.sec) or 0
+    i2c.writeReg(i2cid, i2cslaveaddr, REG_ALARM, string.char(data2,data3,data4,data5))
+    local dataN = i2c.readReg(i2cid, i2cslaveaddr, REG_ALARM, 4)
+    log.info("数据对比", string.char(data2,data3,data4,data5):toHex(), dataN:toHex())
+    pcf8563t.control(1, nil, 0, nil)
+end
+
+--[[
+设置闹钟
+@api pcf8563t.control(AIE, TIE, AF, TF)
+@int 闹钟开关, 0 关闭, 1 开始, nil保持原样
+@int 定时器开关, 0 关闭, 1 开始, nil保持原样
+@int 清除闹钟中断, 0 清除, nil保持原样
+@int 清除定时器中断, 0 清除, nil保持原样
+@return nil 无返回值
+@usage
+-- 主动清除中断标志
+pcf8563t.control(nil, nil, 0, nil)
+-- 关闭alarm
+pcf8563t.control(0, nil, 0, nil)
+]]
+function pcf8563t.control(AIE, TIE, AF, TF)
+    local data = i2c.readReg(i2cid, i2cslaveaddr, 0x01, 1)
+    if data and #data == 1 then
+        data = data:byte()
+        if AIE then
+            data = data | ((AIE & 0x01) << 1)
+        end
+        if TIE then
+            data = data | (TIE & 0x01)
+        end
+        if AF then
+            data = data | ((AF & 0x01) << 3)
+        end
+        if TF then
+            data = data | ((TF & 0x01) << 2)
+        end
+        i2c.writeReg(i2cid, i2cslaveaddr, 0x01, string.char(data))
+        local data2 = i2c.readReg(i2cid, i2cslaveaddr, 0x01, 1)
+        log.info("数据对比", string.char(data):toHex(), data2:toHex())
+    end 
+end
+
+return pcf8563t