OpenEdv-开源电子网

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

WM8978和STM32L496的问题,L系列没有双缓存

[复制链接]

4

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2018-5-18
在线时间
20 小时
发表于 2020-9-24 10:40:46 | 显示全部楼层 |阅读模式
1金钱
项目要用L系列的单片机,驱动WM8978实现录音,然后我就懵了,L系列没有双缓存,好多库函数也不一样,DMA应该怎么配,配完了怎么开启DMA呢

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

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2020-9-25 02:06:43 | 显示全部楼层
没双缓冲就用半完成中断来处理
回复

使用道具 举报

4

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2018-5-18
在线时间
20 小时
 楼主| 发表于 2020-9-25 09:41:51 | 显示全部楼层
正点原子 发表于 2020-9-25 02:06
没双缓冲就用半完成中断来处理

//进入PCM 录音模式                   
void recoder_enter_rec_mode(void)
{
//---------------------------配置芯片功能------------------------------------------------------------
        WM8978_ADDA_Cfg(0,1);                //开启ADC  DAC要不要也开着 然后把录入到双缓存的数据直接丢到芯片中去DAC??
        WM8978_Input_Cfg(1,1,0);        //开启输入通道(MIC&LINE IN) 这里就说明两个地方都使用 不管是麦克风输入 说着数据线输入都可以接收
        WM8978_Output_Cfg(0,1);                //开启BYPASS输出 DAC输出要不要也开着?
        WM8978_MIC_Gain(46);                //MIC增益设置
        WM8978_SPKvol_Set(0);                //关闭喇叭.
        WM8978_I2S_Cfg(2,0);                //飞利浦标准,16位数据长度
       
//---------------------------SAI_DMA_数据传输------------------------------------------------------------
        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_Play_Start();                        //开始SAI数据发送(主机)
        SAI_Rec_Start();                         //开始SAI数据接收(从机)
}

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_DMA_Start(&hdma_sai2_b_RX_Handler ,(uint32_t)&SAI2_Block_B->DR ,(uint32_t)SAI2_blockB_DMA_RX ,SAI_RX_DMA_BUF_SIZE*2);
        HAL_SAI_Receive_DMA(&hsai_BlockA2 ,SAI2_blockB_DMA_RX ,SAI_RX_DMA_BUF_SIZE*2);
        __HAL_DMA_DISABLE(&hdma_sai2_b_RX_Handler);
        delay_us(10);
        __HAL_DMA_ENABLE_IT(&hdma_sai2_b_RX_Handler,DMA_IT_TC);
        __HAL_DMA_CLEAR_FLAG(&hdma_sai2_b_RX_Handler,DMA_FLAG_TC4);
        HAL_NVIC_SetPriority(DMA2_Channel4_IRQn, 4, 0);
        HAL_NVIC_EnableIRQ(DMA2_Channel4_IRQn);
}

原子哥,基本上和阿波罗开发板的例程一样,只把双缓冲改成了HAL_SAI_Transmit_DMA,但是就是不进DMA中断,这是为什么呢
回复

使用道具 举报

4

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2018-5-18
在线时间
20 小时
 楼主| 发表于 2020-9-25 10:22:53 | 显示全部楼层
这是SAI初始化的部分
static void MX_SAI2_Init(void)
{
        //SAI2_A
        HAL_SAI_DeInit(&hsai_BlockA2);
        hsai_BlockA2.Instance = SAI2_Block_A;
        hsai_BlockA2.Init.Protocol = SAI_FREE_PROTOCOL;             //设置SAI1协议为:自由协议(支持I2S/LSB/MSB/TDM/PCM/DSP等协议)
        hsai_BlockA2.Init.AudioMode = SAI_MODEMASTER_TX;                                                //设置SAI2工作模式(可修改)
        hsai_BlockA2.Init.DataSize = SAI_DATASIZE_16;                                                                //数据大小(可修改)
        hsai_BlockA2.Init.FirstBit = SAI_FIRSTBIT_MSB;                                                        //数据MSB位优先
        hsai_BlockA2.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;//数据在时钟的上升/下降沿选通(可修改)
        hsai_BlockA2.Init.Synchro = SAI_ASYNCHRONOUS;                                                                //音频模块异步
        hsai_BlockA2.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;     //立即驱动音频模块输出
        hsai_BlockA2.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;     //使能主时钟分频器(MCKDIV)
        hsai_BlockA2.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;    //设置FIFO阈值,1/4 FIFO
        hsai_BlockA2.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_44K; //设置音频采样率
        hsai_BlockA2.Init.MonoStereoMode = SAI_STEREOMODE;          //立体声模式  
        //帧设置  
        hsai_BlockA2.FrameInit.FrameLength = 64;                     //设置帧长度为64,左通道32个SCK,右通道32个SCK.
        hsai_BlockA2.FrameInit.ActiveFrameLength = 32;               //设置帧同步有效电平长度,在I2S模式下=1/2帧长
        hsai_BlockA2.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;//FS信号为SOF信号+通道识别信号
        hsai_BlockA2.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;       //FS低电平有效(下降沿)
        hsai_BlockA2.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;     //在slot0的第一位的前一位使能FS,以匹配飞利浦标准
        //SLOT设置  
        hsai_BlockA2.SlotInit.FirstBitOffset = 0;                    //slot偏移(FBOFF)为0
        hsai_BlockA2.SlotInit.SlotSize = SAI_SLOTSIZE_32B;           //slot大小为32位
        hsai_BlockA2.SlotInit.SlotNumber = 2;                        //slot数为2个
        hsai_BlockA2.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1; //使能slot0和slot1
        if (HAL_SAI_Init(&hsai_BlockA2) != HAL_OK)
        {
        _Error_Handler(__FILE__, __LINE__);
        }
        __HAL_SAI_ENABLE(&hsai_BlockA2);
        //SAI2_B
        HAL_SAI_DeInit(&hsai_BlockB2);
        hsai_BlockB2.Instance = SAI2_Block_B;
        hsai_BlockB2.Init.Protocol = SAI_FREE_PROTOCOL;
        hsai_BlockB2.Init.AudioMode = SAI_MODESLAVE_RX;
        hsai_BlockB2.Init.DataSize = SAI_DATASIZE_16;
        hsai_BlockB2.Init.FirstBit = SAI_FIRSTBIT_MSB;
        hsai_BlockB2.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
        hsai_BlockB2.Init.Synchro = SAI_SYNCHRONOUS;
        hsai_BlockB2.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
        hsai_BlockB2.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
          hsai_BlockB2.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
        hsai_BlockB2.Init.MonoStereoMode = SAI_STEREOMODE;

        //帧设置   
        hsai_BlockB2.FrameInit.FrameLength = 64;
        hsai_BlockB2.FrameInit.ActiveFrameLength = 32;
        hsai_BlockB2.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
        hsai_BlockB2.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
        hsai_BlockB2.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
        //SLOT设置   
        hsai_BlockB2.SlotInit.FirstBitOffset = 0;
        hsai_BlockB2.SlotInit.SlotSize = SAI_SLOTSIZE_32B;
        hsai_BlockB2.SlotInit.SlotNumber = 2;
        hsai_BlockB2.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1;
        if (HAL_SAI_Init(&hsai_BlockB2) != HAL_OK)
        {
        _Error_Handler(__FILE__, __LINE__);
        }
        SAIB_DMA_Enable();
        __HAL_SAI_ENABLE(&hsai_BlockB2);
}
回复

