タイマとDMAを使って一定周期でのADCデータ取り込みを行ってみました.
マイコンを使ったアプリケーションを作る上で,一定周期でデータを取得し,それを処理したいという機会は結構あると思います.
今回は,研究を行う上でそこそこ正確な連続データが必要となったため試してみました.
はじめに
使用するボード: Nucleo-64 L476(STM32L476RGT6)
他は中華ボードしか持ってないのでこれがスタンダードです笑
CubeMX設定
では,CubeMXを設定します.
クロックは予め80MHzにしてあります.適宜設定して下さい.
1.ADC
今回はIN1のみを使用します.
パラメータは写真の感じで設定して下さい.
Continuous Conversionは
Disabledにして下さい
これを入れていると,HAL_ADC_Start_DMAをした瞬間ADCのクロックに従ってバッファを埋めてしまいます.(=タイマが関係無くなる)
あと重要なのはExternal Trigger
で,External Trigger Conversion Source
はTimer N Trigger Out event
にします.
L476ではTIM1,3,8,15あたりが利用可能ですが,利用頻度を考えると15あたりにしておくのが無難かなと思います.
External Trigger Conversion Edge
はrisingでいいです.
あとはいつも通りDMAを有効にします.
2.TIM
次はタイマです.
設定箇所はClock Source
とパラメータです.チャネルは何も設定しません.
今回は200uS毎にスキャンするため,
- Prescaler: 79 -> 1MHz
- Counter Period: 199 -> 200カウント=200uS
となっています.
auto-reload preload
も有効にします.
最後に,Trigger Event Selection TRGO
をUpdate Event
にします.
これでADCで使用されるようになります.
プログラム(main.c)
上の方
|
|
int main()内
|
|
__HAL_DMA_GET_COUNTERはDMAの残りバッファ数を返す関数らしいのですが,なぜか5~8ぐらいをずっとウロウロしていて0にならなかったのでやっつけの>10
にしてあります.
その雑さもあって取得したデータの後方数個は0になります.
あと連続動作は想定してないので,使用したい場合はADCのDMAContinousRequest
を有効にするといいんじゃないかと思います.
動作確認
ADALM2000で60Hz,3.2Vpp,オフセット1.6Vのsin波を出して,ADCで読んでみます.
一応正しそうな波形ですが,何か下が潰れてますね.ADCの仕様でしょうか
200uS*1000ポイント=0.2Sということで,5Hzのsin波を見てみました.
一周期取れているので200uSというのも正しそうです.
おわりに
中華のSTM32H750VBT6ボードを買ってみましたが,キャッシュとかDMAとかがF4/L4と比べものにならないほど複雑です….
そのかわり480MHzという圧倒的なスピードで動作するのですが. まるでパソコンだなぁ(?)
参考文献
https://qiita.com/amutou/items/b7e6ffc42d2ce2b7f260
https://jp7fkf.hatenablog.jp/entry/20200603/1591186190
日本語の情報があって助かりました…