はじめに
こんにちは、槇原です。前回は基板の設計をしてきました。今回からはマイコンのペリフェラルについて書いていきます。今回はタイトルの通りSTM32マイコンでADCをする際に各チャンネルの変換を1つずつ行う方法について説明します。
やりたいこと
今回のマウスの壁センサでは125 ?sおきに4つある壁センサのうち1つのセンサの値を取得するという動きをさせます。高速でADCを行うことでマウス全体の制御周期(1 ms)より早くすべてのセンサの値を更新できるようにします。
マイコンのピンアサインは次の通りです。
| ピン | ADC |
|---|---|
| PA0 | ADC1_IN1 |
| PA1 | ADC1_IN2 |
| PA2 | ADC1_IN3 |
| PA3 | ADC1_IN4 |

CubeMXでの設定は次のとおりです。設定自体は1ch用の変換の設定をして、プログラム上でどのチャンネルの変換をするか切り替えます。
毎回ソフトウェアをトリガーでADCをするためEnable Regular ConversionsをEnable、External Trigger Conversion SourceをRegular Conversion launched by softwareに指定します。

プログラム
今回は毎周期ごとに、1ch分の通常のADCを行います。さらに毎回必要なチャンネルを切り替える必要があるため。HAL_ADC_ConfigChannel関数によって毎回チャンネルを指定します。
必要な設定項目はADC_ChannelConfTypeDefという構造体に必要な部分を設定します。特に今回はChannelを読みたいポートに合わせて指定します。
ChannelはマイコンのピンのADC_INxに対応します。ここではReadADCという関数を作りました。引数にチャンネルを取り、それに合わせて読み取るチャンネルを指定します。
uint16_t ReadADC(int ch){
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Rank = ADC_REGULAR_RANK_1;
?sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
switch(ch){
case 1:
sConfig.Channel = ADC_CHANNEL_1;
break;
case 2:
sConfig.Channel = ADC_CHANNEL_2;
break;
case 3:
sConfig.Channel = ADC_CHANNEL_3;
break;
case 4:
sConfig.Channel = ADC_CHANNEL_4;
break;
}
if(HAL_ADC_ConfigChannel(&hadc1, &sConfig) !=HAL_OK){
Error_Handler();
}
if(HAL_ADC_Start(&hadc1) == HAL_OK){
if (HAL_ADC_PollForEvent(&hadc1,ADC_EOSMP_EVENT, 200) == HAL_OK){
uint16_t data=HAL_ADC_GetValue(&hadc1);
return data;
}
}
return -1;
}
壁センサの値を取得するためには発光側のLEDを光らせて一定時間待機してからADCを行います。
これを125 ?sおきに呼び出すポートを変えてセンサ値を取得します。割り込み中にADCを行うため、for文で一定時間待機させます。
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_SET); for(int i=0;i<loop_num;i++); right_adc_value= ReadADC(2); HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET);
ここまで書いてしまったのですが、これを作成してからRankを付けておけばひとつずつ呼び出すだけで順番にADCしてくれるらしいという話を聞きました。次からはこちらを使おうと思います…
参考
次回はFlashの書き込みについて書いていきます。
