初级会员

- 积分
- 69
- 金钱
- 69
- 注册时间
- 2018-5-18
- 在线时间
- 20 小时
|
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都不进中断,啊,想得我头秃
望大佬们或者原子哥能帮着看看
|
|