STM HAL_ADC DMA

DMA(ダイレクトメモリアクセス)を体験するというのが趣旨。一番みられるADCで行う。他にもUARTに直接とか、SPIやI2Cに直接とかもできる。

File-New-STM32Projectを選択して新規のプロジェクトを生成


USBからテキストをPCに転送できるようにしたいので、
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の文字列を呼ぶ度に新しい値が格納されてくる。




コメント

このブログの人気の投稿

Attiny85とAQM0802A(LCD)のI2C接続

Attiny85 FuseRest

HS101 STM32の自作お手軽オシロスコープ