マイクロビット(e_48)DS3231 の使い方を再考
DS3231 の再検討
以前、DS3231 RTCを搭載したリアルタイムクロックモジュールの使い方を記事(e_17、18)で記載したのですが、複雑になってしまいスッキリしませんでした。そのため、再検討をしました。少しは簡略になったと思うので記載します。※24H表示のみに対応しています。
改善したスクリプトだけ記載します。DS3231の詳細は記事(e_17、18)を参照してください。
カレンダ設定
write_Cal(l_cal)でカレンダデータを設定します。
設定するデータを「2022/06/16 17:08:56 Thu」なら l_cal=([2022, 06, 16, 17, 08, 56, 4]) のようにリストで与えるようにしました。
read_Cal()で設定値を読み出します。
24H表示のみに対応しています。
スクリプト
ds3231_rwCal_data_b.py
from microbit import *
#RTC DS3231 0x68(104)
adr_rtc=0x68
# 書込むデータを上位下位に分ける hex表示にすると読視できる
def s_dat(dat):
s_dat=(dat//10 << 4) | (dat%10)
return s_dat
# カレンダデータをリストデータ(l_data)で与える
def write_Cal(l_data):
dat=l_data
s_reg=bytearray(1)
s_reg[0]=0x00 # write start regi
# リストデータをバイトアレイに割り当てる
buf=bytearray(7)
# 0x00 seconds
buf[0]= s_dat(dat[5])
# 0x01 minutes
buf[1]= s_dat(dat[4])
# 0x02 hour
buf[2]= s_dat(dat[3])
# 0x03 day of week
buf[3]= s_dat(dat[6])
# 0x04 date
buf[4]= s_dat(dat[2])
# 0x05 month over century
buf[5]= s_dat(dat[1])
# 0x06 year
buf[6]= s_dat(dat[0]-2000)
# writing to registers
s_buf=bytearray(8)
s_buf=s_reg+buf # 開始レジスタ+データ
i2c.write(adr_rtc,s_buf)
# 現在のカレンダデータを読み出す
def read_Cal():
# read real time
wday=['sun','mon','tue','wed','thu','fri','sat']
s_reg=bytearray(1)
s_reg[0]=0x00
i2c.write(adr_rtc,s_reg)
r_reg=i2c.read(adr_rtc,7) # 7bytes読込
r_data=[]
for i in range(7):
a=hex(r_reg[i])[2:] #a='0x36' a[2:]='36' 0xを除外して 読む
if i==3: # 0x03 曜日に
a=wday[int(a)]
if i==6:
a=str(2000+int(a)) # 0x06 2000を足して西暦に
r_data.append(a)
# [::-1][0:3] [::-1][4:7] [::-1][3:4] 逆ソートしてから並べ替える
ss=r_data[::-1][0:3]+r_data[::-1][4:7]+r_data[::-1][3:4]
return ss
##-----------------------------------------
# Callender 24H display dayweek sun(0)
# 2022/06/16 17:08:56 thu ( 0:sun 1:mon 2:tue 3:wed...)
l_cal=([2022, 06, 16, 17, 08, 56, 4])
write_Cal(l_cal)
print(read_Cal())
実行結果
設定値の確認結果がThonnyのshellに表示されます。
>>> %Run ds3231_rwCal_data_b.py
['2022', '6', '16', '17', '8', '56', 'thu'] # 設定直後に読み込んでいるので設定値が表示されている
アラーム設定
write_Adata(set_ldata)
アラームデータを設定します。
設定するデータをset_ldata=[a1,a2,a1m,a2m,a1d,a2d] のようにリストで与えるようにしました。
各々のデータもリストデータです。※詳細はデータシート、記事を参照下さい。
a1、a2は時間のマッチデータ
a1=[59,59,23,30] # sec,min,hour,day/date
a2=[59,23,30] # min,hour,day/date
a1m、a2m、時間、a1d、a2dは日、曜日のマスクビット設定になります。
a1m=[0,1,1,1] #alarm1 mask
a2m=[0,1,1] #alarm1 mask
a1d=[''] #day/date '','0','1' 自動的に a1m=[0,0,0,0]
a2d=[''] #day/date '','0','1' 自動的に a2m=[0,0,0]
read_Adata()
アラーム設定データを読み出します。
スクリプト
ds3231_rwAlm_data_b.py
from microbit import *
#ds3231_test_02.py から関数化
#write_Adata(mach mask) read_Adata
#RTC DS3231 only 0x68(104) EEPROM(AT24C32)0x50~0x57
adr_rtc=0x68
# 書込むデータを上位下位に分ける hex表示にすると読視できる
def s_dat(dat):
s_dat=(dat//10 << 4) | (dat%10)
return s_dat
# 8bitの表示ゼロ穴埋
# zero padding 8-12bit
def z_padd(dat): # int
dat=bin(dat) # str
value='0b'+'0'*(8-len(dat[2:])) + dat[2:] # str 8bit
#value='0'*(12-len(dat[2:])) + dat[2:] # str 12bit
return value
# read 1-register
def read_reg(reg):
s_reg=bytearray(1)
s_reg[0]=reg
i2c.write(adr_rtc,s_reg)
read_reg=i2c.read(adr_rtc,1)
return read_reg
# アラームマッチデータ、マスクデータを書込む
# ldata=[a1,a2,a1m,a2m,a1d,a2d] a1など各々もリスト
def write_Adata(ldata):
a1= ldata[0]
a2= ldata[1]
a1m=ldata[2]
a2m=ldata[3]
a1d=ldata[4]
a2d=ldata[5]
# write alarm data set-regi 0x07-0xd
s_reg=bytearray(1)
s_reg[0]=0x07 # write start regi-num
buf=bytearray(7)
for i in range(4):
buf[i]=s_dat(a1[i]) #一致データを上位下位に変換 マッチデータ
# mask bitを付加
if a1d[0]=='': # DY/DTの設定が無い場合
buf[i]=buf[i] | a1m[i]<< 7 # AM bit7
else:
buf[i]=buf[i] & 0x7f # AM bit7= '0'にする
if a1d[0]=='1': # DY(day)を設定する場合
buf[3]=buf[3] | 0x40 # DY/DT bit '1'
for i in range(3):
buf[i+4]=s_dat(a2[i]) #設定データを上位下位に変換する
# mask bit
if a2d[0]=='':
buf[i+4]=buf[i+4] | a2m[i]<< 7
else:
buf[i+4]=buf[i+4] & 0x7f # AM bit7 '0'
if a2d[0]=='1':
buf[6]=buf[6] | 0x40 # DY/DT bit wo '1'
# regi-addres,write-bytearray
s_buf=s_reg+buf # bytearrayは足し算できる 開始レジスタ+データ
i2c.write(adr_rtc,s_buf) # write mach data
# read alarm data -------------------------
def read_Adata():
s_reg=bytearray(1)
s_reg[0]=0x07
i2c.write(adr_rtc,s_reg)
r_reg=i2c.read(adr_rtc,7)
return r_reg
## -----------------------------------------
# mach data 設定するマッチデータ
a1=[59,59,23,30] # sec,min,hour,day/date
a2=[59,23,30] # min,hour,day/date
# ALARM MASK BITS 飛び設定は出来ない[1,0,1,0] マスクデータ(一致箇所)
a1m=[0,1,1,1] #alarm1 mask(bit7)[1,1,1,1][0,1,1,1][0,0,1,1][0,0,0,1]
a2m=[0,1,1] #alarm1 mask(bit7)[1,1,1][0,1,1][0,0,1]
a1d=[''] #day/date '','0','1' 自動的に a1m=[0,0,0,0]
a2d=[''] #day/date '','0','1' 自動的に a2m=[0,0,0]
set_ldata=[a1,a2,a1m,a2m,a1d,a2d]
# wirte mach mask Adata
write_Adata(set_ldata)
# read Adata
r_reg=read_Adata()
for i in range(7):
print(hex(7+i),z_padd(r_reg[i]))
実行結果
設定値の確認結果がThonnyのshellに表示されます。
>>> %Run ds3231_rwAlm_data_b.py
0x7 0b01011001
0x8 0b11011001
0x9 0b10100011
0xa 0b10110000
0xb 0b11011001
0xc 0b10100011
0xd 0b10110000
>>>
フラグ・割込設定
以下のようにしました。
read_Aflg()
アラームフラグ|A2F|A1F|の状態を返します。
reset_Aflag()
アラームフラグ|A2F|A1F|をリセットします。
set_Aie(s_num=3)
|A2IE|A1IE|の割込み許可を設定します。デフォルトは|A2IE|A1IE|両方の3になります。
read_Aie()
|INTCN|A2IE|A1IE|の状態を返します。
スクリプト
ds3231_rwAie_data_b.py
from microbit import *
# Alarm Flag(read,reset) Ctrl-AIE(read,set)
# RTC DS3231 only 0x68(104) EEPROM(AT24C32)0x50~0x57
adr_rtc=0x68
# read 1-register
def read_reg(reg):
s_reg=bytearray(1)
s_reg[0]=reg
i2c.write(adr_rtc,s_reg)
read_reg=i2c.read(adr_rtc,1)
return read_reg
## Alarm Flag
# read Alarm Flag |A2F|A1F|
def read_Aflg():
a_flag=read_reg(0x0f)[0]& 0x03
#print('Aflg=',bin(a_flag))
return a_flag
# reset Alarm Flag |A2F|A1F|
def reset_Aflag():
r_reg=read_reg(0x0f)
buf=bytearray(2)
buf[0]=0x0f # 0x0fを読出して|A2F|A1F|をリセットして書込む
buf[1]=r_reg[0] & 0xfc # 0b_1111_1100
i2c.write(adr_rtc,buf)
#print('reset 0x0f=',buf[1],bin(buf[1]))
## INTCON Alarm INT Enabel
# read |INTCN|A2IE|A1IE| Control/Status(0x0e)
def read_Aie():
a_ie= read_reg(0x0e)[0] & 0x07
#print('INT-AIE=',bin(a_ie))
return a_ie
# write |A2IE|A1IE| Control/Status(0x0e)
def set_Aie(s_num=3):
r_ie=read_reg(0x0e)[0] & 0xfc #|A2IE|A1IE|をリセットして値を書込む
aie=s_num # 00,01,10,11(0,1,2,3)
buf=bytearray(2)
buf[0]=0x0e
buf[1]=r_ie | aie
i2c.write(adr_rtc,buf)
## MAIN-----------------------------------------
# read_Aflg reset_Aflag read_Aie set_Aie
print('|A2F|A1F|=',bin(read_Aflg())) #|A2F|A1F|の状態
print('|INTCN|A2IE|A1IE|=',bin(read_Aie())) #|A2IE|A1IE|の状態
set_Aie(2) #|A2IE|をセット
print('|INTCN|A2IE|A1IE|=',bin(read_Aie())) #|A2IE|A1IE|の状態
reset_Aflag() #|A2F|A1F|リセット
print('|A2F|A1F|=',bin(read_Aflg())) #|A2F|A1F|の状態
実行結果
実行結果がThonnyのshellに表示されます。
>>> %Run 'ds3231_rwAie_data_b.py'
|A2F|A1F|= 0b11 # AlarmFlag状態
|INTCN|A2IE|A1IE|= 0b100 # 割込み許可の状態 |A2IE|A1IE|ともに無許可
|INTCN|A2IE|A1IE|= 0b110 # A2IEをセット 割込み許可
|A2F|A1F|= 0b0 #reset_Aflag()
>>>
まとめ
前回よりかなり簡素になり分かりやすくなったように思います。