google-site-verification: google3bd66dd162ef54c7.html
fc2ブログ

Arduino UNO R4 のクロックを IOピンに出して周波数を測定

◆まえがき
前の記事で、CPUのレジスタの設定方法を理解した のでその使用例として、チップのクロックをIOピンに出す設定を行ってみます。

実はこれをやりたかったので、レジスタの操作方法を調べていました。

◆効果
クロックの信号をIOピンに出せば、周波数カウンタを使った周波数測定が可能になるので、その誤差を正確に測定することが可能となります。また、いろいろな信号源として使えるので便利だと思います。

◆CLKOUT信号
マニュアルを読むと、クロックを外に出す方法として CLKOUT信号が使えそうです。というか名前の通りです。下記はデーターシートの図8.1の一部です。

CLKOUTの回路図

セレクタでクロックソースを切り替え、分周器を通した信号を出力出来るようになっています。(赤丸部)

◆CKOCRレジスタ
上の回路図のセレクタと分周器の設定は CKOCRレジスタで行います。
CKOCRの設定

◆D11ピンへ出力
後は実際に CLKOUT を CPU のピンに出す方法を調べないといけません。データシートの IOポートの設定表を読むと、CLKOUT 信号は以下に示すように P109 のポートから出力可能です。さらに、このポートはボードの D11 ピンに接続されているので楽に測定出来そうです。

・CLKOUTを出せるポートはP109
CLKOUT
PSEL を 01001b に設定すれば CLKOUT が選択されて、ポートから出力されることが判ります。

なお、CLKOUT は P205 のポートからも出力可能で、このポートは CPUパッケージの23番ピンに接続されています。ただ残念なことに、ボードのIOピンには接続されていないので今回は使わないことにしました。もし D11ピンが使えない場合は何とかして線を引き出して P205 の方を使えば良いでしょう。

ここまで判れば後はプログラムを書いて確認です。

◆プログラム
// 20240214_UnoR4ClockOutTest
// D11ピン(P109)にCLKOUT信号を出す

char cbuff[10];  // 文字列操作バッファ

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println();
  Serial.println("Start !");

  // CKCORを設定(クロックソースと分周比を設定)
  R_SYSTEM->PRCR = 0xA501;           // レジスタプロテクト解除
  R_SYSTEM->CKOCR = 0;               // CKOCRの全ビットクリア
  R_SYSTEM->CKOCR_b.CKOSEL = 0b000;  // HOCO:000, MOCO:001, LOCO:010, MOSC:011, SOSC:100
  R_SYSTEM->CKOCR_b.CKODIV = 0b011;  // 1分周:000, 001, 010, 011, 100, 101, 110, 128分周:111
  R_SYSTEM->CKOCR_b.CKOEN = 1;       // クロックアウト許可
  R_SYSTEM->PRCR = 0xA500;           // レジスタを再プロテクト
  viewCKOCR();

  // D11ポートの設定(CKOUTが出力出来るように設定)
  R_PMISC->PWPR_b.B0WI = 0;                       // 書き込みプロテクトを、
  R_PMISC->PWPR_b.PFSWE = 1;                      // 外す
  R_PFS->PORT[1].PIN[9].PmnPFS = 0;               // 念のために設定をリセット
  R_PFS->PORT[1].PIN[9].PmnPFS_b.PDR = 1;         // D11(P109)を出力に設定
  R_PFS->PORT[1].PIN[9].PmnPFS_b.PSEL = 0b01001;  // CLKOUTを選択
  R_PFS->PORT[1].PIN[9].PmnPFS_b.PMR = 1;         // 周辺機能をON
  R_PMISC->PWPR_b.PFSWE = 0;                      // 書き込みプロテクトを、
  R_PMISC->PWPR_b.B0WI = 1;                       // 掛ける
  viewD11();                                      // ちゃんと設定出来たか確認
}

void loop() {
}

void viewCKOCR() {  // CKOCRの内容を出力
  sprintf(cbuff, "CKOCR     = 0x%02x", R_SYSTEM->CKOCR);
  Serial.println(cbuff);
}

void viewD11() {  // D11のポート設定を出力
  sprintf(cbuff, "D11(P109) = 0x%08lx", R_PFS->PORT[1].PIN[9].PmnPFS);
  Serial.println(cbuff);
}
HOCOを8分周で出力する設定になっています。変更したい時は、CKOSEL と CKODIV の設定値を変えてください。
レジスタの操作の前後にプロテクトを外す(設定する)操作が必要になります。詳しくはプログラムを参照ください。

・実行結果
シリアルモニタに下記のような表示が出ればうまく動いています。
シリアルモニタ
CKOCR と P109 のポートが正しく設定されていることが確認出来ます。

・周波数測定結果の例
32.768kHzの測定結果
ボードのD11ピンに出力される信号の周波数を測っている様子です。
LOCO を分周比=1で出力しているので本来なら32.768kHzになっていて欲しいですが、えらくズレています。値については事項でまた触れます。

◆周波数測定結果
下表はクロックソース毎の周波数の測定結果で、CLKOUTの項が測定結果です。

測定結果
MOSCを選択すると、出力が出なかったので空欄になっています。

分周比から計算した元の周波数の値(原発)も記載しています。それらの標準値は上から48MHz, 8MHz, 32.768kHzなのでその値に対する誤差を表の右に表示しています。(SOSCの標準値は判らなかったです)

