├── LICENSE ├── README.MD ├── examples ├── alarm.py └── networkSync.py ├── package.json └── pcf8563.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 lewis he 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | MicorPython PCF8563 Real-time clock/calendar 2 | ====================================== -------------------------------------------------------------------------------- /examples/alarm.py: -------------------------------------------------------------------------------- 1 | ''' 2 | MIT License 3 | 4 | Copyright (c) 2019 lewis he 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | 24 | alarm.py - MicroPython library for NXP PCF8563 Real-time clock/calendar 25 | Created by Lewis he on September 17, 2019. 26 | github:https://github.com/lewisxhe/PCF8563_PythonLibrary 27 | ''' 28 | import utime 29 | import time 30 | import pcf8563 31 | from machine import I2C 32 | from machine import Pin 33 | 34 | def handle_interrupt(pin): 35 | if r.check_for_alarm_interrupt(): 36 | print('is alarm clock interrupt') 37 | else: 38 | print('is not for alarm interrupt') 39 | r.clear_alarm() 40 | 41 | irq = Pin(37, mode=Pin.IN,handler=handle_interrupt,trigger=Pin.IRQ_FALLING) 42 | i2c = I2C(scl=22, sda=21) 43 | r = pcf8563.PCF8563(i2c) 44 | 45 | print('rtc time') 46 | r.datetime() 47 | time.sleep(1) 48 | 49 | print('Clear alarm config register') 50 | r.clear_alarm() 51 | 52 | print('Setting current clock datetime') 53 | r.write_all(50,30,15,3,17,9,49) 54 | 55 | print('Set the alarm to match for minutes') 56 | r.set_daily_alarm(minutes=31) 57 | 58 | print('Enable rtc chip interrupt') 59 | r.enable_alarm_interrupt() 60 | 61 | while True: 62 | r.datetime() 63 | time.sleep(1) -------------------------------------------------------------------------------- /examples/networkSync.py: -------------------------------------------------------------------------------- 1 | ''' 2 | MIT License 3 | 4 | Copyright (c) 2019 lewis he 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | 24 | networkSync.py - MicroPython library for NXP PCF8563 Real-time clock/calendar 25 | Created by Lewis he on September 17, 2019. 26 | github:https://github.com/lewisxhe/PCF8563_PythonLibrary 27 | ''' 28 | 29 | import utime 30 | import network 31 | from machine import RTC 32 | import time 33 | from machine import I2C 34 | import pcf8563 35 | 36 | ssid = "ssid" 37 | password = "password" 38 | 39 | station = network.WLAN(network.STA_IF) 40 | station.active(True) 41 | station.connect(ssid, password) 42 | while station.isconnected() == False: 43 | pass 44 | print("Connection successful") 45 | print(station.ifconfig()) 46 | 47 | rtc = RTC() 48 | rtc.ntp_sync(server="hr.pool.ntp.org", tz="CST-8") 49 | 50 | while rtc.synced() == False: 51 | print('sync rtc now...') 52 | time.sleep(1) 53 | print('sync success') 54 | utime.localtime() 55 | 56 | i2c = I2C(scl=22, sda=21) 57 | r = pcf8563.PCF8563(i2c) 58 | 59 | print('rtc time') 60 | r.datetime() 61 | time.sleep(1) 62 | print('sync system to pcf8563') 63 | r.write_now() 64 | 65 | while True: 66 | r.datetime() 67 | time.sleep(1) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "urls": [ 3 | ["pcf8563.py", "github:lewisxhe/PCF8563_PythonLibrary/pcf8563.py"] 4 | ], 5 | "version": "1.0.0", 6 | "deps": [] 7 | } -------------------------------------------------------------------------------- /pcf8563.py: -------------------------------------------------------------------------------- 1 | ''' 2 | MIT License 3 | 4 | Copyright (c) 2019 lewis he 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | 24 | pcf8563.py - MicroPython library for NXP PCF8563 Real-time clock/calendar 25 | Created by Lewis he on September 17, 2019. 26 | github:https://github.com/lewisxhe/PCF8563_PythonLibrary 27 | ''' 28 | import utime 29 | from machine import I2C 30 | 31 | PCF8563_SLAVE_ADDRESS = const(0x51) 32 | PCF8563_STAT1_REG = const(0x00) 33 | PCF8563_STAT2_REG = const(0x01) 34 | PCF8563_SEC_REG = const(0x02) 35 | PCF8563_MIN_REG = const(0x03) 36 | PCF8563_HR_REG = const(0x04) 37 | PCF8563_DAY_REG = const(0x05) 38 | PCF8563_WEEKDAY_REG = const(0x06) 39 | PCF8563_MONTH_REG = const(0x07) 40 | PCF8563_YEAR_REG = const(0x08) 41 | PCF8563_SQW_REG = const(0x0D) 42 | PCF8563_TIMER1_REG = const(0x0E) 43 | PCF8563_TIMER2_REG = const(0x0F) 44 | PCF8563_VOL_LOW_MASK = const(0x80) 45 | PCF8563_minuteS_MASK = const(0x7F) 46 | PCF8563_HOUR_MASK = const(0x3F) 47 | PCF8563_WEEKDAY_MASK = const(0x07) 48 | PCF8563_CENTURY_MASK = const(0x80) 49 | PCF8563_DAY_MASK = const(0x3F) 50 | PCF8563_MONTH_MASK = const(0x1F) 51 | PCF8563_TIMER_CTL_MASK = const(0x03) 52 | PCF8563_ALARM_AF = const(0x08) 53 | PCF8563_TIMER_TF = const(0x04) 54 | PCF8563_ALARM_AIE = const(0x02) 55 | PCF8563_TIMER_TIE = const(0x01) 56 | PCF8563_TIMER_TE = const(0x80) 57 | PCF8563_TIMER_TD10 = const(0x03) 58 | PCF8563_NO_ALARM = const(0xFF) 59 | PCF8563_ALARM_ENABLE = const(0x80) 60 | PCF8563_CLK_ENABLE = const(0x80) 61 | PCF8563_ALARM_MINUTES = const(0x09) 62 | PCF8563_ALARM_HOURS = const(0x0A) 63 | PCF8563_ALARM_DAY = const(0x0B) 64 | PCF8563_ALARM_WEEKDAY = const(0x0C) 65 | 66 | CLOCK_CLK_OUT_FREQ_32_DOT_768KHZ = const(0x80) 67 | CLOCK_CLK_OUT_FREQ_1_DOT_024KHZ = const(0x81) 68 | CLOCK_CLK_OUT_FREQ_32_KHZ = const(0x82) 69 | CLOCK_CLK_OUT_FREQ_1_HZ = const(0x83) 70 | CLOCK_CLK_HIGH_IMPEDANCE = const(0x0) 71 | 72 | 73 | class PCF8563: 74 | def __init__(self, i2c, address=None): 75 | """Initialization needs to be given an initialized I2C port 76 | """ 77 | self.i2c = i2c 78 | self.address = address if address else PCF8563_SLAVE_ADDRESS 79 | self.buffer = bytearray(16) 80 | self.bytebuf = memoryview(self.buffer[0:1]) 81 | 82 | def __write_byte(self, reg, val): 83 | self.bytebuf[0] = val 84 | self.i2c.writeto_mem(self.address, reg, self.bytebuf) 85 | 86 | def __read_byte(self, reg): 87 | self.i2c.readfrom_mem_into(self.address, reg, self.bytebuf) 88 | return self.bytebuf[0] 89 | 90 | def __bcd2dec(self, bcd): 91 | return (((bcd & 0xf0) >> 4) * 10 + (bcd & 0x0f)) 92 | 93 | def __dec2bcd(self, dec): 94 | tens, units = divmod(dec, 10) 95 | return (tens << 4) + units 96 | 97 | def seconds(self): 98 | """Get the current allowed seconds of PCF8563 99 | """ 100 | return self.__bcd2dec(self.__read_byte(PCF8563_SEC_REG) & 0x7F) 101 | 102 | def minutes(self): 103 | """Get the current allowed minutes of PCF8563 104 | """ 105 | return self.__bcd2dec(self.__read_byte(PCF8563_MIN_REG) & 0x7F) 106 | 107 | def hours(self): 108 | """Get the current allowed hours of PCF8563 109 | """ 110 | d = self.__read_byte(PCF8563_HR_REG) & 0x3F 111 | return self.__bcd2dec(d & 0x3F) 112 | 113 | def day(self): 114 | """Get the current allowed day of PCF8563 115 | """ 116 | return self.__bcd2dec(self.__read_byte(PCF8563_WEEKDAY_REG) & 0x07) 117 | 118 | def date(self): 119 | """Get the current allowed date of PCF8563 120 | """ 121 | return self.__bcd2dec(self.__read_byte(PCF8563_DAY_REG) & 0x3F) 122 | 123 | def month(self): 124 | """Get the current allowed month of PCF8563 125 | """ 126 | return self.__bcd2dec(self.__read_byte(PCF8563_MONTH_REG) & 0x1F) 127 | 128 | def year(self): 129 | """Get the current allowed year of PCF8563 130 | """ 131 | return self.__bcd2dec(self.__read_byte(PCF8563_YEAR_REG)) 132 | 133 | def datetime(self): 134 | """Return a tuple such as (year, month, date, day, hours, minutes, 135 | seconds). 136 | """ 137 | return (self.year(), self.month(), self.date(), 138 | self.day(), self.hours(), self.minutes(), 139 | self.seconds()) 140 | 141 | def write_all(self, seconds=None, minutes=None, hours=None, day=None, 142 | date=None, month=None, year=None): 143 | """Direct write un-none value. 144 | Range: seconds [0,59], minutes [0,59], hours [0,23], 145 | day [0,7], date [1-31], month [1-12], year [0-99]. 146 | """ 147 | if seconds is not None: 148 | if seconds < 0 or seconds > 59: 149 | raise ValueError('Seconds is out of range [0,59].') 150 | seconds_reg = self.__dec2bcd(seconds) 151 | self.__write_byte(PCF8563_SEC_REG, seconds_reg) 152 | 153 | if minutes is not None: 154 | if minutes < 0 or minutes > 59: 155 | raise ValueError('Minutes is out of range [0,59].') 156 | self.__write_byte(PCF8563_MIN_REG, self.__dec2bcd(minutes)) 157 | 158 | if hours is not None: 159 | if hours < 0 or hours > 23: 160 | raise ValueError('Hours is out of range [0,23].') 161 | # no 12 hour mode 162 | self.__write_byte(PCF8563_HR_REG, self.__dec2bcd(hours)) 163 | 164 | if year is not None: 165 | if year < 0 or year > 99: 166 | raise ValueError('Years is out of range [0,99].') 167 | self.__write_byte(PCF8563_YEAR_REG, self.__dec2bcd(year)) 168 | 169 | if month is not None: 170 | if month < 1 or month > 12: 171 | raise ValueError('Month is out of range [1,12].') 172 | self.__write_byte(PCF8563_MONTH_REG, self.__dec2bcd(month)) 173 | 174 | if date is not None: 175 | if date < 1 or date > 31: 176 | raise ValueError('Date is out of range [1,31].') 177 | self.__write_byte(PCF8563_DAY_REG, self.__dec2bcd(date)) 178 | 179 | if day is not None: 180 | if day < 0 or day > 6: 181 | raise ValueError('Day is out of range [0,6].') 182 | self.__write_byte(PCF8563_WEEKDAY_REG, self.__dec2bcd(day)) 183 | 184 | def set_datetime(self, dt): 185 | """Input a tuple such as (year, month, date, day, hours, minutes, 186 | seconds). 187 | """ 188 | self.write_all(dt[6],dt[5], dt[4], dt[3], 189 | dt[2], dt[1], dt[0] % 100) 190 | 191 | def write_now(self): 192 | """Write the current system time to PCF8563 193 | """ 194 | self.set_datetime(utime.localtime()) 195 | 196 | def set_clk_out_frequency(self, frequency=CLOCK_CLK_OUT_FREQ_1_HZ): 197 | """Set the clock output pin frequency 198 | """ 199 | self.__write_byte(PCF8563_SQW_REG, frequency) 200 | 201 | def check_if_alarm_on(self): 202 | """Read the register to get the alarm enabled 203 | """ 204 | return bool(self.__read_byte(PCF8563_STAT2_REG) & PCF8563_ALARM_AF) 205 | 206 | def turn_alarm_off(self): 207 | """Should not affect the alarm interrupt state. 208 | """ 209 | alarm_state = self.__read_byte(PCF8563_STAT2_REG) 210 | self.__write_byte(PCF8563_STAT2_REG, alarm_state & 0xf7) 211 | 212 | def clear_alarm(self): 213 | """Clear status register. 214 | """ 215 | alarm_state = self.__read_byte(PCF8563_STAT2_REG) 216 | alarm_state &= ~(PCF8563_ALARM_AF) 217 | alarm_state |= PCF8563_TIMER_TF 218 | self.__write_byte(PCF8563_STAT2_REG, alarm_state) 219 | 220 | self.__write_byte(PCF8563_ALARM_MINUTES, 0x80) 221 | self.__write_byte(PCF8563_ALARM_HOURS, 0x80) 222 | self.__write_byte(PCF8563_ALARM_DAY, 0x80) 223 | self.__write_byte(PCF8563_ALARM_WEEKDAY, 0x80) 224 | 225 | def check_for_alarm_interrupt(self): 226 | """check for alarm interrupt,is alram int return True 227 | """ 228 | return bool(self.__read_byte(PCF8563_STAT2_REG) & 0x02) 229 | 230 | def enable_alarm_interrupt(self): 231 | """Turn on the alarm interrupt output to the interrupt pin 232 | """ 233 | alarm_state = self.__read_byte(PCF8563_STAT2_REG) 234 | alarm_state &= ~PCF8563_ALARM_AF 235 | alarm_state |= (PCF8563_TIMER_TF | PCF8563_ALARM_AIE) 236 | self.__write_byte(PCF8563_STAT2_REG, alarm_state) 237 | 238 | def disable_alarm_interrupt(self): 239 | """Turn off the alarm interrupt output to the interrupt pin 240 | """ 241 | alarm_state = self.__read_byte(PCF8563_STAT2_REG) 242 | alarm_state &= ~(PCF8563_ALARM_AF | PCF8563_ALARM_AIE) 243 | alarm_state |= PCF8563_TIMER_TF 244 | self.__write_byte(PCF8563_STAT2_REG, alarm_state) 245 | 246 | def set_daily_alarm(self, hours=None, minutes=None, date=None, weekday=None): 247 | """Set alarm match, allow sometimes, minute, day, week 248 | """ 249 | if minutes is None: 250 | minutes = PCF8563_ALARM_ENABLE 251 | self.__write_byte(PCF8563_ALARM_MINUTES, minutes) 252 | else: 253 | if minutes < 0 or minutes > 59: 254 | raise ValueError('Minutes is out of range [0,59].') 255 | self.__write_byte(PCF8563_ALARM_MINUTES, 256 | self.__dec2bcd(minutes) & 0x7f) 257 | 258 | if hours is None: 259 | hours = PCF8563_ALARM_ENABLE 260 | self.__write_byte(PCF8563_ALARM_HOURS, hours) 261 | else: 262 | if hours < 0 or hours > 23: 263 | raise ValueError('Hours is out of range [0,23].') 264 | self.__write_byte(PCF8563_ALARM_HOURS, self.__dec2bcd( 265 | hours) & 0x7f) 266 | 267 | if date is None: 268 | date = PCF8563_ALARM_ENABLE 269 | self.__write_byte(PCF8563_ALARM_DAY, date) 270 | else: 271 | if date < 1 or date > 31: 272 | raise ValueError('date is out of range [1,31].') 273 | self.__write_byte(PCF8563_ALARM_DAY, self.__dec2bcd( 274 | date) & 0x7f) 275 | 276 | if weekday is None: 277 | weekday = PCF8563_ALARM_ENABLE 278 | self.__write_byte(PCF8563_ALARM_WEEKDAY, weekday) 279 | else: 280 | if weekday < 0 or weekday > 6: 281 | raise ValueError('weekday is out of range [0,6].') 282 | self.__write_byte(PCF8563_ALARM_WEEKDAY, self.__dec2bcd( 283 | weekday) & 0x7f) 284 | --------------------------------------------------------------------------------