Nucleo F303K8 DACを試す w/STM32CubeIDE

# とにかく電圧を出してみる

```main.c
  /* USER CODE BEGIN 2 */

#define V2R5_12BIT 0xfff*2.5/3.3
#define V2R0_12BIT 0xfff*2.0/3.3
#define V1R5_12BIT 0xfff*1.5/3.3

  HAL_DAC_Init(&hdac1);

  // output DAC1_OUT1 to 2.5V

  HAL_DAC_SetValue(&hdac1, DAC1_CHANNEL_1, DAC_ALIGN_12B_R,
		  V2R5_12BIT);
  HAL_DAC_Start(&hdac1, DAC1_CHANNEL_1);

  // output DAC1_OUT2 to 2V

  HAL_DAC_SetValue(&hdac1, DAC1_CHANNEL_2, DAC_ALIGN_12B_R,
		  V2R0_12BIT);
  HAL_DAC_Start(&hdac1, DAC1_CHANNEL_2);

  // output DAC1_OUT2 to 1.5V

  HAL_DAC_Init(&hdac2);

  HAL_DAC_SetValue(&hdac2, DAC2_CHANNEL_1, DAC_ALIGN_12B_R,
		  V1R5_12BIT);
  HAL_DAC_Start(&hdac2, DAC2_CHANNEL_1);

  /* USER CODE END 2 */
```

関数は Auto Completion の機能を使って探り，`stm32f3xx_hal_dac.h` 等を参照しました。

Nucleoでは以下のピンで確認します。

```NUCLEO PIN OUT
PIN Arduino STM32
 7    A5     PA6 DAC2_OUT1 UnBuffer
 8    A2     PA5 DAC1_OUT2 UnBuffer
 9    A3     PA4 DAC1_OUT1
```

基準電圧は `RM0316` によると `VREF+` とのことです。第5ピン，LDOに接続されているので3.3Vです。

iocでは特に不思議なところはありませんでした。以下は DAC1 の例です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/a7492967-1d8e-869a-3205-eb618ae6705f.png)

12ビット右詰めで値を書くには，以下の方法も使えます。

```main.c
  HAL_DAC_Init(&hdac2);
  DAC2->DHR12R1 = 0x123; // write to DAC2 channel 1
  uint32_t d1 = DAC2->DOR1; // check the value
```

なぜかデバッガでDAC2のレジスターが読めません（設定のミス？）が，RM0316にアドレスが書いてあり，halで普通にアクセスできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/50757f1d-46ca-91a8-a484-51212ca90cff.png)

```stm32f303x8.h
#define DAC1_BASE             (APB1PERIPH_BASE + 0x00007400UL)
#define DAC2_BASE             (APB1PERIPH_BASE + 0x00009800UL)
```

# DMAで電圧を可変する

DMAで配列から値を取ってきてDACに出し，正弦波を出す，のような記事があります。（感謝！）

- https://qiita.com/nanase/items/90dd2131d912f6a51073

STM32CubeIDEを使って実現を試みます。DMAということは，いつDMAで値を取ってくる？ つまりTriggerの設定をします。TIM6にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/73c1018b-ccd2-29a6-b657-ea9cd7e42b41.png)

DMAセクションで add します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/0b159c65-5cd5-3603-e1f7-2c3903e9b412.png)

TIM6の設定をします。一番下はTIM6のCR2レジスタの設定のようですが，`Update Event`にすることでTIM6がリロードしたときにDACに更新情報が伝わるようです。ハマりポイントのようですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/b463d097-5ded-5c72-78b5-d6501bd210ab.png)

TIM6をスタートさせて，そのあとDACをDMA付きでスタートさせました。

```main.c
  /* USER CODE BEGIN 2 */

  HAL_TIM_Base_Start(&htim6);

  uint16_t dac_data[]={
		  0x8,
		  0x80,
		  0x800
  };

  HAL_DAC_Start_DMA(&hdac1, DAC1_CHANNEL_1, (uint32_t)&dac_data, sizeof(dac_data)/sizeof(uint16_t), DAC_ALIGN_12B_R);

  HAL_Delay(500);
  uint32_t d0=DAC1->DOR1;

  HAL_Delay(1000);
  uint32_t d1=DAC1->DOR1;

  HAL_Delay(1000);
  uint32_t d2=DAC1->DOR1;

  HAL_Delay(1000);
  uint32_t d3=DAC1->DOR1;

  HAL_Delay(1000);
  uint32_t d4=DAC1->DOR1;

  HAL_Delay(1000);
  uint32_t d5=DAC1->DOR1;

  /* USER CODE END 2 */
```

実行結果 最初はTIM6からトリガーがかからず，DACの値が0のままになっていますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/f0558ca1-3acb-52e8-b1a6-dd0f265c01d9.png)

成功のようです。循環バッファに変更してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/a7224823-cf92-0488-40c4-6d37fc5a9096.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/48ef90ee-131c-2f21-00ae-8f998a0f25e2.png)


# おしまい

RM0316 および DS9866 からポイントを箇条書きにしてみます。

- F303K8は12ビットDACチャンネル3個
- buffer OFF のとき，出力インピーダンス <= 15k max

上にも書きましたが Nucleo では USB を上に見て，右側に並んでいます。

```NUCLEO PIN OUT
PIN Arduino STM32
 7    A5     PA6 DAC2_OUT1 UnBuffer
 8    A2     PA5 DAC1_OUT2 UnBuffer
 9    A3     PA4 DAC1_OUT1
```