STM32三昧(6) Cube IDE、TIMER6+DACで三角波生成、Nucleo

Joseph Halfmoon

STMicroelectronics社純正開発環境Cube IDEを使用し、STM32のHAL(ハードウエア抽象化レイヤ)を試用中です。前回はTIMER6の割り込みを使ってみました。今回はDAC(デジタル・アナログ・コンバータ)が搭載する「ジェネレータ」機能をTIMER6でトリガしてDACから3角波を出力してみます。

※Windows 11 PC上にインストールしたSTM32CubeIDE Version: 1.13.2上で動作を確認しています。今回のターゲットボードは Nucleo-F072RBです。

DAC内蔵のジェネレータ

DAコンバータといえば、所定のデジタル値をアナログ変換して出力するもの。「アナログ波形」を出力する場合、ソフトでタイミングをとってデジタル値を次々と与えるか、あるいはメモリ上に配置したデータ表をDMAを使ってDACへ流し込むのが普通だと思います。しかし、STM32のDACがちょっとユニークなのは、以下のジェネレータ機能をDAC側に内蔵していることです。

    1. ホワイトノイズジェネレータ
    2. 三角波ジェネレータ

1のホワイトノイズジェネレータは、LFSR(リニア・フィードバック・シフト・レジスタ)を使った乱数のようなので「疑似」的なものですが、シビアな用途でなければノイズ源としては十分な気がしないでもないっす。

今回は2の三角波ジェネレータを使用してみます。

なお、ST社の以下のアプリケーションノートを参照させていただいております。

AN3126 Audio and waveform generation using the DAC in STM32 products

三角波ジェネレータ時の設定

DAC内蔵の三角波ジェネレータを使用する場合、振幅、オフセット、周期というパラメータは以下のように与える必要があります。

    • 振幅、DACのAMPx[3:0]ビットの設定による
    • オフセット、HAL_DAC_SetValue()で設定できる
    • 周期、タイマのトリガと振幅設定による

振幅(ピークツーピークなので注意)は、Vref=3.3V時に0.0008V~3.2992Vまで12段階に設定可能です。オフセット(信号下限値なので注意)はもともとのDACの出力設定値(12ビット)で操作可能。よって振幅の設定と「信号がDACの出力可能範囲から溢れないように相談」しながらオフセットも調整可能です。

周期はタイマからのトリガ信号を基準としているのですが「振幅」と密につながっていることがちょっとメンドイ。振幅のために設定した値まで、トリガ信号によりインクリメント、値に達するとデクリメントすることで3角波を作り出しているみたいです。よってタイマからの「トリガ周期*振幅設定値*2」が三角波の周期となるみたい。

DACの設定を行う前に、DAC出力ピンを設定しておかないとなりません。Pin設定画面からPA4をDAC_OUT1に設定しました。

DAC_pinout

さて本題のDAC設定は以下のようにしてみました。Timer 6からトリガを貰い、3角波を生成せよ、その際の振幅は設定値127(電圧値で0.1023V。)

DAC_PARAM

 

TIMER6の設定

上記のDAC内蔵のジェネレータにトリガを与えるためにTIMER6は以下のように設定してみました。カウンタは48(クロックは48MHz設定なので1MHzでトリガできるハズ。)

TIM6_PARAM

トリガ周期*振幅設定値*2という計算だと、約3.9kHz周期の三角波が得られる期待。

実験に使用したソース

自動生成のソースに書き加えた部分のみ抜き出しました。Cube IDEのお作法により、自動生成されたソース内の「User書き変え可」部分を示すコメント付きです。BEGINとENDの間に書くのがお作法。書き変えたのは main.c のみです。

/* USER CODE BEGIN 2 */
HAL_DAC_Start(&hdac, DAC_CHANNEL_1);
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 128);
HAL_TIM_Base_Start_IT(&htim6);
/* USER CODE END 2 */

上記でDACとTIMER6をスタートさせてます。今回の実体は上記のみ。

以下は、Armコアが走っていることを表すためのLチカ部分です。DAC出力とは無関係。

  /* USER CODE BEGIN 3 */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
  HAL_Delay(200);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
  HAL_Delay(200);
}
/* USER CODE END 3 */
実機上での実行

上記オブジェクトを書き込んだ実機の様子が以下に。右下の方にコンデンサと抵抗が転がってますが、最初DAC出力(Arduino互換ピンソケットのA2端子)の先にLPF取り付けてみたためです。取り外しても波形ほとんど変わらないので取りました。TIM_DAC_DUT

観察された3角波の波形が以下に。ResultWOLPF

アプリケーションノートに書いてあるAmplitudeは、生成ロジック的にピークツーピーク値です。片側の「振幅」50mV期待のところ、上記では約45mV。アプリケーションノートのオフセットはこれまた生成ロジック的には「下限値」なので100mV期待が約70mVとな。そういえば測定系自体に数十mVくらいの誤差オフセットが載っているのに修正してなかった。。。ま、それを考えたらこんなもんかい。テキトーだな。

STM32三昧(5) Cube IDEでTIMER6割り込み、Nucleo へ戻る

STM32三昧(7) Cube IDE、TIMER6+DACで疑似ノイズ波生成、Nucleo へ進む