OpenEdv-开源电子网

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

通过DMA给I2S的数据寄存器SPI->DR发送数据,中断显示数据发送完了,但是SPI->DR里的值一直是0x0000,请问是什么原因?

[复制链接]

23

主题

73

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
449
金钱
449
注册时间
2016-7-12
在线时间
121 小时
发表于 2016-9-27 08:57:34 | 显示全部楼层 |阅读模式
10金钱
本帖最后由 莫问1990 于 2016-9-27 09:02 编辑

通过DMA给I2S的数据寄存器SPI->DR发送数据,中断显示数据发送完了,但是SPI->DR里的值一直是0x0000,请问是什么原因?I2S的配置如下:
[mw_shl_code=c,true]void I2S2_Init(u16 I2S_Standard,u16 I2S_Mode,u16 I2S_Clock_Polarity,u16 I2S_DataFormat)
{
    I2S_InitTypeDef    I2S_InitStructure;

       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//使能SPI2时钟
       
        RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE); //复位SPI2
        RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE);//结束复位
               
  
        I2S_InitStructure.I2S_Mode=I2S_Mode;//IIS模式
        I2S_InitStructure.I2S_Standard=I2S_Standard;//IIS标准
        I2S_InitStructure.I2S_DataFormat=I2S_DataFormat;//IIS数据长度
        I2S_InitStructure.I2S_MCLKOutput=I2S_MCLKOutput_Enable;//主时钟输出禁止
        I2S_InitStructure.I2S_AudioFreq=I2S_AudioFreq_44k;//IIS频率设置
        I2S_InitStructure.I2S_CPOL=I2S_Clock_Polarity;//空闲状态时钟电平       
        I2S_Init(SPI2,&I2S_InitStructure);//初始化IIS
       
        SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Tx,ENABLE);//SPI2 TX DMA请求使能.       
    I2S_Cmd(SPI2,ENABLE);//SPI2 I2S EN使能.
       

} [/mw_shl_code]


DMA的配置如下:
[mw_shl_code=c,true]void I2S2_TX_DMA_Init(u8* buf0,u8 *buf1,u16 num)
{  

        NVIC_InitTypeDef   NVIC_InitStructure;
        DMA_InitTypeDef    DMA_InitStructure;
       
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//DMA1时钟使能
       
        DMA_DeInit(DMA1_Channel5);   //将DMA1的通道4寄存器重设为缺省值       

       
  /* 配置 DMA1 Channel5 */       
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI2->DR;//外设地址为u32)&SPI2->DR
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)buf0;//DMA 存储器0地址       
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//存储器到外设模式
    DMA_InitStructure.DMA_BufferSize = num;//数据传输量
    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_Circular;// 使用循环模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输  
       
    DMA_Init(DMA1_Channel5, &DMA_InitStructure);//初始化DMA Channel4

   
    DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);//开启传输完成中断       
  

    NVIC_InitStructure.NVIC_IRQChannel =DMA1_Channel5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;//子优先级0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
    NVIC_Init(&NVIC_InitStructure);//配置


}  [/mw_shl_code]

在中断里设置了DMA的双缓冲的切换,仿真时发现切换时有效了,而且DMA发送完的中断是运行的,但是SPI->DR里的数据就是没有变化
[mw_shl_code=c,true]void DMA1_Channel5_IRQHandler(void)
{  

   
        if(DMA_GetITStatus(DMA1_IT_TC5)==SET)////DMA1_Channel4,传输完成标志
        {
                               
               
        DMA_Cmd(DMA1_Channel5,DISABLE);
               

                if((DMA1_Channel5->CMAR)==((u32)audiodev.i2sbuf1))
                {       
                        DMA1_Channel5->CMAR=(u32)audiodev.i2sbuf2;
//                        DMA_InitStructure.DMA_MemoryBaseAddr =(u32)audiodev.i2sbuf2;
//                        DMA_InitStructure.DMA_BufferSize =DMA1_MEM_LEN;
//                        DMA_Init(DMA1_Channel5, &DMA_InitStructure);
            mp3witchbuf=0;

                }
                else
                {
                        DMA1_Channel5->CMAR=(u32)audiodev.i2sbuf1;
//                        DMA_InitStructure.DMA_MemoryBaseAddr =(u32)audiodev.i2sbuf1;
//                        DMA_InitStructure.DMA_BufferSize =DMA1_MEM_LEN;
//                        DMA_Init(DMA1_Channel5, &DMA_InitStructure);                                               
                        mp3witchbuf=1;
                                               
                }
               
                DMA_Cmd(DMA1_Channel5,ENABLE);
               
               
                DMA_ClearITPendingBit(DMA1_IT_TC5);               
                       
              i2s_tx_callback();        //执行回调函数,读取数据等操作在这里面处理  
                       
               
        }                                                                                            
} [/mw_shl_code]

最佳答案

