2019年4月2日火曜日

STM32: 内蔵DACをDMA経由で使う(Nucleo-F446RE)

内蔵DACをDMA経由で使ってみました。データをあらかじめ用意できれば、DMAにデータ転送をまかせて、CPUは他の処理が行えます。

参考
「Elastic Notes」さんの「Usage DMA and DAC in STM32CubeMX

プロジェクト
https://github.com/ryood/STM32Cube_Test/tree/master/SW4STM32/Nucleo-F446_DAC_DMA_Test2

実行環境

  • Nucleo-F446RE
  • STM32CubeMX Version 5.1.0
  • System Workbench for STM32 - C/C++ Embedded Development Tools for MCU Version: 2.8.1.201903050911

4096サンプルのサイン波テーブルを作成して内蔵DACから出力します。

STM32CubeMXの設定


Clock Configuration
  PLL Source Mux: HSE
  HCLK: 180MHz

Pinout & Configuration
  Timers
    TIM6
      Mode: Activatedをチェック
      Counter Period: 220
      Trigger Event Selection: Update Event

180MHz駆動するとAPB1 Timer clocksは90MHzになります。4096サンプルで1波形のサイン波を出力するので、1kHzのサイン波を出力しようとすると
90MHz / prescaler / 4096 = 1kHz
なので
prescaler = 90MHz / (1kHz * 4096) ≒ 22.0
ですが、prescalerを22に設定するとDACから信号が出力されませんでした。100Hzにしようとprescalerを220に設定するとOKでした。

  Analog
    DAC
      Mode: OUT1 Configurationをチェック
      Prameter Settings
        Trigger: Timer 6 Trigger Out event
      NVIC Settings
        Enableをチェック
      DMA Settings
        DMA Request: DAC1を追加
        Mode: Circular
        Increment Address: Memory
        Data Width: Half Word
     

 SW4STM32でコードを追加(一部抜粋)


/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <math.h>
/* USER CODE END Includes */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define SINE_TABLE_SIZE (4096)
/* USER CODE END PD */

/* USER CODE BEGIN PV */
uint16_t sine_wave_array[SINE_TABLE_SIZE];
/* USER CODE END PV */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
static void generateSineWave(void)
{
  for (int i = 0; i < SINE_TABLE_SIZE; i++) {
      float fv = ((float)i / SINE_TABLE_SIZE) * 2.0f - 1.0f;
      float phi = (float)M_PI * fv;
      sine_wave_array[i] = 4095 * ((sinf(phi) + 1.0f) / 2.0f);
  }
}
/* USER CODE END 0 */

  /* USER CODE BEGIN 2 */
  generateSineWave();
  HAL_TIM_Base_Start(&htim6);
  HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)sine_wave_array, SINE_TABLE_SIZE, DAC_ALIGN_12B_R);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

Memory→DACのデーター転送はTimer駆動(TIM6)のDMAにまかせているので、プログラム(while(1)ループ)では何もしていません。

出力波形

いつものように、サイン波形の最大振幅付近で若干クリップしています。

99.6Hzのサイン波になりました。水晶がクロック源なので少し誤差が大きいような・・・(@@?

Prescaler Prescler(丸め) 誤差
219.7265625 220 0.1244%

期待周期(ms) 実測周期(ms) 誤差
10 10.04 0.4000%

0 件のコメント:

コメントを投稿