学前班
最后登录1970-1-1
在线时间 小时
注册时间2014-9-12
|
本帖最后由 wz18th 于 2016-10-23 14:44 编辑
想用STM32F407做个播放器,由于从SD卡读取文件时间比较长,如果单缓冲DMA传输到I2S总是断,现在用双缓冲模式做测试,却发现双缓冲数据发送错位了,部分测试代码如下:
这是配置函数:- void I2S_Mode_Config(uint16_t _usStandard, uint16_t _usWordLen, uint32_t _uiAudioFreq, uint16_t _usMode)
- {
- I2S_InitTypeDef I2S_InitStructure;
- if ((_usMode == I2S_Mode_SlaveTx) && (_usMode == I2S_Mode_SlaveRx))
- {
- /*不支持这2种模式 */
- return;
- }
- /*
- For I2S mode, make sure that either:
- - I2S PLL is configured using the functions RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S),
- RCC_PLLI2SCmd(ENABLE) and RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY).
- */
- {
- uint32_t n = 0;
- FlagStatus status = RESET;
-
- RCC_PLLI2SConfig(271,2);//new,手册755页表格
- RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S);
- RCC_PLLI2SCmd(ENABLE);
- for (n = 0; n < 500; n++)
- {
- status = RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY);
- if (status == 1)
- {
- break;
- }
- }
- }
- /* 打开 I2S2 APB1 时钟 */
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
- /* 复位 SPI2 外设到缺省状态 */
- SPI_I2S_DeInit(SPI2);
-
- /* I2S2 外设配置 */
- if (_usMode == I2S_Mode_MasterTx)
- {
- I2S_StructInit(&I2S_InitStructure);
- I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx; /* 配置I2S工作模式 */
- I2S_InitStructure.I2S_Standard = _usStandard; /* 接口标准 */
- I2S_InitStructure.I2S_DataFormat = _usWordLen; /* 数据格式,16bit */
- I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;/* 主时钟模式 */
- I2S_InitStructure.I2S_AudioFreq = _uiAudioFreq; /* 音频采样频率 */
- I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
- I2S_Init(SPI2, &I2S_InitStructure);
- // /* Configure the I2Sx_ext (the second instance) in Slave Receiver Mode */
- // I2S_FullDuplexConfig(I2S2ext, &I2S_InitStructure);
- /* 使能 SPI2/I2S2 外设 */
- I2S_Cmd(SPI2, ENABLE);
- // /* Enable the I2Sx_ext peripheral for Full Duplex mode */
- // I2S_Cmd(I2S2ext, ENABLE);
- }
- }
复制代码- void I2S_DMA_Config(u32 memory_address_0,u32 memory_address_1,u16 number_to_transfer)
- {
- DMA_InitTypeDef DMA_InitStructure;
-
- SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Tx,ENABLE);//配置I2S TX DMA使能
-
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能
-
- DMA_DeInit(DMA1_Stream4);
-
- while (DMA_GetCmdStatus(DMA1_Stream4) != DISABLE){}//等待DMA可配置
-
- /* 配置 DMA Stream */
- DMA_InitStructure.DMA_Channel = DMA_Channel_0; //通道选择
- DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI2->DR; //DMA外设地址
- DMA_InitStructure.DMA_Memory0BaseAddr = memory_address_0; //DMA 存储器0地址
- DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; //存储器到外设模式
- DMA_InitStructure.DMA_BufferSize = number_to_transfer; //数据传输量
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器增量模式
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据长度:16位
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//存储器数据长度:16位
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //使用循环模式
- DMA_InitStructure.DMA_Priority = DMA_Priority_High; //高优先级
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存储器突发单次传输
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输
- DMA_Init(DMA1_Stream4, &DMA_InitStructure);//初始化DMA Stream
-
- //配置双缓冲的第二个缓冲区,指定第一个缓冲区先发
- DMA_DoubleBufferModeConfig(DMA1_Stream4, memory_address_1,DMA_Memory_0);
- DMA_DoubleBufferModeCmd(DMA1_Stream4,ENABLE); //使能双缓冲
- }
复制代码- void I2S_DMA_Trans_Start(void)
- {
- DMA_Cmd(DMA1_Stream4, ENABLE);
- }
复制代码
在主函数中:
- u16 test_buf0[8] = {0x0000, 0x1111, 0x2222, 0x3333, 0x4444 ,0x5555, 0x6666, 0x7777};
- u16 test_buf1[8] = {0x8888, 0x9999, 0xaaaa, 0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xffff};
- I2S_Mode_Config(I2S_Standard_Phillips,I2S_DataFormat_16b,I2S_AudioFreq_44k,I2S_Mode_MasterTx);
- I2S_DMA_Config((u32)test_buf0, (u32)test_buf1, 8);
- I2S_DMA_Trans_Start();
复制代码
预想结果是按顺序输出:
0x0000, 0x1111, 0x2222, 0x3333, 0x4444 ,0x5555, 0x6666, 0x7777, 0x8888, 0x9999, 0xaaaa, 0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xffff
然后不断自动重复……
但是结果却不是这样的,逻辑分析仪输出是这样:
逻辑分析仪捕捉结果1
逻辑分析仪捕捉结果2
请问是哪里出了问题呢?
|
|