RTC-8564NB
2023/03/28
MicroPython1.17(ESP32)
リアルクロックタイムIC、RTC-8564NBの設定(I2C通信)
import machine
import math
from machine import Pin, SoftI2C
class RTC_8564NB:
def __init__(self,scl,sda,freq=100000,reset=True):
self.connected = False
self.i2c = SoftI2C(scl=Pin(scl), sda=Pin(sda), freq=freq)
ls = self.i2c.scan()
if len(ls) == 0:
print('error: cannot find i2c slave')
return
found = False
for addr in ls:
if addr == 0x51:
found = True
break
if not found:
print('error: cannot find RTC_8564NB')
return
self.connected = True
if reset:
self.reset()
def reset(self):
self.i2c.writeto(0x51,b'\x00\x00\x00')
def set_time(self,years,months,days,hours,minutes,secconds):
if not self.connected:
print('error: disconnect RTC module')
return
if years > 2000:
century = 1
else:
century = 0
years = int2bcd(years % 100)
months = int2bcd(months) & 0b00011111
if century:
months = months | 0b10000000
days = int2bcd(days)
hours = int2bcd(hours)
minutes = int2bcd(minutes)
secconds = int2bcd(secconds)
weekdays = 0b000 #sunday (not used)
values = bytes([2,secconds,minutes,hours,days,
weekdays,months,years])
self.i2c.writeto(0x51,values)
def time(self):
if not self.connected:
print('error: disconnect RTC module')
self.i2c.writeto(0x51, b'\x02')
data = self.i2c.readfrom(0x51, 7)
vol_low = data[0] >> 7
if vol_low == 1:
print('error: voltage low bit is set. must be reset.')
return
secconds = bcd2int(data[0] & 0b01111111)
minutes = bcd2int(data[1] & 0b01111111)
hours = bcd2int(data[2] & 0b00111111)
days = bcd2int(data[3] & 0b00111111)
months = bcd2int(data[5] & 0b00011111)
century = data[5] >> 7
years = bcd2int(data[6])
if century == 1:
years += 2000
else:
years += 1900
return [years,months,days,hours,minutes,secconds]
def set_alarm(self,day=None,hour=None,minute=None):
self.i2c.writeto(0x51,b'\x09\x80\x80\x80') #reset
if day != None:
day = int2bcd(day) & 0b00111111
self.i2c.writeto(0x51,bytes([0x0B,day]))
if hour != None:
hour = int2bcd(hour) & 0b00111111
self.i2c.writeto(0x51,bytes([0x0A,hour]))
if minute != None:
minute = int2bcd(minute) & 0b01111111
self.i2c.writeto(0x51,bytes([0x09,minute]))
def start_alarm(self):
self._alarm_enable(True)
def stop_alarm(self):
self._alarm_enable(False)
def _alarm_enable(self,enable):
self.i2c.writeto(0x51, b'\x01')
data = self.i2c.readfrom(0x51, 1)[0]
if enable:
data = data | 0b00000010 #set AIE
else:
data = data & 0b11111101 #clear AIE
self.i2c.writeto(0x51,bytes([0x01,data]))
def alarm_flag(self,clear=False):
self.i2c.writeto(0x51,b'\x01')
data = self.i2c.readfrom(0x51,1)[0]
r = (data & 0b00001000) >> 3
if clear:
data = data & 0b11111101 #clear
self.i2c.writeto(0x51,bytes([0x01,data]))
return r
def set_timer(self,count,freq_mode=2,pulse_mode=False):
'''
freq_mode: 0 => 4096Hz, 1 => 64Hz, 2 => 1Hz, 3 => 1/60Hz
count: 0~256
pulse_mode: True/False
'''
#write timer control
if freq_mode == 1:
data = 0b01
elif freq_mode == 2:
data = 0b10
elif freq_mode == 3:
data = 0b11
self.i2c.writeto(0x51,bytes([0x0E,data,count]))
#write control 2
self.i2c.writeto(0x51,b'\x01')
data = self.i2c.readfrom(0x51,1)[0]
if pulse_mode:
data = data | 0b00010000 # set TI/TP
else:
data = data & 0b11101111 #clear TI/TP
self.i2c.writeto(0x51,bytes([0x01,data]))
def start_timer(self):
self.timer_flag(clear=True)
self._timer_enable(True)
def stop_timer(self):
self._timer_enable(False)
def _timer_enable(self,enable):
#write TIE
self.i2c.writeto(0x51,b'\x01')
data = self.i2c.readfrom(0x51,1)[0] #control 2
if enable:
data = data | 0b00000001 # set TIE
else:
data = data & 0b11111110 #clear TIE
self.i2c.writeto(0x51,bytes([0x01,data]))
#write TE
self.i2c.writeto(0x51,b'\x0E')
data = self.i2c.readfrom(0x51,1)[0] #timer control
if enable:
data = data | 0b10000000 # set TE
else:
data = data & 0b01111111 #clear TIE
self.i2c.writeto(0x51,bytes([0x0E,data]))
def timer_flag(self,clear=False):
self.i2c.writeto(0x51,b'\x01')
data = self.i2c.readfrom(0x51,1)[0]
r = (data & 0b00000100) >> 2
if clear:
data = data & 0b11111110 #clear
self.i2c.writeto(0x51,bytes([0x01,data]))
return r
def timer_count(self):
self.i2c.writeto(0x51,b'\x0F')
data = self.i2c.readfrom(0x51,1)[0]
return data
def bcd2int(byte):
conv = [1,2,4,8]
dt = 0
for i in range(4):
dt += ((byte >> i+4) & 1)*conv[i]
dt = dt*10
for i in range(4):
dt += ((byte >> i) & 1)*conv[i]
return dt
def int2bcd(number):
ten_dig = int(hex(math.floor(number/10)))
ten_bin = ten_dig.to_bytes(1,'big')
one_dig = number % 10
one_bin = one_dig.to_bytes(1,'big')
value = ten_bin[0] << 4 | one_bin[0]
return value.to_bytes(1,'big')[0]
def alarm_test():
import utime
rtc = RTC_8564NB(scl=21,sda=25)
rtc.set_time(2023,3,3,12,59,55)
rtc.set_alarm(hour=13,minute=0)
rtc.start_alarm()
print('start alarm test')
while True:
print(rtc.time())
if rtc.alarm_flag():
print('its time!')
break
utime.sleep(1)
utime.sleep(1)
rtc.alarm_flag(clear=True)
rtc.stop_alarm()
def timer_test():
import utime
rtc = RTC_8564NB(scl=21,sda=25)
rtc.set_timer(5,freq_mode=2)
rtc.timer_flag()
rtc.start_timer()
print('start timer test')
while True:
print(rtc.timer_count())
if rtc.timer_flag():
print('its time!')
break
utime.sleep(1)
utime.sleep(1)
rtc.timer_flag(clear=True)
rtc.stop_timer()
if __name__ == '__main__':
#alarm_test()
timer_test()
MicroPythonでリアルタイムクロックRTC-8564NBを使う
https://tiblab.net/blog/2023/03/use_rtc-8564nb_by_micropython/