OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4225|回复: 1

stm32l系列单片机驱动WM8978的问题

[复制链接]

4

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2018-5-18
在线时间
20 小时
发表于 2020-10-29 16:40:26 | 显示全部楼层 |阅读模式
1金钱
项目用了L496单片机,参考了原子哥的“潘多拉STM32L475”的例程,驱动WM8978
用的是SAI2,在用示波器量出LRC=44.6M,BLCK=2.85M,MCLK=11.43M,可以看出,SAI初始化应该没有问题
现在问题来了:在程序跑起来之后,只有几个时钟的波形正常显示,但是ADC没有采样,或者说SAIB的DMA中断没有进去
由于L系列没有双缓存,所以按照潘多拉例程,使用半完成中断
录音模式的进入函数和例程如出一辙
//进入PCM 录音模式                   
void recoder_enter_rec_mode(void)
{
        WM8978_ADDA_Cfg(0,1);                //开启ADC   关闭DAC
        WM8978_Input_Cfg(1,1,0);        //开启输入通道(MIC&LINE IN) 这里就说明两个地方都使用 不管是麦克风输入 说着数据线输入都可以接收
        WM8978_Output_Cfg(1,1);                //开启BYPASS输出 DAC输出要不要也开着?
        WM8978_MIC_Gain(46);                //MIC增益设置
        WM8978_SPKvol_Set(0);                //关闭喇叭.
        WM8978_I2S_Cfg(2,0);                //飞利浦标准,16位数据长度
       
        MX_SAI2_Init();//SAI1 Block A,主发送,16位数据
        SAIA_TX_DMA_Init();
        __HAL_DMA_DISABLE_IT(&hdma_sai2_a_TX_Handler, DMA_IT_TC);
        SAIA_RX_DMA_Init();
    sai_rx_callback = rec_sai_dma_rx_callback;//初始化回调函数指sai_rx_callback
    HAL_SAI_Transmit(&hsai_BlockA2, (uint8_t *)&saiplaybuf[0], 2, 0);
    HAL_SAI_Receive_DMA(&hsai_BlockB2, sairecbuf, SAI_RX_DMA_BUF_SIZE);
    SAI_Play_Start();                        //开始SAI数据发送(主机),为SAI1B通道提供时钟
}


于是我想是不是DMA初始化部分出现了问题
static void SAIA_TX_DMA_Init(void)
{
        __HAL_RCC_DMA1_CLK_ENABLE();
    __HAL_LINKDMA(&hsai_BlockA2,hdmatx,hdma_sai2_a_TX_Handler);
    hdma_sai2_a_TX_Handler.Instance = DMA1_Channel6;
    hdma_sai2_a_TX_Handler.Init.Request = DMA_REQUEST_1;
    hdma_sai2_a_TX_Handler.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_sai2_a_TX_Handler.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_sai2_a_TX_Handler.Init.MemInc = DMA_MINC_ENABLE;
    hdma_sai2_a_TX_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; //此处是音频采样码率 8位:DMA_PDATAALIGN_BYTE /32位:DMA_PDATAALIGN_WORD
    hdma_sai2_a_TX_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;    //此处是音频采样码率 8位:DMA_MDATAALIGN_BYTE /32位:DMA_MDATAALIGN_WORD
    hdma_sai2_a_TX_Handler.Init.Mode = DMA_CIRCULAR;                           //循环模式?
    hdma_sai2_a_TX_Handler.Init.Priority = DMA_PRIORITY_HIGH;                   //优先级之后再排
    if (HAL_DMA_Init(&hdma_sai2_a_TX_Handler) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
    __HAL_DMA_DISABLE(&hdma_sai2_a_TX_Handler);                         //先关闭DMA
    delay_us(10);                                                   //10us延时,防止-O2优化出问题        
    __HAL_DMA_ENABLE_IT(&hdma_sai2_a_TX_Handler,DMA_IT_TC);             //开启传输完成中断
        __HAL_DMA_ENABLE_IT(&hdma_sai2_a_TX_Handler,DMA_IT_HT);             //开启半传输完成中断
       
    __HAL_DMA_CLEAR_FLAG(&hdma_sai2_a_TX_Handler,DMA_FLAG_TC6);             //清除DMA传输完成中断标志位
        __HAL_DMA_CLEAR_FLAG(&hdma_sai2_a_TX_Handler,DMA_FLAG_HT6);             //清除DMA半传输完成中断标志位

        HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
}

static void SAIA_RX_DMA_Init(void)
{
        __HAL_RCC_DMA2_CLK_ENABLE();
        __HAL_LINKDMA(&hsai_BlockB2,hdmarx,hdma_sai2_b_RX_Handler);
        hdma_sai2_b_RX_Handler.Instance = DMA2_Channel4;
        hdma_sai2_b_RX_Handler.Init.Request = DMA_REQUEST_1;
        hdma_sai2_b_RX_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY;
        hdma_sai2_b_RX_Handler.Init.PeriphInc = DMA_PINC_DISABLE;
        hdma_sai2_b_RX_Handler.Init.MemInc = DMA_MINC_ENABLE;
        hdma_sai2_b_RX_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;//此处需要和A block对应,多少码率采集就用多少码率播放
        hdma_sai2_b_RX_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
        hdma_sai2_b_RX_Handler.Init.Mode = DMA_CIRCULAR;
        hdma_sai2_b_RX_Handler.Init.Priority = DMA_PRIORITY_LOW;
        if (HAL_DMA_Init(&hdma_sai2_b_RX_Handler) != HAL_OK)
        {
          _Error_Handler(__FILE__, __LINE__);
        }
       
        HAL_NVIC_SetPriority(DMA2_Channel4_IRQn, 0, 1);
        HAL_NVIC_EnableIRQ(DMA2_Channel4_IRQn);
}

使用的半传输完成中断,基本和例程相同,区别在于DMA通道使用的不一样,经检查,DMA1_6和DMA2_4都应该使用正确
最后是DMA中断处理和回调函数
void DMA1_Channel6_IRQHandler(void)
{
        DMA1_Channel6_Callback(&hdma_sai2_a_TX_Handler);       
}

void DMA2_Channel4_IRQHandler(void)
{
        DMA2_Channel4_Callback(&hdma_sai2_b_RX_Handler);
}


问题点就在此处,程序仿真,打断点于两个DMA中断函数,发现无论怎样,DMA都不进中断,啊,想得我头秃
望大佬们或者原子哥能帮着看看

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2018-5-18
在线时间
20 小时
 楼主| 发表于 2020-10-29 16:54:05 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-4-29 23:45

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表