JP7FKFの備忘録

ヒトは,忘れる生き物だから.

STM32マイコンでADCを使ってみる話

最近はPICよりかはSTM32を用いて電子な工作をしている. 基本的なペリフェラルとして,GPIO(論理出力/入力),ADC, PWM,Timer(割り込み),通信系(I2C,SPI,USART,I2S,CAN,USBなどなど)等がある.このうちでもセンシング等でよく利用されるのがADCであろう.秋月で簡単にチップが入手できるSTM32F042には,12bitというわりと分解能の高いADCが付いている.PICでは8bitや10bitが多い中,12bitもの分解能が得られるADCはありがたいものだ.

今回はこのSTM32のADCを利用する方法を簡単にまとめてみようと思う. 主に下記の記事を参考にさせていただいた.

STM32の少しややこしいところは,PICのようにチャネルを設定しADCをGOしてフラグが落ちるまで(ADC完了まで)待ち,データを取る.というシーケンスでチャネルを次々変えて変換すれば異なるチャンネルのADCができるというわけではないという点である.特に注意するべきがこの複数チャンネルのADCであり,これはDMAを使ってやるとかなり簡単に処理することができる.STM32でADCを利用するときはDMAの利用は必須と言えそうだ.

複数チャネルのADCについては,上記の記事でかなり詳細に紹介されているので,ここは自分が忘れない程度にざっくりと記載していく.参考にするのであれば上記の記事を参考にすることをお勧めする.

DMAを用いたADC

まずはSTM32CubeMXでペリフェラルの設定をする. ADCしたいピンをADCモードに設定する.GUIなので簡単である. f:id:jp7fkf:20180108234233p:plain:w500

さらにconfigurationタブから,ADCのconfigは下記のようにしておく.

  • Continuous Conversion Mode: Enable
  • DMA Continuous Requests: Enable
  • Overrun behaviour: Overrun data overwritten

f:id:jp7fkf:20180108233837p:plain:w500

さらにDMAのconfigをいじっておく.ADCからのDMAリクエストを追加して

  • Mode: Circular
  • Increment Address: Memory
  • Data width: half word

f:id:jp7fkf:20180108233855p:plain:w500
ここまでできたらCubeMXを用いた設定は終了なので,コードを生成する.

ここからはSW4STM32でコードを書いて行く. 追加するべきは,初期化や変数宣言をするあたりに下記のコードを追加するだけである.

enum{ ADC_BUFFER_LENGTH = 2 };
uint16_t g_ADCBuffer[ADC_BUFFER_LENGTH];

memset(g_ADCBuffer, 0, sizeof(g_ADCBuffer));
HAL_ADC_Start_DMA(&hadc, g_ADCBuffer, ADC_BUFFER_LENGTH);

これで,任意の場所でg_ADCBufferの中身をみてやれば各chのADC値が読み取れる.ch1とch2を使っているのであればg_ADCBuffer[0]にch1が,g_ADCBuffer[1]にch2のADC値が入っている.
ADCを複数チャネルで利用する場合であっても,チャネルの若番から順に配列に格納されていく.ch1とch3のみを有効化した場合でもg_ADCBuffer[0]にch1, g_ADCBuffer[1]にch3の結果が入る.

というわけで,これだけでDMAを使ってADC値を得ることができる.ADCするためにCPUを使う必要もないし,いい感じである.CPUのリソースを有効に使える感じがする.これからもSTM32の勉強を進めて色々なモノづくりを進めてみようと思う.

References