HOCO周波数の誤差は-0.19%でそこそこ小さいですが、水晶オシレーターと比べると100倍くらい悪い値です。また、LOCOはRTCのクロックとして使われますが、こんなに誤差が大くては、時計としては使えないと思います。

◆まとめ
CPUのレジスタを操作して Arduino UNO R4 のクロックをボードのピンに出して、クロック周波数を測定してみました。

チップ内蔵のクロック源はCRオシレーターなので仕方無いのでしょうが、周波数の誤差が大きいので、正確な時間精度が必要な場合は注意が必要だと思います。安く作るために割り切ったのでしょうが、ここは水晶を使って欲しかったです。

ここまで Arduino UNO R4 をいじってきて、前回の記事のアナログ入力インピーダンスの問題などいろいろな不満点が目に付きます。ただ、チップのマニュアルを読むと、色んな機能や配慮が各所にあってなかなか良く出来ていると感じます。マニュアル読んでいると、なんだかこのチップが好きになっちゃいました。

非難されるのを覚悟で書くと、Arduino UNO R4 ボードのいろいろな性能上の不具合は、チップのせいでは無くボードとしてのまとめ方に問題がある気がします。

◆おまけ
CLKOUTで出力可能な周波数を計算してみました。

オシレーター別出力周波数(Typ.)
緑色部は出力可能な周波数の上限(16MHz)を超えているので使用不可です。
ブザーの音源として使うことを想定すると300〜3kHzの範囲になりますが、この範囲は黄色で示した設定が該当しています。これ、覚えておくと役に立つことがあるかも知れません。

◆追記(2024/2/18)
CLKOUTの周波数の上限は16MHzと書きましたが、実際にはもっと高い周波数でも出力可能でした。下記はHOCOを分周率1で出力した波形です。
HOCO 48MHz クロック
D11から出力した48MHzのクロック波形。
最近うちのオシロの調子が悪いので、使えるうちに写真撮っときます。430Ω→50Ω同軸→オシロ内50Ω終端で観察、テクトロ 2465B (アナログ,400MHz)

関連記事

コメントの投稿

管理者にだけ表示を許可する

試しましたが

UNO R4のクロックアウトの結果をお待ちしていました。ありがとうございます。
久々にルビジウムをカウンタにつないで、試しましたが・・・
純正UNOが、HOCO:0.004%,MOCO:-2.7%,LOCO:-0.78%,MOSCとSOSCは測定できず。
コアボード(互換機)が、HOCO:0.004%,MOCO:-3.1%,LOCO:-3.6%,MOSC:-0.0018%SOSCは測定できず。(8分周で4〜5MHz位のノイズ?は出てきます。)
純正UNOのLOCO誤差が少ないのは、色々いじっているためかもしれません。
外部クロック搭載の互換機で、なぜMOSCが計測できないのか、現在のところ分かりません。

CLKOUTの上限

コメントを投稿し終えて気づきました。
「コアボード」の外部クロックは16MHzでした。
CLKOUTの上限が16MHzなのでダメなのでしょうか?

パオさん,情報ありがとうございます

ルビジウムをお持ちなんですね、仲間です。

HOCOの周波数精度がすばらしく良いですね。それ以外のオシレーターの精度はうちのとあまり変わらない感じでしょうか。

このCPUのクロックはややこしくて、全貌を掴むのは大変というかまだよく理解していないです。

あと、記事にCLKOUTの上限が16MHzと書いたのは、マニュアルの48.3.13項のCLKOUTタイミングに端子出力サイクル62.5ns min. と記載されているからです。
実際にはもっと高い周波数でも出力可能で、HOCOを分周比1でそのまま、つまり48MHzでも出力されました。ただ、外部のピンを高速で駆動するのはいろいろ問題がありそうなので止めておいた方が良さそうではあります。

クロック切り替え

(我家のルビジウムは、校正などしていない野良ですが。)
メイン・クロックが測定できない件は、もう少し確認してみます。

ついでに、公開していただいたスケッチを参考にRTCのクロックを「RTC.cpp」を書き換えずに、RCR4のRCKSELレジスタを0にしてみましたが切り替わらないようです。データシートに電源投入時に一度だけと書かれているので、ダメなのでしょうか?

re:クロック切り替え

RTCの水晶化はややこしそうですね。
.cppに書いた手続きが実行されるのは、チップの電源が入ってからかなり後だと思うので、レジスタ操作でもRTCの外部水晶化は出来そうな気がしますがどうなんでしょう。
ただ、うちの基板に外部水晶を付けるのはかなり厄介なので、実験は難しいです。
カレンダー
03 | 2024/04 | 05
- 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 - - - -
プロフィール

ラジオペンチ

Author:ラジオペンチ
電子工作を中心としたブログです。たまに近所(東京都稲城市)の話題など。60過ぎて視力や器用さの衰えを感じつつ日々挑戦!
コメントを入れる時にメールアドレスの記入は不要です。なお、非公開コメントは受け付けていません。
記事の内容のご利用は読者の自己責任でお願いします。

記事が気に入ったらクリックを!
最新記事
カテゴリ
最新コメント
リンク
FC2カウンター
検索フォーム
月別アーカイブ
RSSリンクの表示
QRコード
QRコード