2021年3月19日金曜日

STM32CubeIDE: I2S DACのPCM5102Aを16bitで使う

PCM5102Aは表面実装パッケージですが、秋月からDIP化キットが販売されていてブレッドボードやユニバーサル基板でも実験しやすいDACです。

外付け回路が必要な電流出力ではなく電圧出力で、内蔵電源によりGNDを中心としたAC波形が得られます。また内蔵PLLによりマスタークロックなしの3線(BCK/DIN/LRCK)で使用可能です。

電源電圧が3.3Vで、絶対定格が-0.3V~3.9Vな点は十分注意する必要があります。私は実験中に間違えて5Vを掛けて壊してしまいました。ほんの数秒でアウトです。

秋月ではIC単体ではなくDIP化基板のみの販売です。近年TIがIC単体の販売を絞っているためでしょうか。どういう意図があるんでしょうね?


PCM5102Aは32bit/384kHzまで対応してますが16bitでも使えます。今回は16bit/48kHzで動作させてみます。

STM32CubeIDE: Version 1.5.1
Target board: Nucleo-F446RE

回路図

データシートに載っているTypical Applicationの回路から、出力にかかっているCR LPFを削除しています。SCKは使わずBCKを利用するためGNDに落としています。

配線図



実験のようす

3.3V電源はNucleoからも供給可能ですがPCM5102Aは結構電源にシビアなので、別の電源からとっています。今回は3.3Vのリニアレギュレータを使った電池電源を使用しています。

STM32のプログラムは「STM32CubeIDE: I2S DACのTDA1543を使う - サイン波を出力」のものと同じです。

MXの設定


System Core
  GPIO
    PC5: 
      GPIO mode: Output Push Pull
      User Label: CK_PERIOD
    PC6:
      GPIO mode: Output Push Pull
      User Label: CK_CPLT
    PC8:
      GPIO mode: Output Push Pull
      User Label: CK_HALF_CPLT
Multimedia
  I2S2
    Mode
      Mode: Half-Duplex Master
  Configuration
    Parameter Settings
      Generic Parameters
        Selected Audio Frequency: 48KHz
    DMA Settings
      SPI2_TX
        DMA Request Settings
          Mode: Circular
          Peripheral: Data Width: Half Word
          Memory   : Data Width: Half Word

main.cにコードを追加


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

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define PI_F	(3.1415926f)
/* USER CODE END PD */

/* USER CODE BEGIN PV */
uint32_t sampling_rate = 48000u;
float frequency = 1000.0f;
float phi = 0.0f;
float delta;
uint16_t tx_buffer[2] = { 0, 0 };
/* USER CODE END PV *

  /* USER CODE BEGIN 1 */
  delta = (2.0f * PI_F * frequency) / sampling_rate;
  /* USER CODE END 1 */

  /* USER CODE BEGIN 2 */
  HAL_I2S_Transmit_DMA(&hi2s2, tx_buffer, 2);
  /* USER CODE END 2 */

/* USER CODE BEGIN 4 */
void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{
	HAL_GPIO_WritePin(GPIOC, CK_HALF_CPLT_Pin, GPIO_PIN_SET);

	// Generate Sine wave
	float fv = sinf(phi);
	int16_t v = fv * 0x7fff;
	tx_buffer[0] = (uint16_t)v;

	HAL_GPIO_WritePin(GPIOC, CK_HALF_CPLT_Pin, GPIO_PIN_RESET);
}

void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
{
	HAL_GPIO_WritePin(GPIOC, CK_CPLT_Pin, GPIO_PIN_SET);

	// Generate Sawtooth wave
	float fv = phi / PI_F;
	int16_t v = fv * 0x7fff;
	tx_buffer[1] = (uint16_t)v;

	// Advance in phase
	phi += delta;
	if (phi > PI_F) {
		phi -= 2.0f * PI_F;
		HAL_GPIO_TogglePin(GPIOC, CK_PERIOD_Pin);
	}

	HAL_GPIO_WritePin(GPIOC, CK_CPLT_Pin, GPIO_PIN_RESET);
}
/* USER CODE END 4 */

出力波形を観測


C1:Lch C2:Rch

NOSのTDA1503の場合と比べるとオーバーサンプリングとデジタルフィルタが効いているため、同じ16bit/48kHzのデータでもサイン波にガタガタがほとんど見られません。

ノコギリ波もガタガタは無くなっていますが、上下のエッジに振動が見られます。内蔵のデジタル補間フィルタの特性ですね。

サイン波ではあまりわかりませんが、ノコギリ波だと過渡特性がよくわかります。

スペクトラム


Lch(サイン波) 500kHzレンジ

Lch(サイン波) 100kHzレンジ

48kHz動作ですが、TDA1543を192kHzで動作させた場合と比較して歪が少なくなっています。

Rch(ノコギリ波) 50kHzレンジ

Rch(ノコギリ波) 500kHzレンジ

ノコギリ波では25kHz付近で一旦高調波がカットされ、その後放物線状のカーブが現れ350kHz~400kHzでは帯状のピークが出ています。面白いですね。

PCM5102Aのハードウェア設定


PCM5102AのFLTピンとDEMPピンはH/Lさせることにより特性が変わります。

FLT: H

FLTピンをHレベルにすると補間フィルタがLow Latencyになります。ノコギリ波の波形がNormalとは異なります。

PCM5102Aのデータシートのインパルス応答を見るとNormalがFIR、Low LatencyがIIRっぽいです。IIRのほうがアナログフィルタに近い特性で次数が少なくて済むようですがどうなんでしょうね。

DEMP: H

DEMPピンをHレベルにするとDe-emphasisがONになります。この機能はよく知らないのですがレコードのRIAAのように録音時に高音を強め、再生時に高音を弱めるのでしょうか。ノコギリ波の出力波形を見るとLPFを通したような感じです。

0 件のコメント:

コメントを投稿