ライブラリないから自作せないかんやん。。。
ということで、手持ちのpsoc6とDS3231と通信できるようにします。
DS3231とは
DS3231とは、リアルタイムクロック(RTC)モジュールです。
I2Cでマイコンと通信させて時刻情報の設定・取得ができます。スレーブアドレスは0x68。
電源は3.3V、5Vともに可、400kHz通信で信号レベルは電源電圧と同等。
時刻誤差は2ppm。枝番があるようで末尾がSNだと2ppm、Mだと5ppm、Nだと偽物らしいです。
amazonだとボタン電池付きで1つ300円で手に入ります。
データシートは日本語化したので、こちら参照ください。
使い方
DS3231のレジスタマップを見てもらえればと思いますが、00番地は秒、01番地は分、のように決められています。
BCD方式
まず理解しておきたいのが、このICで設定する時刻情報はBCD方式を採用していて、
1バイトのうち、十の位を上位4ビット、一の位を下位4ビットで表現します。
そのため、45秒と秒レジスタに書き込みたい(←後述)場合、十の位の4と一の位の5を作って1バイト化しないといけないので、ちょっとめんどくさいです。
45の4は、10で割って4ビット左にシフトさせる、45の5は10で割った余りですね。
読み込むときもめんどくさいです。
0x45だったら、40は右に4ビットシフトして10倍して得られ、5は0x0Fの論理和をとればいいですね。
時刻情報を設定する
i2cの基本ですが、まずスレーブアドレス + R/Wビット0を送ってアクノリッジを確認します。
続いて、書込みの始点になるアドレスを送ります。
たとえば、0x02番地だったら、00000002ですね。
その後、書き込むデータを送ります。
このとき1バイトだけでなく、複数バイト書き込みすることもできます。
1バイト書き込むと、次のレジスタに向くので、また1バイト送るとそのレジスタに書き込まれます。
int8_t arr[4] = {0x02, 0x34, 0x12}
たとえば、この配列を送ると、
最初の1バイトが書き込みレジスタ指定で0x02番地が指定され、次の0x34で0x02番地に0x34を書き込みます。
DS3231は0x03番地に向くので、0x12が0x03番地に書き込まれる、ということです。
だから私は一回の書き込みで8バイト(レジスタ指定1バイト+データ7バイト)送って、0x00番地から0x06番地まで一気に書き込んでます。
時刻情報を取得する
時刻情報設定の最初にもやりましたが、まずスレーブアドレス + R/Wビット0を送ってアクノリッジを確認します。
続いて、読み込みの始点になるアドレスを送ります。
これをやらないと、直近の操作で向いたレジスタからの情報を取得してしまいます
つづいて、まずスレーブアドレス + R/Wビット1を送ってアクノリッジを確認します。
すると、このあとDS3231が始点のアドレスの中身を送ってくるので、マイコン側で受信処理します。
DS3231はマイコンが返すアクノリッジを確認すると、次のレジスタの中身を送ってきます。
ほしいバイトサイズ分のデータを配列に入れるなりして受け取ったら、マイコン側の受信処理を止めます。
DS3231はマイコンからのアクノリッジが返ってこないことを確認すると、データの送信を停止します。
まとめ
時刻の設定・取得はBCD方式なので、ちょっとめんどくさいです。
ただ一度コード作っちゃえば、すごく便利なICなのは間違いない!
FATFSでf_utimeと組み合わせて、ファイルに正確なタイムスタンプ機能を実装することもできます!
コメント