-1

我是嵌入式编程的新手,我目前正在使用 STM32F469I 发现板进行项目。我将 Eclipse 与 ARM 工具链和提供的驱动程序一起使用。我无法播放在特定地址闪入芯片的二进制音频文件。我非常简单地将我的代码基于一些示例文件,尽管因为我只是想让它工作而减少了很多。

目前,代码一直运行到播放缓冲区的位置,但随后似乎卡住了。缓冲区正在循环播放(我已更改缓冲区的大小以确认这一点),您可以听到它,但这就是发生的一切。传输中断回调永远不会执行,因此缓冲区不会重新填充,并且永远不会播放完整的样本。

我试过使用外部中断来重新填充缓冲区,但是当我尝试这个时,它卡住了。我也尝试通过打开 LED 来调试它,但这已经证实它在播放样本后不久就卡住了。无限while循环永远不会执行,传输中断永远不会执行。

我的问题是 - 为什么它会卡住,为什么没有触发中断?

任何帮助将不胜感激!

#include "main.h"

static void SystemClock_Config(void);

#define AUDIO_FILE_ADDRESS   0x08010000
#define AUDIO_FILE_SIZE      (180*1024)
#define PLAY_HEADER          0x2C
#define PBSIZE               4096
uint16_t                      PlayBuff[PBSIZE];

int OFFSET = 0;
int TransferState = 0;
int CycleCount1 = 1;
int CycleCount2 = 1;

int main(void)
{
  uint32_t PlaybackPosition   = PBSIZE + PLAY_HEADER;
  HAL_Init();
  /* Configure the system clock to 180 MHz */
  SystemClock_Config();
  // Fill the buffer first time round
   for(int i=0; i <= PBSIZE; i++)
     {
       PlayBuff[i]=*((__IO uint16_t *)(AUDIO_FILE_ADDRESS + PLAY_HEADER + i));
     }
   BSP_AUDIO_OUT_Init(2,50,AUDIO_FREQUENCY_16K );
   BSP_AUDIO_OUT_Play(PlayBuff,PBSIZE);

   while(1){
       if(TransferState==1){
           // refill the first part of the buffer
           TransferState=0;
           OFFSET = CycleCount1*PBSIZE;
           for(int i=0; i <= PBSIZE/2; i++){
                  PlayBuff[i]=*((__IO uint16_t *)(AUDIO_FILE_ADDRESS + PLAY_HEADER + OFFSET));
                }
           CycleCount1++;

       }
       if(TransferState==2){
           // refill the second part of the buffer
           OFFSET = CycleCount2*PBSIZE+PBSIZE;
           TransferState=0;
           for(int i=PBSIZE/2; i <= PBSIZE; i++){
                 PlayBuff[i]=*((__IO uint16_t *)(AUDIO_FILE_ADDRESS + PLAY_HEADER + OFFSET));
                }
           CycleCount2++;

       }
    }
}

void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
{
  TransferState=2;
}

void BSP_AUDIO_OUT_HalfTransfer_CallBack(void){
  TransferState=1;
}

为了确定问题的原因,我进一步精简了代码,以便它所做的只是播放缓冲区。我已删除中断调用以尝试确定导致问题的原因。

它应该做的是配置系统时钟,填充缓冲区,初始化音频,然后打开 LED。然后它应该播放音频缓冲区,等待 1 秒,然后关闭 LED。它循环播放缓冲区(因为它应该在循环模式下)但随后卡住并且从不关闭 LED。我试过在正常模式下运行它,但它只是播放一次缓冲区,然后就卡住了。

这让我认为我错误地配置/填充了缓冲区。

#include "main.h"

static void SystemClock_Config(void);

#define AUDIO_FILE_ADDRESS   0x08010000
#define PLAY_HEADER          0x17569
#define PBSIZE               4096
uint16_t                     PlayBuff[PBSIZE];

int main(void)
{
  BSP_LED_Init(LED1);
  HAL_Init();
  /* Configure the system clock to 180 MHz */
  SystemClock_Config();
  // Fill the buffer first time round
   for(int i=0; i <= PBSIZE; i++)
     {
       PlayBuff[i]=*((__IO uint16_t *)(AUDIO_FILE_ADDRESS + PLAY_HEADER + i));
     }
   BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_HEADPHONE ,50,AUDIO_FREQUENCY_44K );

   BSP_LED_On(LED1);

   BSP_AUDIO_OUT_Play(PlayBuff,PBSIZE);

   HAL_Delay(1000);

   BSP_LED_Off(LED1);
}

此外,我还发现网上其他人有类似问题的实例,尽管到目前为止还没有解决方案。任何帮助将不胜感激。

4

2 回答 2

0

我发现了问题。我没有在 stm32f4xx_it.c 中设置 DMA 中断。

void DMA2_Stream3_IRQHandler(void)
{
  HAL_DMA_IRQHandler(haudio_out_sai.hdmatx);
}

我还发现,当使用BSP_AUDIO_OUT_Play()声音时,它下面的低音波动是错误的。

使用以下内容可以正常工作。

/* Start the playback */
  if(0 != audio_drv->Play(AUDIO_I2C_ADDRESS, NULL, 0))
  {
    Error_Handler();
  }
  if(HAL_OK != HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t *) PlayBuff, PLAY_BUFF_SIZE))
  {
    Error_Handler();
  }
于 2017-06-23T15:50:25.920 回答
-1

我不熟悉特定的板,据我所知,您可能需要将 TransferState 定义为 volatile。

volatile int TransferState = 0;

这是嵌入式和多线程开发中相当普遍的问题。编译器可以优化寄存器中的变量 TransferState,因此它实际上永远不会看到来自不同上下文(回调)的更新。易失性阻止它这样做

于 2017-06-22T17:13:59.463 回答