STM32 正弦波可以工作,但音频文件会从 DAC 产生静电

发布于 2025-01-10 09:31:24 字数 2317 浏览 2 评论 0原文

我正在尝试使用 STM32F466RE 上的内部 DAC 播放简单的 WAV 文件。我有 DMA,按照 Timer4 设置的时间间隔写入 dac。使用正弦波,效果非常好:

正弦波示例(效果很好):

  const uint16_t sine_wave_array[32] = {2047, 1648, 1264, 910, 600,  345,
                     156, 39,  0,  39,  156,  345,
                     600, 910, 1264, 1648, 2048, 2447,
                     2831, 3185, 3495, 3750, 3939, 4056,
                     4095, 4056, 3939, 3750, 3495, 3185,
                     2831, 2447};




    HAL_DAC_Start(&hdac,DAC_CHANNEL_1);
    HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)sine_wave_array, 32, DAC_ALIGN_12B_R);
    HAL_TIM_Base_Start(&htim4);

  //timer config
  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 0;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 1136; // (16MHZ /(32 * 440hz))
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;



//DAC Setup from Stm32cubeIDE
static void MX_DAC_Init(void)
{

  /* USER CODE BEGIN DAC_Init 0 */

  /* USER CODE END DAC_Init 0 */

  DAC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN DAC_Init 1 */

  /* USER CODE END DAC_Init 1 */
  /** DAC Initialization
  */
  hdac.Instance = DAC;
  if (HAL_DAC_Init(&hdac) != HAL_OK)
  {
    Error_Handler();
  }
  /** DAC channel OUT1 config
  */
  sConfig.DAC_Trigger = DAC_TRIGGER_T4_TRGO;
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN DAC_Init 2 */

  /* USER CODE END DAC_Init 2 */

}

DAC 设置为使用 DMA 流 5。DMA 设置为半字(16 位)。 MCU 的频率为 16 MHz。一切听起来都不错。

所以现在我尝试用此处以 44.1khz 形式采样的音频文件(已删除标头)替换 sine_wave:hello.h

这是修改后的代码:

#include "helo.h"
//HELLO_LENGTH is 57890

    HAL_DAC_Start(&hdac,DAC_CHANNEL_1);
    HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)hello, HELLO_LENGTH, DAC_ALIGN_12B_R);
    HAL_TIM_Base_Start(&htim4);


 htim4.Init.Period = 362; // (16MHZ /44100)

我还将 DMA 缓冲区从半字更改为字节(8 位)。然而,我现在只听到扬声器发出静电声。但静电干扰有重复,几乎就像声音存在但全是乱码。

我还尝试使用自己的音频文件(删除了标题,仅删除了数据部分),但仍然得到同样的结果。

有什么想法吗?

I'm trying to play a simple WAV file using the internal DAC on the STM32F466RE. I have the DMA, writing to a dac by an interval set by Timer4. Using a Sine Wave, this works perfectly:

Sine Wav Example (This works fine):

  const uint16_t sine_wave_array[32] = {2047, 1648, 1264, 910, 600,  345,
                     156, 39,  0,  39,  156,  345,
                     600, 910, 1264, 1648, 2048, 2447,
                     2831, 3185, 3495, 3750, 3939, 4056,
                     4095, 4056, 3939, 3750, 3495, 3185,
                     2831, 2447};




    HAL_DAC_Start(&hdac,DAC_CHANNEL_1);
    HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)sine_wave_array, 32, DAC_ALIGN_12B_R);
    HAL_TIM_Base_Start(&htim4);

  //timer config
  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 0;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 1136; // (16MHZ /(32 * 440hz))
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;



//DAC Setup from Stm32cubeIDE
static void MX_DAC_Init(void)
{

  /* USER CODE BEGIN DAC_Init 0 */

  /* USER CODE END DAC_Init 0 */

  DAC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN DAC_Init 1 */

  /* USER CODE END DAC_Init 1 */
  /** DAC Initialization
  */
  hdac.Instance = DAC;
  if (HAL_DAC_Init(&hdac) != HAL_OK)
  {
    Error_Handler();
  }
  /** DAC channel OUT1 config
  */
  sConfig.DAC_Trigger = DAC_TRIGGER_T4_TRGO;
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN DAC_Init 2 */

  /* USER CODE END DAC_Init 2 */

}

The DAC is set to use DMA Stream 5. The DMA is set to half-word (16 bit). The MCU is at 16 MHZ. Everything sounds good.

So now I'm trying to replace that sine_wave with an audio file (headers removed) sampled at 44.1khz form here: hello.h

Here's the modified code:

#include "helo.h"
//HELLO_LENGTH is 57890

    HAL_DAC_Start(&hdac,DAC_CHANNEL_1);
    HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)hello, HELLO_LENGTH, DAC_ALIGN_12B_R);
    HAL_TIM_Base_Start(&htim4);


 htim4.Init.Period = 362; // (16MHZ /44100)

I also changed the DMA Buffer from Half-word to Byte (8 bit). However, I'm just hearing static now from the speaker. But the static has a repetition to it, almost like the sound is there but all garbled.

I also tried with my own audio file (with headers removed, only the data portion) and I still get the same thing.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

樱&纷飞 2025-01-17 09:31:24

尝试一次走一步!您大幅提高了数据速率,并同时更改了数据格式和来源。

首先以增加的速率尝试正弦波,并验证您是否获得了合理的输出。尝试不同频率的正弦波。从 1kHz 等低频开始,然后逐步提高。 44.1kHz采样率应该能够得到接近20kHz的信号。

每次在示波器上验证信号看起来是否正确。如果您没有示波器,请连接扬声器并使用手机上的频率监控应用程序收听音频(例如:这个),或者甚至可能是电子吉他调音器。

在连接扬声器之前,请考虑如何滤除直流偏置并放大信号。如果您不知道这意味着什么,那么您必须在电子堆栈交换上询问。

我预计您可能会发现您正在尝试以比 DAC 更快的速度运行采样率。内部 DAC 通常不用于音频,而且它们是非常非线性的。

一旦找到合适的采样率,就可以创建该格式的数据文件。请记住,对于 wav 文件 数据可以是无符号或有符号整数格式。如果它是有符号的,那么您需要通过添加偏差将其转换为无符号。还要考虑字节顺序。

Try to go one step at a time! You have massively ramped up the data rate, and changed the data format and source all at once.

First try the sine wave at the increased rate and verify that you get sensible output. Try different frequencies of sine wave. Start with a low frequency like 1kHz and work up. 44.1kHz sample rate should be able to get close to 20kHz signal.

Each time verify on the oscilloscope that the signal looks correct. If you don't have an oscilloscope then connect up a speaker and listen to the audio with a frequency monitoring app on your phone (eg: this one), or else maybe even an electronic guitar tuner.

Before you hook up a speaker think about how you will filter out the DC bias and amplify the signal. If you don't know what that means then you will have to ask on electronics stack exchange.

I expect that you may find that you are trying to run the sample rate faster that the DAC can go. Internal DACs are not usually meant for audio, also they are very non-linear.

Once you have found a sample rate that works then create a data file in that format. Remember that for wav files the data may be in unsigned or signed integer format. If it is signed then you need to convert to unsigned by adding a bias. Also think about endianness.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文