查看完整内容[请看2#楼]

DR寄存器在CPU内部有两个实体,A和B, 都是DR,但写的时候是向A里面写,读是从B往外读, 写进去的内容是永远读不回来的。类似接口还有串口,可能还有其他。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

58

主题

6294

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11571
金钱
11571
注册时间
2014-4-1
在线时间
1320 小时
发表于 2016-9-27 08:57:35 | 显示全部楼层
本帖最后由 xuande 于 2016-9-27 11:26 编辑

DR寄存器在CPU内部有两个实体,A和B,
都是DR,但写的时候是向A里面写,读是从B往外读,
写进去的内容是永远读不回来的。类似接口还有串口,可能还有其他。



回复

使用道具 举报

6

主题

201

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1149
金钱
1149
注册时间
2015-11-13
在线时间
267 小时
发表于 2016-9-27 09:09:53 | 显示全部楼层
SPI2_Tx对应的是DMA1的数据流4,你的这个通道5是肯定不对的
回复

使用道具 举报

23

主题

73

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
449
金钱
449
注册时间
2016-7-12
在线时间
121 小时
 楼主| 发表于 2016-9-27 09:53:38 | 显示全部楼层
特朗姆斯 发表于 2016-9-27 09:09
SPI2_Tx对应的是DMA1的数据流4,你的这个通道5是肯定不对的

DMA1

DMA1

回复

使用道具 举报

23

主题

73

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
449
金钱
449
注册时间
2016-7-12
在线时间
121 小时
 楼主| 发表于 2016-9-27 09:54:07 | 显示全部楼层
回复

使用道具 举报

6

主题

201

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1149
金钱
1149
注册时间
2015-11-13
在线时间
267 小时
发表于 2016-9-27 10:40:24 | 显示全部楼层
那应该把问题发在F1的区里,或者注明一下型号。。
回复

使用道具 举报

6

主题

201

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1149
金钱
1149
注册时间
2015-11-13
在线时间
267 小时
发表于 2016-9-27 10:49:54 | 显示全部楼层
调试DMA应该观察SPI_Tx发送出去的数据是否正确,而不是看SPI->DR寄存器的值,因为数据已经通过DMA发出去了。

回复

使用道具 举报

23

主题

73

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
449
金钱
449
注册时间
2016-7-12
在线时间
121 小时
 楼主| 发表于 2016-9-27 13:34:00 | 显示全部楼层
xuande 发表于 2016-9-27 11:16
DR寄存器在CPU内部有两个实体,A和B,
都是DR,但写的时候是向A里面写,读是从B往外读,
写进去的内容是 ...

我是播放音频文件,一直往DR里写数据,也读取不到吗?DMA的中断显示发送完了,而且在不停的填充数据并发送,但是语音芯片没有反应!!
回复

使用道具 举报

58

主题

6294

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11571
金钱
11571
注册时间
2014-4-1
在线时间
1320 小时
发表于 2016-9-27 13:36:41 | 显示全部楼层
莫问1990 发表于 2016-9-27 13:34
我是播放音频文件,一直往DR里写数据,也读取不到吗?DMA的中断显示发送完了,而且在不停的填充数据并发 ...


说得还不清楚吗?


回复

使用道具 举报

6

主题

201

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1149
金钱
1149
注册时间
2015-11-13
在线时间
267 小时
发表于 2016-9-27 13:46:44 | 显示全部楼层
xuande 发表于 2016-9-27 11:16
DR寄存器在CPU内部有两个实体,A和B,
都是DR,但写的时候是向A里面写,读是从B往外读,
写进去的内容是 ...

还是版主理解的透彻,赞同这是正解。
回复

使用道具 举报

23

主题

73

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
449
金钱
449
注册时间
2016-7-12
在线时间
121 小时
 楼主| 发表于 2016-9-27 15:49:54 | 显示全部楼层
xuande 发表于 2016-9-27 13:36
说得还不清楚吗?

F103RFT6的I2S是没有I2Sext_SD,所以我没有接SPI的MISO。但是探索者407开发板的I2S是全双工的,我在407的板子上测试时,DR寄存器里的值是变化的,我将MISO引脚接高电平或低电平都不影响DR寄存器里的值。但是将MOSI引脚接高电平或低电平,DR寄存器的值是0xFFFF或0x0000,这是为什么啊?
回复

使用道具 举报

58

主题

6294

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11571
金钱
11571
注册时间
2014-4-1
在线时间
1320 小时
发表于 2016-9-27 16:41:48 | 显示全部楼层
莫问1990 发表于 2016-9-27 15:49
F103RFT6的I2S是没有I2Sext_SD,所以我没有接SPI的MISO。但是探索者407开发板的I2S是全双工的,我在407的 ...


不了解I2S,刚才临时看了一下。
I2S比较复杂,各种标准,信号也不一样。
但同样是两个buffer,TX和RX;写入是一个,读出是另一个。
无论是用 i=DR,还是仿真器观察,两种方式都是“读出”,数据都来源于RX的buffer。

出现你说的问题,我猜测数据线是双向的。

回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2016-9-28 23:14:48 | 显示全部楼层
你这样看是不对的。 直接看SD线上的波形比较好。
仿真看寄存器数据, 发送完以后,是0很正常的。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-7-12 01:47

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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