STM HAL_ADC DMA
DMA(ダイレクトメモリアクセス)を体験するというのが趣旨。一番みられるADCで行う。他にもUARTに直接とか、SPIやI2Cに直接とかもできる。
File-New-STM32Projectを選択して新規のプロジェクトを生成
ConectivityのUSBをクリック□Device(FS)にチェックをいれる。
Categoriesの下のMiddlewareの所に”USB_DEVICE"が反転し選択
Class For FS IPが現れてDisableになっているが、選択できるようになる。Communication Device Class(Virtual Port Com)を選択する。
続いてCategoriesのAnalogを展開して、ADC1をクリック。ADC1 mode and configrationが開くので、ここでは、IN0~IN3の4つにチェックを入れる。その後、Parameter settingのScan Continuous ModeをEnableに。 Scan Conversion ModeもEnableになっているか確認する。
Mode:ADC1と2を両方使う場合同期させるか、独立にするか?
Data Alignment:データを右詰?左詰?を選択
Scan Conversion Mode:複数のチャンネルを次々と測定するか、しないかの指定
Continuous Conversion Mode/Discontinuous Conversion Mode
ADCの完了後に次々と繰り返す/繰り返さない
Number of Conversion:変換するチャンネルの数 ここでは4。
External Trigger Conversion Source:トリガの指定。ソフトウェアからトリガをあげるか、タイマーをトリガーにすることもできる。
Sampling Time:ADCのコンデンサがチャージしている時間。アナログ的な平均化が可能?と信じて長いものを設定している。
DMA settingsのタブを開いて、バッファの末端を超えると先頭からデータを格納する循環バッファを形成するためCircularを選択し、Memoryにチェックをいれる。
クロックの調整をする。ここはADCの単チャンネルの時にも行ったとおり。
/* USER CODE BEGIN PV */
uint16_t ADC_buff[4];
float adc_voltage[4];
uint8_t cdc_TX_Buffer[64];
/* USER CODE END PV */
ADC_buffはADCの結果を格納する配列、adc_voltageは電圧に換算した値を格納する配列、cdc_TX_BufferはUSB経由で結果を排出する時のUSBへ送る文字列の配列を定義 //ADC setting
while(HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK); // calibrate AD convertor
if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC_buff, 1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE END 2 */
HAL_ADCEx_Calibration_Start:STM32にはキャリブレーションする機能があり、これをまず最初に実行する。実行しないでも値は読めるが、小さな値だと正しく読めない。
HAL_ADC_Start_DMA
第一引数はハンドル、第二引数は、格納する文字列をポインタで、最後はどれだけのチャンネル数か?4チャンネル読み込むので4を入れている。
ここでスタートさせてしまうので、whileの外でOK。
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
for (int i=0;i<4;i++){
adc_voltage[i]=ADC_buff[i]/4095.0*3.3;
sprintf(cdc_TX_Buffer, "ch%d=%d\n\r",i+1,ADC_buff[i]);
while(CDC_Transmit_FS((uint8_t*)cdc_TX_Buffer, strlen((char*)cdc_TX_Buffer)) == USBD_OK) {}
HAL_Delay(1);
}
HAL_Delay(240);
}
/* USER CODE END 3 */
}
メインのループではDMAされているので、ADC_buffの文字列を呼ぶ度に新しい値が格納されてくる。
コメント
コメントを投稿