正月休みは風邪引いて本物の寝正月で、趣味の工作など、全く出来なかった。
去年の11月終わりに請けた仕事も、ようやく何とかなりそうで、やっとRXマイコン
を再開した。
RX64M、176ピンは、内臓RTCを持っており、バックアップ用別電源端子が用
意されている。
※ VBATT(15)
※バッテリーバックアップできないようなRTCは、ほとんど利用価値が無い為、外部
にさらにRTCを繋ぐ必要がある。
RX64M、RTCのもう一つのメリットは、バイナリーカウンターモードがある点で、
これは、やっとまともな仕様になったとも言える。
時間管理を普通にやる場合、シリアライズがどうしても必要だが、一般的なRTCのレ
ジスター構成は、二度手間になるだけで何のメリットも無いものになっている。
※レジスターは、秒、時間、日、月、年、曜日などに分かれており、扱いが容易では無
い、これは、30年前以前の処理能力が無かった時代の腐った仕様が現役になっている。
時間の設定や、時間管理を考えた場合、「うるう年」や「曜日」の管理を行うのが普通
なので、基点からの経過時間(秒)で管理するのが確実だ、従って、RTCは、単純な
秒単位のカウンターが一番適している。
ハードウェアーデバイスに着目すると、単なるバイナリーカウンターのRTCも流通し
てはいるが、腐った仕様のRTCよりコストが高い事に驚く。
※DS1371などがバイナリー仕様のRTC
バイナリーカウンタRTC:
DS1371(単価341円)
年、月、日、時間RTC:
MCP79410(単価122円)
DS3231モジュール(単価110円)
※何でこんな値段でやれるのか、不思議でならない・・・
リチウムイオン電池には直列に逆流防止ダイオードを入れる。
ただ注意しなければならないのは、順方向電圧降下が少ないタイプ(ショットキー)は
逆方向電流が多い物が多い、今回は、RB751S-40を使った。
RX64M内臓のRTCは、バイナリーカウンターなので、非常に簡単に実装する事が
できた。
RTCの読み出しでは、注意する必要がある。
複数の非同期カウンターをどのように読むべきか?
何も考えずに読み出すと、カウントアップ時の非同期性の為、間違った値を読んでしま
う事がある。
全てのカウンターレジスター更新には、多少の時間的ズレがある為、確率的に全てのカ
ウント更新が終了していない中途半端な状態を読み出してしまう為で、以前に観た実装
では、RTCから1Hz出力を出して、それを割り込みを使って、そのタイミングで読
み出すとかしていた、しかもこの方法でも、正しい値を読み出せる保障は無く、多分、
「たまたま」うまく読み出せているだけで、RTCが違う場合には、うまくいかない場
合もあるかもしれない。
非同期で動作する複数のカウンターがある場合、以下のように、二度読み出して、両方
同じなら、「値を信用」し、違えば、二度同じ値になるように読み出すループを作れば
良い。
腐った仕様のRTCでは、利用するレジスター全てを比較する。
bool get_time(time_t& tp) const { auto a = get_(); for(int i = 0; i < 5; ++i) { auto b = get_(); if(a == b) { tp = static_cast(a); return true; } a = b; } return false; }
そして、
以前に、R8C、RL78のRTC用に実装した、マネージメントを組み込んだ。
時間関数は、libc に含まれているが、巨大なので、必要最低限の実装を行った独自の
「common/time.c」を使っている。
※「うるう秒」の補正は行っていない。
# RX64M RTC sample # help date date yyyy/mm/dd hh:mm[:ss] # date Sat Jan 14 23:13:56 2017
コマンドラインから、時間設定と、表示を行う事ができる。
時間管理は、「time_t」(基点からの経過秒数)で行っており、内部はグリニッジ標準
時間を使い、タイムゾーン(東京+9時間)はハードコートしてある。
RX64Mのバックアップ機能も問題無く動作しているようだ~