cancel
Showing results for 
Search instead for 
Did you mean: 

DAC output interfacing with the MCP601 Op Amp on the STM32H563ZIT6 for the speaker

Berlin-raj123
Associate III

Hi, I am using the STM32H563ZIT6 microcontroller and trying to interface it with an internal DAC to a speaker through an external MCP601 op-amp. I am generating a sine wave on that DAC pin, but it is producing some noise in the speaker. I am unsure how to properly generate sound with the speaker using the hardware setup shown in my connection diagram. Can anyone please advise me on how to generate sound on the speaker using the hardware setup below?

 

Note: Small correction: We are using 5V for the speaker; the remaining setup is unchanged.op_amp.png

8 REPLIES 8
LCE
Principal

Looks dangerous, without any resistors in there...

Anyway, can you see the DAC signal at the opamp input?

thank you for your reply!!

internal DAC output wavesinternal DAC output wavesOP-AMP OUTPUT SIGNALOP-AMP OUTPUT SIGNALSpeaker input signalSpeaker input signal

And also attached is my code for your reference! Are there any changes needed for our circuit?

#include "main.h"
#include <math.h>
DAC_HandleTypeDef hdac1;
DMA_NodeTypeDef Node_GPDMA1_Channel3;
DMA_QListTypeDef List_GPDMA1_Channel3;
DMA_HandleTypeDef handle_GPDMA1_Channel3;

TIM_HandleTypeDef htim1;

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_GPDMA1_Init(void);
static void MX_ICACHE_Init(void);
static void MX_DAC1_Init(void);
static void MX_TIM1_Init(void);
#define NUM_SINE_SAMPLES 100
#define AMPLITUDE 127
#define OFFSET 128

uint8_t sine_wave[NUM_SINE_SAMPLES];

//const uint8_t aEscalator8bit[6] = {0x0, 0x33, 0x66, 0x99, 0xCC, 0xFF;
void generate_sine_wave(uint8_t *table, int num_samples, int amplitude, int offset)
{
    for (int i = 0; i < num_samples; i++)
    {
        table[i] = (uint8_t)(offset + amplitude * sinf(2.0f * M_PI * i / num_samples));
    }
}

// Function to initialize the sine wave table
void init_sine_wave(void)
{
    generate_sine_wave(sine_wave, NUM_SINE_SAMPLES, AMPLITUDE, OFFSET);
}
const uint8_t aEscalator8bit[6] = {0x0, 0x33, 0x66, 0x99, 0xCC, 0xFF};
//const uint16_t aEscalator8bit[6] = {0x0, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff};
int main(void)
{
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* Configure the system clock */
  SystemClock_Config();
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_GPDMA1_Init();
  MX_ICACHE_Init();
  MX_DAC1_Init();
  MX_TIM1_Init();
  HAL_TIM_Base_Start(&htim1);
  init_sine_wave();

  // Start the DAC in DMA mode
  if (HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_2, (uint32_t*)sine_wave, NUM_SINE_SAMPLES, DAC_ALIGN_8B_R) != HAL_OK)
  {
       Error_Handler();
  }
   // Start the Timer
   if (HAL_TIM_Base_Start(&htim1) != HAL_OK)
   {
        Error_Handler();
   }
   while (1)
   {
   }
   /* USER CODE END 3 */
 }
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);

  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV2;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_PCLK3;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
}
static void MX_DAC1_Init(void)
{

  /* USER CODE BEGIN DAC1_Init 0 */

  /* USER CODE END DAC1_Init 0 */

  DAC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN DAC1_Init 1 */

  /* USER CODE END DAC1_Init 1 */

  /** DAC Initialization
  */
  hdac1.Instance = DAC1;
  if (HAL_DAC_Init(&hdac1) != HAL_OK)
  {
    Error_Handler();
  }

  /** DAC channel OUT2 config
  */
  sConfig.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_ABOVE_80MHZ;
  sConfig.DAC_DMADoubleDataMode = DISABLE;
  sConfig.DAC_SignedFormat = DISABLE;
  sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
  sConfig.DAC_Trigger = DAC_TRIGGER_T1_TRGO;
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_EXTERNAL;
  sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
  if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN DAC1_Init 2 */

  /* USER CODE END DAC1_Init 2 */

}
static void MX_GPDMA1_Init(void)
{

  /* USER CODE BEGIN GPDMA1_Init 0 */

  /* USER CODE END GPDMA1_Init 0 */

  /* Peripheral clock enable */
  __HAL_RCC_GPDMA1_CLK_ENABLE();

  /* GPDMA1 interrupt Init */
    HAL_NVIC_SetPriority(GPDMA1_Channel3_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(GPDMA1_Channel3_IRQn);

 }
static void MX_ICACHE_Init(void)
{


  if (HAL_ICACHE_Enable() != HAL_OK)
  {
    Error_Handler();
  }

}
static void MX_TIM1_Init(void)
{

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 32-1;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 99;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }

}

static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}
LCE
Principal

No need to look at the code, this is an analog problem.
I never used this analog push/pull output with such a low voltage and single supply.

The only thing you should change in the code as a start:

reduce the sine / DAC's output level, so that the sine wave is somewhere between 1V .. 2V.

You cannot expect all levels to be clean between 0 and VCC, especially with "power" output, which it is, driving an 8 Ohm speaker.

I usually put some resistors before the transistors' base.

But I still think that the low voltage and low impedance are the biggest problems here.

LCE
Principal

I forgot: a good example to use some PSPICE / simulation in advance.

AScha.3
Chief III

You should use an amp, thats working at low voltage, like : TDA1308 , or TA8227P , etc.

Here add a 100 r resistor and a little gain+offset , + opamp at 5V ,  to get some signal :

 

AScha3_0-1719560065451.png

But dont expect wonders... :)

If you feel a post has answered your question, please click "Accept as Solution".
Peter BENSCH
ST Employee

Some addition to what @LCE and @AScha.3 said:

With your schematics, it doesn't matter whether you supply the transistors with 5V or 50V - it's a voltage follower whose gain is only theoretically 1, but whose output voltage corresponds to the maximum input voltage, reduced by the two base-emitter voltages. At full level at the input with 3.3V you will therefore only get a maximum peak voltage of 3.3V-1.3V=2V, which corresponds to 0.71V rms voltage - which even at 4ohms only produces a quiet whisper.

I would also suggest using an integrated amplifier instead of such discrete contortions, e.g. the TS4890 or TS4990, both of which can work with both 3.3V and 5V.

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Few notes:
MCP601 input common mode range is VDD-1.2V. That means you should input only voltages up to 2.1V from DAC.

Second scope trace (OP-AMP OUTPUT SIGNAL) should be measured with DC coupling - something smells there, because you measured about 3.6Vpp at 3.3V powered opamp output... 

Find some amplifier IC, or try AScha.3 schematic or search for more serious amplifier circuit.