STM32的SPI3的DMA,这样配置对吗?

2019-07-20 15:48发布

unsigned char DMA1_Init(void)
{
         DMA_InitTypeDef DMA1_Init;
               
         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2,ENABLE);

         //DMA2通道2用于RAM->SPI的数据传输
         DMA_DeInit(DMA2_Channel2);//发送
         DMA1_Init.DMA_PeripheralBaseAddr=(u32)&SPI3->DR;//SPI3_DR_Address (u32)&SPI3->DR
         //DMA1_Init.DMA_MemoryBaseAddr=...; //启动传输前装入实际RAM地址
         DMA1_Init.DMA_DIR=DMA_DIR_PeripheralDST;
         DMA1_Init.DMA_BufferSize=1028;//1028
         DMA1_Init.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
         DMA1_Init.DMA_MemoryInc=DMA_MemoryInc_Enable;
         DMA1_Init.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
         DMA1_Init.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
         DMA1_Init.DMA_Mode=DMA_Mode_Normal;
         DMA1_Init.DMA_Priority=DMA_Priority_High;
         DMA1_Init.DMA_M2M=DMA_M2M_Disable;

         DMA_Init(DMA2_Channel2,&DMA1_Init); //对DMA2通道2进行初始化
               
         //DMA通道1用于SPI->RAM的数据传输
         DMA_DeInit(DMA2_Channel1);        //接收
         DMA1_Init.DMA_PeripheralBaseAddr=(u32)&SPI3->DR;
         //DMA1_Init.DMA_MemoryBaseAddr=...; //启动传输前装入实际RAM地址
         DMA1_Init.DMA_DIR=DMA_DIR_PeripheralSRC;
         DMA1_Init.DMA_BufferSize=1028;//512
         DMA1_Init.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
         DMA1_Init.DMA_MemoryInc=DMA_MemoryInc_Enable;
         DMA1_Init.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
         DMA1_Init.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
         DMA1_Init.DMA_Mode=DMA_Mode_Normal;
         DMA1_Init.DMA_Priority=DMA_Priority_High;
         DMA1_Init.DMA_M2M=DMA_M2M_Disable;
         
         DMA_Init(DMA2_Channel1,&DMA1_Init); //对DMA通道1进行初始化
         
         SPI_I2S_DMACmd(SPI3,SPI_I2S_DMAReq_Rx,ENABLE); //使能SPI的DMA接收请求
         SPI_I2S_DMACmd(SPI3,SPI_I2S_DMAReq_Tx,ENABLE); //使能SPI的DMA发送请求

         return 0;
}

unsigned char DMA1_Star_SPI_RX(u8 *buffer,u16 len)
{
                //DMA_DeInit(DMA2_Channel1);        //接收
            unsigned char temp=0xff;
            
                DMA2_Channel1->CNDTR=len; //设置传输的数据长度
                DMA2_Channel1->CMAR=(unsigned long)buffer; //设置内存缓冲区地址
               
                /*SPI作为主机进行数据接收时必须要主动产生时钟,因此此处必须有DMA通道2的配合*/
                DMA2_Channel2->CNDTR=len;
                DMA2_Channel2->CMAR=(u32)&temp; //temp=0xff
                DMA2_Channel2->CCR&=~DMA_MemoryInc_Enable; //内存地址非自增
               
                DMA_Cmd(DMA2_Channel1,ENABLE); //首先启动DMA通道1
                DMA_Cmd(DMA2_Channel2,ENABLE); //再启动DMA通道2
                while(!DMA_GetFlagStatus(DMA2_FLAG_TC1)); //等待DMA通道1接收数据完成
                DMA_ClearFlag(DMA2_FLAG_TC1);
                DMA_ClearFlag(DMA2_FLAG_TC2); //清除DMA通道1与2的传输完成标志
                DMA_Cmd(DMA2_Channel1,DISABLE);
                DMA_Cmd(DMA2_Channel2,DISABLE); //使DMA通道1与2停止工作
               
                DMA2_Channel2->CCR|=DMA_MemoryInc_Enable; //将DMA通道2恢复为内存地址自增方式
          return 0;
}

//向sd卡写入一个数据包的内容 len字节 启动DMA传输
//buf:数据缓存区
unsigned char DMA1_Star_SPI_TX(u8 *buffer,u16 len)
{
                DMA2_Channel2->CNDTR=len; //设置要传输的数据长度//DMA2_Channel2->CNDTR=512;
                DMA2_Channel2->CMAR=(u32)buffer; //设置RAM缓冲区地址
               
                DMA_Cmd(DMA2_Channel2,ENABLE); //启动DMA传输 RAM->SPI
                while(!DMA_GetFlagStatus(DMA2_FLAG_TC2)); //等待DMA通道2传输完成
                DMA_ClearFlag(DMA2_FLAG_TC2); //清除通道2传输完成状态标记
                DMA_Cmd(DMA2_Channel2,DISABLE); //使DMA通道2停止工作
          return 0;
}


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
18条回答
lvehe
1楼-- · 2019-07-20 20:20
midisamboy
2楼-- · 2019-07-20 22:21
lvehe 发表于 2016-5-31 19:31
http://www.openedv.com/thread-60866-1-1.html
看我的帖子

看起来没什么差异,就是不行呀,运行会卡在while(!DMA_GetFlagStatus(DMA2_FLAG_TC2));
xuande
3楼-- · 2019-07-21 03:37

1、可能SPI没有工作,或者运行次数不够、不足以触发DMA的标志;
2、DMA配置错误。


midisamboy
4楼-- · 2019-07-21 05:18
 精彩回答 2  元偷偷看……
xuande
5楼-- · 2019-07-21 06:19

去查下DMA2_FLAG_TC2标志的意义。


lvehe
6楼-- · 2019-07-21 08:44
midisamboy 发表于 2016-6-1 10:08
看起来没什么差异,就是不行呀,运行会卡在while(!DMA_GetFlagStatus(DMA2_FLAG_TC2));

差异大了去了!
你好好对比你的发送函数和接收函数,发送函数没有设置通道1。
SPI无论发送还是接收,2个通道必须同时工作,发送时接收通道也必须开启,可设置接收通道为内存地址不自增的方式。
具体代码见我的帖子附件。

一周热门 更多>