2020年8月10日月曜日

STM32でDCC/DDCを作る方向で (33) 周波数カウンタ

告知です.
コミケ99にて当社のDDC/DACを頒布いたします.
  日付   2021年12月31日(金) 東地区 テ-40b  東5ホール
  サークル名    bangflat
コミケにお越しの際はお立ち寄りいただけますとありがたいです.
商品紹介ページを作りました.
ーーーー

STM32でDDCを作ろう!(DCCじゃないらしいぞ)     INDEXページへ

feedbackがなかなかうまく動きません.そこでFsの源発振周波数(49.152MHz)とHOSTのSOF周期(8kHz)の偏差を検証したくなりました.

そのために絶対精度はさほど高性能を求めないけど有効数字6桁ぐらいで周波数測定したい.がっ、わたしは周波数カウンタを持ってません.てなわけでSTM32F205で作りました.回路図はこちらに置いときます.(PCB写真とは一致してません)

【仕様】
8kHzを6桁ぐらいの精度で測るのなら60秒ぐらい積算カウントせにゃいかんので、カウントインターバルは0.1秒~最大60秒まで可変にします.インターバル時間の変更にはロータリエンコーダを使います.

測定結果をUARTへ出力しFT232を介してPC USB portへ送りterminalに表示させます.

【構成】
TIM2が主役です.測定信号をTIM2の外部clock(PA5)に加えます.
TIM3で0.1~60秒のインターバルを発生させ、TIM2の32bitカウンタ値をインターバル毎にFFにコピーします.tim2cntをごちゃっと計算すれば周波数が求まる.
STM32F205のTIM2の内部clockは60MHz maxです.TIM2は外部clockを内部clockでsampleするようなので、素の状態では外部clockの最高周波数は30MHzと思っとくのが無難です.しかし50MHzぐらいまで測りたいので外部clockをプリスケーラで2分周します.これで測定周波数レンジは60MHzまで対応できます.

周波数はこの式で求められます.
周波数 Hz = tim2cnt * 2 ÷ interval秒

【STM32CubeMXの設定】
やりたいことは上の通りで、文字表現では単純ですけれど、タイマの設定はかったるいです.STM32CubeMXを活用しましょう.というかMXが無かったらやる気が起きない.

clockの設定.
TIM2はAPB1に接続されているのでAPB1 Timer clocksが該当するのでしょうから、最高の60MHzにしときます.clock tree全体はこちらで見れます.

TIM2の設定.
Trigger Source ITR2にすると、TIM3の出力が内部でTIM2トリガへ接続されます.
Clock Source ETR2にすると、外部port PA5がclock入力になります.
Channel1 ..... by TRCにすると、TIM3にトリガされてCNT→FFにコピってくれる.

気にするところは、Counter preload 0xFFFFFFFF、auto-reload preload ENABLE の2か所かな.TIM2割り込みは使いませんでした.

TIM3の設定.
測定インターバル時間を決定します.PWMでパルスを発生させます.

下記の分周比設定ですと、60MHz ÷ 100 ÷ 60000 = 10Hz、すなわち測定インターバルは0.1秒になります.
測定インターバルパルスを生成するため、Master/Slave mode Enable、Trigger Event Selection Update Event にセットします.
tim2cntを採取する処理はTIM3割り込みでやりますので、割り込みをオンにしときます.

TIM1の設定.
基板上のロータリエンコーダはTIM1に接続してあります.(PA8,PA9)
TIM1をロータリエンコーダの受信回路として使うための設定が要ります.
Combined Channels Encoder Modeがそれです.

その他の設定としては、Counter Period 30000、Encoder Mode TI1 and TI2 ぐらい.なおTIM1割り込みは使いませんでした.PA8,PA9のGPIO設定をPULL-UPにするのをお忘れなく.

pin out


【プログラム】
ほとんどはMXが生成してくれます.
自分で書き足したところは、TIM3割り込みと、main()と、そこからcallされるお手製routineです.

TIM3割り込みでは、測定した周波数を表示しています.
TIM3割り込みは、stm32f2xx_it.c の TIM3_IRQHandler() にある.

ロータリエンコーダの処理は、main()のwhile loopでやっています.ロータリエンコーダが操作されたら、インターバル時間を変更しています.

こちらにproject folderを置きましたので、STM32CubeIDEで開けるはずです.
間違っていても責任持たないので素直にお死にください.


【周波数測定】
さて本題です.周波数を測定してみるなり.....

まずは、DACを駆動するFs源発振のXTALから.1024Fs=49.152MHzが公称値です.
測定結果は、49145719.5 Hzぐらいでした.偏差-128ppm

次に、HOSTが発生するSOF周期です.公称値は8kHzです.
測定結果は、7999.15Hzぐらいでした.偏差-106ppm

どちらも-100ppmぐらいなので、この偏差はSTM32基板のせいという可能性が大でしょう.校正手段がないのでとりあえず放置するしかありません.

いずれにせよ、DACとHOSTの間には20ppmぐらいの周波数偏差しかないことが証明されました.想像してたよりも優秀です.これならfeedbackをオフしていてもbuffer over flowの頻度はとても少ないと予想され、現状とは大きく乖離しています.feedbackの研究はまだ続きます.

かしこ

0 件のコメント:

コメントを投稿