STM32 + LL でADCのレギュラ変換を動かしてみる
STM32マイコンのペリフェラル関連記事を一覧にまとめました。
センサの入力でよく使用するA/D変換の使い方を書いていきたいと思います。今回は、LLAPIを使用してレギュラ変換の1チャンネル変換のプログラムを書いていきたいと思います。
マイコンはSTM32F405RGTを使用していきます。
リファレンスマニュアルを読む
ADCのシングル変換のやり方の確認
今回はシングル変換を行っていきたいと考えています。プログラムの実装に必要になりそうな場所を、リファレンスマニュアルから一部抜粋で見ていきたいと思います。
ADCのシングル変換は、リファレンスマニュアルの流れ通り設定していけば良さそうだということが考えられれます。レギュラ変換で割り込みを行うことを考えていないため外部トリガ、割り込み生成、インジェクトチャンネルについての設定を考える必要はなさそうです。
タイミングチャートから読み取れることはEOCはソフトウェアでクリアする必要があること、SWSTARTは自動でオフになるということです。
レジスタの確認をする
ADCの設定や、EOCフラグの設定にはどのレジスタをいじってあげればいいのかが少しわかりました。この後のSTM32CubeMXや、生成してもらった初期化プログラムの確認に使用するため他のレジスタは各自で確認をお願いします。ここでは、プログラムの実装で使用するレジスタだけ取り上げました。
STM32CubeMXの設定
ADCの設定は次の通り行いました。
今回はADC2を使用してやっていきます。また、ADCの変換結果を見るためにUSART3の設定をしました。機能の設定は10bit,データは右詰め、その他の機能はすべてDisableで、変換のサイクルは15サイクルにしました。
Project ManagerでAdvanced Settingsで使用するAPIをLLに変更したり、プロジェクト名の設定をしたりした後にコードを生成してもらいましょう。
ソースコードを実装する
生成されたソースコードを確認して、実装する関数を考える
- ADCの機能を有効化する。
- ADCのシングル変換を行う。
実装する
実装したプログラムは以下の通りです。
void ADC2_Start(void)
{
LL_ADC_Enable(ADC2);
}
uint16_t ADC2_SingleConversion(void)
{
uint16_t data;
LL_ADC_REG_StartConversionSWStart(ADC2);
while(LL_ADC_IsActiveFlag_EOCS(ADC2) == 0);
LL_ADC_ClearFlag_EOCS(ADC2);
data = LL_ADC_REG_ReadConversionData10(ADC2);
return data;
}
ADCを有効化する関数では、CR2レジスタのADONビットたてることだけを行っています。
シングル変換を行い値を取得する関数ではCR2レジスタのSWSTARTのビットを立てて、SRレジスタのEOCビットが立つまで待った後にEOCビットをクリア、DRレジスタから値を取得の流れで実装をしました。
LL_ADC_IsActiveFlag_EOCS関数はSRレジスタのEOCビットを確認しるので、使用している関数はあっています。何をしているかどうかを知りたいときはLLライブラリの関数の定義を確認しましょう。
抵抗分圧で得られた電圧をADCでマイコンに入力して電圧に変換してみる
抵抗分圧の回路は次の通りです。
C1のコンデンサはつけてもつけなくてもOKです。抵抗の値は0~3.3Vの間に電圧が収まるように設定するようにしてください。
電圧に変換するプログラムは以下の通りです。
#define BATT_CONVERSION_CONST 0.0103125f //3.3f / 1024.0f * ( 2200.0f + 1000.0f ) / 1000.0f;
float getBatteryVoltage(void)
{
return (float)BATT_CONVERSION_CONST * ADC2_SingleConversion();
}
電圧の変換計算用に毎回抵抗分圧の計算することはリソースの無駄遣いだと考えたため、先に計算した値を定数として入れています。計算式については各自で理解できると思われますので省略します。
ADCのプログラムを動かす
main関数内に処理を追加していきます。
/* USER CODE BEGIN 2 */
ADC2_Start();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
printf("batt_monitor = %fr, getBatteryVoltage() );
/* USER CODE BEGIN 3 */
}
初期化処理内でADC2の機能を有効化したのちにprintfで電圧を確認するプログラムにしました。
USARTでprintfの設定は下のSTM32 + LL のUSARTでprintf(float)を実装するを参考にしていただければと思います。
おわりに
今回は、レギュラ変換の実装をしてみました。今回の電圧を変換するプログラムは、マイクロマウスやロボットなどの電圧監視で使われることが多いので参考になればと思い書いてみました。
次回はDMAを使用した複数チャンネルの実装を行っていきたいと思います。