はじめに
先日Amazonから購入したTiny RTCをMachiKaniaで使ってっみました。日時の読み書き、不揮発性SRAM、EEPROMへのデータの読み書きができたのでその方法をまとめました。
検証環境
下記の環境で動作を確認しました。
- MachiKania簡易キット:Raspberry Pi Pico 2 Wを搭載しています
- MachiKania type P Phyllosoma 1.6.1.0
- Tiny RTC
Tiny RTC
Tiny RTCはリアルタイムクロックチップにDS1307を使用し、32Kビット(4Kバイト)のEEPROM AT24C32を搭載しています。DS1307は56バイトのバッテリバックアップされたSRAMを内蔵しているので少量ですがデータを保存できます。また、SQW/OUTピンから1Hz/4.096k/8.192k/32.768kHz を矩形波を出力できます。また、I2Cでアクセスできる容量4KバイトのEEPROM AT24C32を搭載しているので内蔵のSRAMよりも多くのデータを保存できます。
接続
Tiny RTCをMachiKania簡易キットのRaspberry Pi Picoを次の表に示すように接続しました。
| Tiny RTC | Pico |
|---|---|
| DS | 未接続 |
| SCL | DP7(10) |
| SDA | DP6(9) |
| VCC | VBUS(40) |
| GND | GND(38) |
Tiny RTCは3.3Vでは動作しませんでした。5Vを印加する必要があります。
写真の画面には以前作ったI2Cスレーブアドレスのスキャンプログラムの実行結果が表示されています。AT24C32とRS1307のスレーブアドレスが取得できているのがわかります。
DS1307の日時設定
DS1307に設定する日時はレジスタ0x00〜0x06に秒、分、時、曜日、日、月、年(西暦年下二桁)の順にそれぞれの値のBCDコードで書き込みます。
DS1307はI2Cでアクセスでき、そのスレーブアドレスは0x68です。
Radpberry Pi Pico WやPico 2 WでNTP経由で取得した日時をDS1307に設定しました。次のプログラムでRadpberry Pi Picoの日時を取得してDS1307に設定しました。
A=$68
DIM B(6)
I2C
REM Get datetime from Pico
T$=GETTIME$()
Y=VAL(STRFTIME$("%Y"))-2000
M=VAL(STRFTIME$("%m"))
D=VAL(STRFTIME$("%d"))
H=VAL(STRFTIME$("%H"))
I=VAL(STRFTIME$("%M"))
S=VAL(STRFTIME$("%S"))
POKE B+6,GOSUB(D2B,Y)
POKE B+5,GOSUB(D2B,M)
POKE B+4,GOSUB(D2B,D)
POKE B+3,GOSUB(WD,Y,M,D)
POKE B+2,GOSUB(D2B,H)
POKE B+1,GOSUB(D2B,I)
POKE B ,GOSUB(D2B,S)
REM Set datetime on DS1307 RTC
I2CWRITEDATA A,B,7,0
END
REM Convert BCD to decimal
LABEL B2D
VAR T
T=ARGS(1)
T=(T >> 4) * 10 +(T AND $0F)
RETURN T
REM Convert decimal to BCD
LABEL D2B
VAR T
T=ARGS(1)
T=((T/10)<<4) OR (T%10)
RETURN T
REM Get weekday number
LABEL WD
VAR Y,M,D,T,R
DIM T(11)
T(0)=0:T(1)=3:T(2)=2:T(3)=5
T(4)=0:T(5)=3:T(6)=5:T(7)=1
T(8)=4:T(9)=6:T(10)=2:T(11)=4
Y=ARGS(1)
M=ARGS(2)
D=ARGS(3)
IF M<3 THEN Y=Y-1
R=(Y+Y/4-Y/100+Y/400+T(M-1)+D)%7+1
RETURN R
DS1307のバッテリーバックアップSRAMの読み書き
DS1307のレジスタアドレス0x08〜0x3Fの56バイト領域は自由に読み書きできます。たとえば、文字列MachiKaniaをレジスタアドレス0x08からの領域に書き込み、読み出して表示する場合のコードは次のようになります。
REM Write string 'MachiKania'
S$="MachiKania"
I2CWRITEDATA A,S,LEN(S$),$08
REM Read SRAM DATA
DIM B(10)
I2CREADDATA A,B,LEN(S$),$08
FOR I=0 TO LEN(S$)-1
PRINT CHR$(PEEK(B+I));
NEXT
I2CWRITEDATA命令のバッファアドレスには文字列変数の接尾語$を除いた変数名を与えます。こうすると文字列の格納アドレスが得られます。
EEPROM AT24C32の読み書き
Tiny RTCに搭載されたEEPROM AT24C32はI2Cでアクセスできます。そのスレーブアドレスは0x50です。AT24C32は32Kビット(4Kバイト)の容量なのでそのアドレス範囲は0x0000〜0x0FFFとなります。読み書きする先頭アドレスを上位4ビット、下位4ビットに分けて送信し、データを読み書きします。
次のコードはアドレス0x0010からの領域に文字列MachiKaniaを書き込み、読み取るものです。バッテリバックアップSRAMへのアクセスとほぼ同じです。
REM READ/WRITE EEPROM(AT24C32)
USEVAR EE,ADR,HI,LO
DIM B(10)
EE=$50 : REM EEPROM I2C address
ADR=$0010 : REM memory address
I2C
HI=ADR/256
LO=ADR AND $FF
REM Write string
S$="MachiKania"
I2CWRITEDATA EE,S,LEN(S$),HI,LO
GOSUB EE_WAIT
REM Read string
I2CREADDATA EE,B,LEN(S$),HI,LO
REM Print string
PRINT "READ: ";
FOR I=0 TO LEN(S$)
PRINT CHR$(PEEK(B+I));
NEXT
PRINT
END
REM Wait for write to complete
LABEL EE_WAIT
DO
I2CWRITE EE,0
DELAYMS 1
LOOP WHILE I2CERROR()!=0
RETURN
さいごに
DS1307の日時設定は以前使ったDS3231とスレーブアドレス、レジスタアドレスも同じで、プログラムを流用できました。
EEPROM AT24C32の使い方はChatGPT 5.2 Thinkingで調べ、コードを作成させました。ほぼ正しいコードが作成されていたので情報源を確認すると、自分のQiitaへの投稿が含まれていました。
DS1307の不揮発性SRAMやEEPROMが利用できるのはストレージを持てないシステムでは有用だなと思おいました。
