-
Notifications
You must be signed in to change notification settings - Fork 0
XRTC_PCF85063A
これはNXP PCF85063A
カレンダーIC(外部RTC)を制御するインタフェースを提供する。
この I2CデバイスIC は "Duino" 系列製品のオンボードに搭載されており
内臓周辺機能での計時なしに長周期割込、アラーム割込、カレンダー日時保持を提供する。
以下の解説では暗に "Duino" ボード固有機能を前提にした内容も含まれることに注意されたい。
#include <XRTC_PCF85063A.h>
XRTC_PCF85063A XRTC = {Wire};
void setup (void) {
pinControlRegister(PIN_PF1) = PORT_PULLUPEN_bm | PORT_ISC_FALLING_gc;
Serial.begin(CONSOLE_BAUD);
Wire.initiate(TWI_SM);
if (!XRTC.update()) {
Serial.println(F("Failed XRTC"));
for (;;);
}
XRTC.startPeriodTimer(1);
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_enable();
}
ISR(PORTF_PORT_vect) {
PORTF_INTFLAGS = PIN1_bm;
}
void loop (void) {
digitalWrite(LED_BUILTIN, TOGGLE);
if (XRTC.update()) {
bcddatetime_t BCD = XRTC.getBcdDateTimeNow();
Serial
.print(_BCDDT(BCD)->col.year, ZHEX, 4)
.write('-')
.print(_BCDDT(BCD)->col.month, ZHEX, 2)
.write('-')
.print(_BCDDT(BCD)->col.day, ZHEX, 2)
.write(' ')
.print(_BCDDT(BCD)->col.hour, ZHEX, 2)
.write(':')
.print(_BCDDT(BCD)->col.minute, ZHEX, 2)
.write(':')
.print(_BCDDT(BCD)->col.second, ZHEX, 2)
.ln();
}
Serial.flush();
sleep_cpu();
}
この用例ではXRTC
に1秒周期割込を指示し、
それをPIN_PF1
端子で捉えて CPU休止状態を解除し、
シリアルモニターに現在時刻を表示してまた
CPU休止状態に入る動作を繰り返す。
時刻取得と表示には
<bcddatetime.h>
を利用している。
時刻設定を使わずに単に周期割込を発生させたいだけならstartPeriodTimer
を、
単発割込を発生させたいだけならstartCountdownTimer
を使えば良い。
割込出力はオープンドレインなので、外部入力端子にプルアップ設定は必要。
/* 60秒周期割込 : 毎00秒発動 */
XRTC.setMinuteInterruptEnable(true).activeTimer();
/* 30秒周期割込 : 毎00秒と毎30秒発動 */
XRTC.setHarfMinuteInterruptEnable(true).activeTimer();
/* その他任意長周期割込 : 1〜15300 秒範囲 : 現時刻起点 */
XRTC.startPeriodTimer(20);
/* 単発タイムアウト割込 : 1〜15300 秒範囲 : 現時刻起点 */
XRTC.startCountdownTimer(20);
/* 単発割込解除 : 解除するまで割込端子は LOW を維持 */
XRTC.clearTimerFlag();
/* 割込タイマー動作停止 */
XRTC.deactiveTimer();
このデバイスを使用せず、時刻管理も不要なら次の方法で停止できる。 停止しなければ不意に周期割込等が発生する場合がある。
/* デバイスを初期状態に戻し、計時機能停止 */
XRTC.reset();
XRTC.stop();
PCF85063A
の場合、年は2桁精度かつセンチュリービット機能を持たない。
このため00
年には常に2月29日があり、2000
年以外と一致しない。
つまり時刻管理の有効範囲は1900-03-01
から2100-02-28
である。
しかし曜日はそれと無関係に正しく更新されるので、
getCenturyDateTimeNow
メソッドは以下の補正を加えることで
1900-01-01
から2299-12-31
の400年間を正しく返却できる。
- 現在年月日を
2000-01-01
から2099-12-31
と見做して MJD(修正ユリウス通日)を取得。 - MJDから得られる曜日から現在保持している曜日を減じて
7
の剰余X
を得る。 -
X
が0
であるなら2000
年代であるから補正不要。 - MJDが
51603
以下(2000-02-29
以前)である場合、
a. MJDが51603
であるなら存在してはならない閏日であるからY
をマーク。
b.X
が5
であるなら1900
年代であるからMJDより36524
を減じる。
c.X
が1
であるなら2100
年代であるからMJDに36525
を加える。
d.X
が3
であるなら2200
年代であるからMJDに73049
を加える。 - MJDが
51604
以上(2000-03-01
以降)である場合、
a.X
が6
であるなら1900
年代であるからMJDより36525
を減じる。
b.X
が2
であるなら2100
年代であるからMJDに36524
を加える。
c.X
が4
であるなら2200
年代であるからMJDに73048
を加える。 - 補正されたMJDから新たな年月日を導く。これは同時に存在しない
02-29
を03-01
に置換する。 -
Y
がマーク済なら現在年月日は誤りなので、新たな年月日を現在年月日に設定する。
上記の補正判定から漏れた年月日と曜日の組は、
グレゴリウス暦には存在しないので2000
年代と見做さざるを得ない。
何故ならグレゴリウス暦は以下の式に従って、400年間で年月日と曜日の組が循環しているからだ。
400年 × 365日 + 閏日97日 == 146097日 == 20871週 × 7日(端数なし)
この性質から100年毎の同月同日の曜日はただ4通りしかなく、 それを超える範囲は曜日補正法では求めることが出来ない。
もしそれが必要なら西暦上位桁を
setRamByte
で保持しておいて補うと良い。
依存性:<api/TWIM.h>
<bcddatetime.h>
classXRTC_PCF85063A
を定義する。
初期化子にはTWIM_Class
インスタンス(Wire
等)を与える。
その I2C Bus を別途初期化することで、デバイス通信準備が整う。
通信速度は通常 100kbps(TWI_SM
)を指示するが、
400kbps(TWI_FM
)でも、
10kbps(TWI_LM
)でも良い。
#include <XRTC_PCF85063A.h>
XRTC_PCF85063A XRTC = {Wire};
...
Wire.initiate(TWI_SM); /* Wire.begin(100000L) も可 */
XRTC.update();
PCF85063A
の場合、2種類の精度校正機能がある。
また1バイトの任意RAM保持機能がある。
デバイスの現在の制御状態を取得する。実行は即時。成功すれば真を返す。 これには現在の時刻情報の他、各種制御状態が含まれる。 遅延中の設定命令は反映されずに破棄される。 このメソッドは、これ以後の他の制御に先立って呼ばれなければならない。
これはupdate
メソッドの別名として機能する。
デバイスに新たな制御状態を反映させる。実行は即時。成功すれば真。 これは「実行は遅延」と説明された設定変更を、デバイスに送信する。
デバイスを再起動する。実行は即時。update
も続けて実行され、成功すれば真。
現在時刻は破棄されて2000-01-01 00:00:00
から計時を始め、
アラームとタイマーは停止され、
周波数出力(COT)端子制御は初期設定となり、
isPowerDown
は真となる。
デバイスが再起動したか、バックアップ電源喪失を経験したなら真を返す。 現在時刻は信用できない。 あらたな時刻を再設定するまで真に留まる。
テストモードが有効なら真。通常運用では使用しない。
水晶発振子負荷容量設定の選択値を返す。通常運用では使用しない。
ユーザー設定RAMバイトの設定値を返却する。保持できるのは1バイトだけである。
テストモードの有効
/無効
を真
/偽
で設定する。実行は遅延。メソッドチェーンが後続できる。
通常運用では使用しない。
水晶発振子負荷容量12.5pf
/7pf
の切替を真
/偽
で設定する。実行は遅延。メソッドチェーンが後続できる。
通常運用では使用しない。
"Duino" ボードでは通常
7pf
水晶発信子が搭載されているので既定値でよい。
ユーザー設定RAMバイトを0
〜255
の範囲で設定する。実行は遅延。メソッドチェーンが後続できる。
使用は任意。保存期間はバックアップキャパシタ次第。
デバイス再起動で0
初期化される。
1バイトしか保持できないので用途は限られるだろう。
NIMEM
機能を使うほうがより大容量を保持できてかつ非破壊検査が出来る。
精度校正モード設定の選択値を真理値で返す。
精度校正が有効である時、補正パルスの割込端子出力が設定されているならば真。通常運用では使用しない。
精度校正の現在の補正値を返却する。
精度校正モードの1
/0
の別を真
/偽
で設定する。実行は遅延。メソッドチェーンが後続できる。
校正モード0の場合、2時間毎(時桁が偶数の時)起点で指定数の 1/32768秒×分 を増やすか減らす。 つまり調整可能精度は ±4.34 ppm 粒度。
例えば精度校正値が
-3
だと、2時間に付き 1/32768秒 が 1分間隔で 3回減らされる。
校正モード1の場合、4分毎(分桁が4の倍数の時)起点で指定数の 1/32768秒×秒 を増やすか減らす。 つまり調整可能精度は ±4.069 ppm 粒度。
例えば精度校正値が
-3
だと、4分に付き 1/32768秒 が 1秒間隔で 3回減らされる。
精度校正は時刻刻みに対して行われるが、周波数出力端子の出力周波数には影響しない。
精度校正モードで補正クロックが挿入/除去されるとき、
割込端子を活動させるかを真
/偽
で設定する。実行は遅延。メソッドチェーンが後続できる。
精度校正値を-64
〜+63
の範囲で設定する。実行は遅延。メソッドチェーンが後続できる。
更新反映は次回校正時刻から有効。
時刻管理には既定の 24時間表現モードと、12時間表現モードとがある。 両者の切替は透過ではないので時刻の再設定が必要になる。
PCF85063A
の年管理は2桁だがセンチュリービットはサポートされていない。
このため年が00
の場合、常に閏日(2月29日)が存在する。
しかし曜日更新はそれと別に機能するからソフトウェアで閏日補正を行うことができ、
1900
〜2299
年範囲の西暦を正しく扱うことが出来る。
なおPCF85063A
にはタイムスタンプ(ストップウォッチ)モードはなく、切り替えもできない。
計時停止中のデバイスに計時を再開させる。実行は即時。成功すれば真。 成功すればちょうど 0.5秒後に最初の計時(秒の桁の)インクリメントが発生する。 計時タイミング合わせに使用する。
計時中のデバイスに計時を停止させる。実行は即時。成功すれば真。 計時タイミング合わせ、あるいはデバイスを使用しない場合の省電力待機に使用する。
デバイスが計時中なら真を返す。stop
メソッドを実行するまで真に留まる。
デバイスが計時停止中なら真を返す。start
メソッドを実行するまで真に留まる。
デバイスが12時間表現モードで稼働中なら真を返す。 24時間表現モード(既定値)で稼働中なら偽を返す。
計時機能の計時
/停止
を真
/偽
で設定する。実行は遅延。メソッドチェーンが後続できる。
start
stop
と機能は同じだが即時実行ではない。
時刻表示モードの12時間制
/24時間制
の別を真
/偽
で設定する。実行は遅延。メソッドチェーンが後続できる。
時刻表示モード変更後の時刻保持内容は不正であるから、改めて設定しなければならない。
現在時刻をtime_t
型のUNIX Epoch
に変換して返却する。
UTC(世界協定時)か否かは使用者定義による。
返却値は現在時刻が西暦
2000
〜2099
年範囲のあいだのみ正しい。
getEpochNow
の別名。
現在時刻をbcddatetime_t
型で(年月日時分秒を)返却する。
年
は2000
〜2099
範囲で、曜日情報は含まない。
有効範囲外の時刻では曜日が正しくならない。
現在時刻をbcddatetime_t
型で(年月日時分秒を)返却する。
年
は1900
〜2299
範囲で、曜日情報は含まない。
グレゴリウス暦は 400年周期で循環しているため、範囲外の指定は結果的に丸められる。
現在時刻が保持している曜日を返す。範囲は0:日(Sun)
〜6:土(Sat)
である。
年の精度が2桁の場合、 保持している年月日を21世紀と見做して曜日を算出し、それと異なるなら 保持している年月日は21世紀ではないと判定できる。 グレゴリウス暦でのその曜日組み合わせは計4通りしか存在しないので、 それらを20〜23世紀の何れかであると見做すことができる。
他の3種はグレゴリウス暦に現れるはずがないので、結果は未知である。
time_t
型で現在時刻を設定する。実行は即時。成功すれば真。
現在時刻には正しい曜日が設定される。
設定可能なのは西暦
2000
〜2099
年範囲のあいだに限られる。
閏日のない年の 2月29日は、3月1日とみなされる。
bcddatetime_t
型で現在時刻を設定する。実行は即時。成功すれば真。
年
には1900
〜2299
範囲が指定でき、
現在時刻には正しい曜日が設定される。
グレゴリウス暦は 400年周期で循環しているため、範囲外の指定は結果的に丸められる。
閏日のない年の 2月29日は、3月1日とみなされる。
bcddate_t
型で年月日のみを現在時刻に設定する。実行は即時。成功すれば真。
年
には1900
〜2299
範囲が指定でき、
現在時刻には正しい曜日が設定される。
グレゴリウス暦は 400年周期で循環しているため、範囲外の指定は結果的に丸められる。
閏日のない年の 2月29日は、3月1日とみなされる。
bcdtime_t
型で時分秒のみを現在時刻に設定する。実行は即時。成功すれば真。
date_t
型の MJD(修正ユリウス通日)で年月日のみを現在時刻に設定する。実行は即時。成功すれば真。
年
には1900
〜2299
範囲が指定でき、
現在時刻には正しい曜日が設定される。
グレゴリウス暦は 400年周期で循環しているため、範囲外の指定は結果的に丸められる。
閏日のない年の 2月29日は、3月1日とみなされる。
adjustBcdDateTime
の別名。bcddatetime_t
型を渡す。
adjustEpoch
の別名。time_t
型を渡す。
アラームには週
日
時
分
秒
の5つの比較要素が有り、その論理和を取る。
複数の比較を有効にすると、その全てが真とならなければアラーム動作は発動しない。
アラーム動作自体は単発ストローブであり、発動フラグをクリアしなければ 次の比較条件を満たした時刻が訪れても、アラーム動作は発動しない。
アラーム発動中は割込端子が
LOW
に引かれたままとなるので、これをクリアしなければ他の割込もまた通知されない。
アラーム比較条件を格納する構造体定義。 ひとつの曜日と、5つの比較フラグを保持している。
XRTC_ALARM_SETTINGS | 型 | 説明 |
---|---|---|
.WEEKDAYS | 3bit | 曜日指定 0-7 |
.SECOND | bool | 真で秒比較有効 |
.MINUTE | bool | 真で分比較有効 |
.HOUR | bool | 真で時比較有効 |
.DAY | bool | 真で日比較有効 |
.WEEKDAY | bool | 真で曜日比較有効 |
アラームが発動したなら真を返す。 新たなアラームを設定するか、クリアするまで真に留まる。
これがクリアされなければ発動中のアラーム割込端子制御LOW
は取り下げられない。
アラーム割込が有効なら真を返す。
アラームの有効
/無効
を真
/偽
で設定する。実行は即時。成功すれば真。
アラームを有効化すると、アラーム割込もまた有効化される。
アラームを無効化すると、アラーム割込もまた無効化される。
現在発動中のアラームをクリアする。実行は即時。成功すれば真。 発動したアラームをクリアしても、アラーム割込は無効化されない。
アラーム比較条件を設定する。実行は遅延。メソッドチェーンを後続できる。
引数にはひとつのbcdtime_t
型の時分秒と、
一組のXRTC_ALARM_SETTINGS
構造体を与える。
現在のアラーム比較時分秒をbcdtime_t
型で返却する。
現在のアラーム比較設定をXRTC_ALARM_SETTINGS
型で返却する。
タイマー動作には周期動作と単発動作がある。 周期動作には更にふたつの組込固定長周期タイマーがある。
何れかのタイマーが発動したなら真を返す。
新たなタイマーを設定するか、クリアするまで真に留まる。
これがクリアされなければ単発動作で発動中のタイマー割込端子のLOW
制御は取り下げられない。
タイマー割込が有効なら真を返す。
任意タイマーが周期動作設定なら真を返す。 任意タイマーが単発動作設定なら偽を返す。
タイマー動作の有効
/無効
を真
/偽
で設定する。実行は遅延。メソッドチェーンが後続できる。
通常これは他のタイマー操作内で上書きされるため、使用する機会はない。
タイマー割込動作の有効
/無効
を真
/偽
で設定する。実行は遅延。メソッドチェーンが後続できる。
通常これは他のタイマー操作内で上書きされるため、使用する機会はない。
タイマー動作と割込を無効化する。実行は即時。成功すれば真。
現在のタイマー発動フラグはクリアされる。
activeTimer(false, false)
に同じ。
タイマー動作と割込の有効
/無効
を真
/偽
で設定する。実行は即時。成功すれば真。
現在のタイマー発動フラグはクリアされる。
activeTimer(void)
はactiveTimer(true)
に同じ。
activeTimer(false)
はactiveTimer(false, false)
に同じ。
タイマー動作とタイマー割込の個別の有効
/無効
を真
/偽
で設定する。実行は即時。成功すれば真。
現在のタイマー発動フラグはクリアされる。
activeTimer(false, false)
はdeactiveTime(void)
に同じ。
activeTimer(true, true)
はactiveTimer(void)
に同じ。
activeTimer(false, true)
は設定可能だが意味をなさない。
activeTimer(true, false)
はタイマー発動フラグ更新のみ許可され、割込端子は駆動しない。
タイマーが発動したか否かはisTimer
で調べることができる。
現在のタイマー発動フラグをクリアして割込端子制御を取り下げる。実行は即時。成功すれば真。
周期動作タイマーは有効である間、指定の周期長間隔で単発パルスストローブを繰り返す。 タイマー発動フラグは初回発動時に真となり、以後クリアされるまで真を維持する。
任意設定タイマーの他に60
秒および30
秒の固定長周期タイマーが別にあり、
任意動作の周期タイマーと同時に使用できる。
ただしタイマー発動フラグはひとつなので、どのタイマーが発動したかを知ることは出来ない。
組込60
秒周期タイマーが有効なら真。
組込30
秒周期タイマーが有効なら真。
組込60
秒周期長タイマーの有効
/無効
を真
/偽
で設定する。実行は遅延。メソッドチェーンが後続できる。
この組込周期タイマーは秒桁が00
の時に単発割込を発生させる。
組込60秒周期タイマーは、任意設定周期タイマーと同時に使用できる。
組込30
秒周期長タイマーの有効
/無効
を真
/偽
で設定する。実行は遅延。メソッドチェーンが後続できる。
この組込周期タイマーは秒桁が00
か30
の時に単発割込を発生させる。
従って組込60
秒周期長タイマーの効果は隠蔽される。
組込30
秒周期長タイマーは、任意設定周期タイマーと同時に使用できる。
任意設定周期長タイマーに、現時刻を起点とする周期長をt_seconds
で与えて有効化する。実行は即時。成功すれば真。
タイマー発動フラグはクリアされる。
指定可能な最低値は1
秒。
255
秒までは秒刻みで指定可能。
それ以上は60
秒刻みに丸められ、15300
秒までが指定できる。
0
を指定するとこのタイマー動作と割込は無効化される。
単発動作タイマー割込は、その発動中は割込端子をLOW
に引く。
それはclearTimerFlag
でクリアするまで取り下げられない。
activateTimer
を実行する際の詳細設定構造体。
通常これを使用する必要はない。
XRTC_TIMER_SETTINGS | 型 | 説明 |
---|---|---|
.Value | uint8_t | カウントダウン設定値0 〜255
|
.InterruptMode | bool | 真で周期動作、偽で単発動作 |
.InterruptEnable | bool | 真で割込端子制御許可 |
.Enable | bool | 真でタイマー動作有効 |
.ClockFrequency | 2bit | カウントダウン周波数を以下で指定 |
0 | 4.096kHz | |
1 | 64Hz | |
2 | 1Hz | |
3 | 1/60Hz |
任意設定タイマーの現在の詳細情報をXRTC_TIMER_SETTINGS
構造体に返却する。
任意設定タイマーに詳細かつ完全な動作設定をXRTC_TIMER_SETTINGS
で与える。実行は即時。成功すれば真。
タイマー発動フラグはクリアされる。
通常これを使用する必要はない。
任意設定単発動作タイマーに、現時刻を起点とするカウントダウン時間をt_seconds
で与えて有効化する。実行は即時。成功すれば真。
タイマー発動フラグはクリアされる。
指定可能な最低値は1
秒。
255
秒までは秒刻みで指定可能。
それ以上は60
秒刻みに丸められ、15300
秒までが指定できる。
0
を指定するとこのタイマー動作と割込は無効化される。
任意設定単発動作タイマーが発動するとタイマー発動フラグが真になり、
それがクリアされるまで割込端子もLOW
を維持する。
周波数出力端子(COT)は既定で 32.768kHz の矩形波(push-pull)を常時出力している。
この信号は "Duino" ボードのPIN_PF0
にジャンパー設定で入力することができ、
RTC
周辺機能に供給、または主制御クロックの自動校正、
あるいは直接的に主制御クロックとして使用することが出来る。
周波数出力端子(COT)の出力周波数を、以下のt_clockfreq
で指定する。実行は即時。成功すれば真。
t_clockfreq | 出力周波数 | 矩形波Duty比 | 計時停止時 |
---|---|---|---|
0 | 32.768kHz | 60:40〜40:60 | 不定 |
1 | 16.384kHz | 50:50 | 不定 |
2 | 8.192kHz | 50:50 | 不定 |
3 | 4.096kHz | 50:50 | LOW固定 |
4 | 2.048kHz | 50:50 | LOW固定 |
5 | 1.024kHz | 50:50 | LOW固定 |
6 | 1Hz | 50:50 | LOW固定 |
7 | 停止 | - | LOW固定 |
出力周波数は、1Hz出力を除いて精度校正の影響を受けない。
Twitter(X): @askn37
BlueSky Social: @multix.jp
GitHub: https://github.com/askn37/
Product: https://askn37.github.io/
Copyright (c) 2022,2023 askn (K.Sato) multix.jp
Released under the MIT license
https://opensource.org/licenses/mit-license.php
https://www.oshwa.org/
multix.jp/てくにかるむ(休眠中)
Multix Zinnia Product SDK [*AVR]
AVR.JP(日本語訳)
AVR-LIBC(日本語訳)