为什么用SD+DMA+DAC播放WAV文件只有哒哒哒的声音

2019-07-21 06:36发布

我是直接在开发板的PA4引脚和一个GND引脚上接的一个8欧0.5瓦的小喇叭,喇叭上还串联了一个105的电容,播放的WAV文件是8位22KHz单声道PCM格式的文件,DMA代码是这样的
  DMA_DeInit(DMA2_Channel3);
  DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR8R1_Address; // 单通道8位右对齐     数据的来源
  DMA_InitStructure.DMA_BufferSize = BUFF_SIZE; // 缓冲大小
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 8位数据宽度
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 8位数据宽度
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&Wavebuffer; // 内存基址     数据要写到哪里去
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; // 外设作为数据传输的目的地
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址寄存器不变
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存地址寄存器递增
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 工作在正常缓存模式
  DMA_InitStructure.DMA_Priority = DMA_Priority_High; // DMA通道x拥有高优先级
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // DMA通道x没有设置为内存到内存传输
  DMA_Init(DMA2_Channel3, &DMA_InitStructure);
  DMA_Cmd(DMA2_Channel3, ENABLE);     //使能DMA2通道3
  DMA_ITConfig(DMA2_Channel3, DMA_IT_TC | DMA_IT_HT, ENABLE);

TIM6的代码是这样的:
  TIM_DeInit(TIM6);
  TIM_SetAutoreload(TIM6, TIM6ARRValue);        //TIM6ARRValue的值是72000000/22050
  TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);
  TIM_Cmd(TIM6, ENABLE);

DAC的代码是这样的

  DAC_DeInit();
  DAC_StructInit(&DAC_InitStructure);

  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO; //选择定时器6做外部触发源
  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; // 无波形产生
  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; // 禁止输出缓冲

  DAC_Init(DAC_Channel_1, &DAC_InitStructure);         //DAC通道1初始化
  DAC_Cmd(DAC_Channel_1, ENABLE);            //使能DAC通道1:一旦使能了DAC通道1,PA.04将自动连接到DAC转换器
  DAC_DMACmd(DAC_Channel_1, ENABLE);       //使能DMA用于DAC通道1

  DAC_Init(DAC_Channel_2, &DAC_InitStructure);   //DAC通道2初始化
  DAC_Cmd(DAC_Channel_2, ENABLE);             //使能DAC通道2:一旦使能了DAC通道2,PA.05将自动连接到DAC转换器   
  DAC_DMACmd(DAC_Channel_2, ENABLE);        //使能DMA用于DAC通道2

然后使用了中断
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =3;//NVIC_PriorityGroup_1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;// NVIC_PriorityGroup_4;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

在中断函数中写数据

void PlayReadBlock(u16 offset)
{
    FRESULT res;
    res = f_read(&fp, Wavebuffer + offset, 512, &br);
    if((res!=FR_OK) || (br==0))
    {
      f_close(&fp);
    }
    else if (br < 512)
    {
        f_close(&fp);
        TIM_ITConfig(TIM6, TIM_IT_Update, DISABLE);    //禁止TIM6更新中断
          TIM_Cmd(TIM6, DISABLE);       //禁止TIM6    
    }    
}

void DMA2_Channel3_IRQHandler(void)
{
    if (DMA_GetITStatus(DMA2_IT_HT3) == SET)
    {    
        DMA_ClearITPendingBit(DMA2_IT_HT3);
        DMA_ClearFlag(DMA2_FLAG_HT3);
        //检查过半标志,有效,清除标志,处理前半段数据   
        PlayReadBlock(0);
    }
    LED3 = !LED3;
    if (DMA_GetITStatus(DMA2_IT_TC3) == SET)
    {  
        DMA_ClearITPendingBit(DMA2_IT_TC3);
        DMA_ClearFlag(DMA2_FLAG_TC3);    
        //检查完成标志,有效,清除标志,处理后半段数据
        PlayReadBlock(BUFF_SIZE>>1);
      }
}

基本上就是这些了,代码都能正常运行中断也能正常进入,不知道是不是我的配置有问题,或者是计算有问题,本人是菜鸟才入门STM32请教坛子里的各位朋友,谢谢了!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
11条回答
xiang90721
2019-07-22 06:41
回复【5楼】正点原子:
---------------------------------
原子大哥,1:使用DMA+DAC+TIM6这样的传输方式,因为外设地址不变,有木有可能DMA之前传送的一个数据还未数模转换,DMA传送的数据又到了将之前的数据覆盖了???
2:DMA使用正常模式(即不使用循环传送),缓冲区数据传送完成后将停止DMA传送,如果再次启动DMA,是不是又是从缓冲区首地址开始传送?
求解,谢谢原子大哥!

一周热门 更多>