使用道具 举报

4

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2018-5-18
在线时间
20 小时
 楼主| 发表于 2020-9-25 10:30:02 | 显示全部楼层
MCLK和BCLK我量了下,都是有输出的,证明时钟这块配的应该没问题
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2020-9-26 01:38:41 | 显示全部楼层
xyw66668 发表于 2020-9-25 09:41
//进入PCM 录音模式                   
void recoder_enter_rec_mode(void)
{

可能你的dma根本没开始传输。。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

4

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2018-5-18
在线时间
20 小时
 楼主| 发表于 2020-9-27 08:49:25 | 显示全部楼层
正点原子 发表于 2020-9-26 01:38
可能你的dma根本没开始传输。。。。

所以其实我理解的就是,SAI数据采集本质上也是也是一个ADC采样,开启ADC的DMA传输的HAL库函数有“HAL_ADC_Start_DMA”“HAL_ADCEx_MultiModeStart_DMA”一些函数;SAI开启DMA传输,是调用“HAL_DMAEx_MultiBufferStart”,但是我试遍L系列HAL库给出的函数,感觉没有一个可以调用使得DMA开始传输的函数,有点尴尬
回复

使用道具 举报

4

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2018-5-18
在线时间
20 小时
 楼主| 发表于 2020-9-27 09:01:15 | 显示全部楼层
正点原子 发表于 2020-9-26 01:38
可能你的dma根本没开始传输。。。。

我理解的是SAI的数据采集和传输,本质上和adc采样没有区别,ADC外设的采集用到DMA传输的时候,是调用“HAL_ADCEx_MultiModeStart_DMA”或者“HAL_ADC_Start_DMA”;SAI调用DMA时,F系列有“HAL_DMAEx_MultiBufferStart”,但是L系列就没有类似这样的HAL库函数
回复

使用道具 举报

4

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2018-5-18
在线时间
20 小时
 楼主| 发表于 2020-9-27 09:05:34 | 显示全部楼层
这是从stm32l4xx_hal_sai.h上扒下来的库函数


/* I/O operation functions  ***************************************************/
/** @addtogroup SAI_Exported_Functions_Group2
  * @{
  */
/* Blocking mode: Polling */
HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout);

/* Non-Blocking mode: Interrupt */
HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size);

/* Non-Blocking mode: DMA */
HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai);
HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai);
HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai);

/* Abort function */
HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai);

/* Mute management */
HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val);
HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai);
HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter);
HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai);

/* SAI IRQHandler and Callbacks used in non blocking modes (Interrupt and DMA) */
void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai);
void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai);
void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai);
void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai);
void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai);
void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai);
/**
  * @}
  */
回复

使用道具 举报

4

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2018-5-18
在线时间
20 小时
 楼主| 发表于 2020-9-27 17:19:08 | 显示全部楼层
下午又仔细的用示波器量了一下,发现很奇怪,在wm8978上只有8,10两个脚有来自单片机的信号,分别是SCK=3.077M约等于fs*slot个数*slot大小,这个脚应该是对的,10脚大约是12.3M,即256*fs,但是10脚定义为DACDAT,对比了PCB发现连线是没有问题的,其他三个sai引脚均无信号,
我~懵~了·
回复

使用道具 举报

4

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2018-5-18
在线时间
20 小时
 楼主| 发表于 2020-9-27 17:19:38 | 显示全部楼层
xyw66668 发表于 2020-9-27 17:19
下午又仔细的用示波器量了一下,发现很奇怪,在wm8978上只有8,10两个脚有来自单片机的信号,分别是SCK=3.0 ...

也就是说MCLK的信号,跑到了DACDAT引脚上
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-22 17:04

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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