打印
[STM32F0]

DMA实现SPI1与SPI2通信?

[复制链接]
2039|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
donsbin|  楼主 | 2016-9-28 15:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
两块FLASH分别接到片子的SPI1与SPI2上面,现在想把FLASH1的数据拷贝到SPI2上。
目前想采用DMA实现数据拷贝,即SPI1从FLASH读数据,然后SPI2把数据写到FLASH2上。
DMA寄存器到寄存器的模式, 中间不进过缓存的过渡。不知道这种是否可以实现。
沙发
稳稳の幸福| | 2016-9-28 17:01 | 只看该作者
absolutely。
你完全可以。

使用特权

评论回复
板凳
稳稳の幸福| | 2016-9-28 17:05 | 只看该作者
//SPI1: PA5--SCK  PA7--MOSI
//SPI2: PB13--SCK  PB15--MOSI
//SPI1--Master  SPI2--Slave
//SPI1发送数据到SPI1的数据寄存器   然后SPI2数据寄存器中如果有数据的时候会发出DMA请求  接着DMA把数据搬到内部寄存器SPI2_Buffer_Rx[BufferSize]
//SPI1DMA1_Channel3传送数据  时钟速率达到36M/s ,SPI2DMA1_Channel4传送 最大速率达18M/s
#include"stm32f10x.h"
#define BufferSize  50
#define SPI2_DR_Addr  0x4000380c
#define SPI1_DR_Addr  0x4001300c
uint8_t Idex=0;
typedef enum {FAILED=0,PASSED=!FAILED}TextStatus;
uint16_tSPI1_Buffer_Tx[BufferSize]={0x0102,0x0203,0x0304,0x0405,0x0506,0x0607,0x0708,0x0809,0x090a,0x0a0b,
                                                                             0x0102,0x0203,0x0304,0x0405,0x0506,0x0607,0x0708,0x0809,0x090a,0x0a0b,
                                                                             0x0102,0x0203,0x0304,0x0405,0x0506,0x0607,0x0708,0x0809,0x090a,0x0a0b,
                                                                             0x0102,0x0203,0x0304,0x0405,0x0506,0x0607,0x0708,0x0809,0x090a,0x0a0b,
                                                                             0x0102,0x0203,0x0304,0x0405,0x0506,0x0607,0x0708,0x0809,0x090a,0x0a0b
                                     };
uint16_t SPI2_Buffer_Rx[BufferSize];
volatile TextStatus textstatus=FAILED;
void RCC_Config(void);
void GPIO_Config(void);
void DMA_Config(void);
void SPI_Config(void);
TextStatus TempComp(uint16_t*temp1,uint16_t* temp2,uint16_t length);
int main(void)
{
RCC_Config();
GPIO_Config();
DMA_Config();
SPI_Config();
while(1);
}
void RCC_Config(void)
{
//RCC_PCLK2Config(RCC_HCLK_Div2);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_SPI1,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
}
void GPIO_Config(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
void DMA_Config(void)
{
  DMA_InitTypeDef DMA_InitStructure;
  DMA_DeInit(DMA1_Channel4);
  DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)SPI2_DR_Addr;
  DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)SPI2_Buffer_Rx;
  DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_BufferSize=BufferSize;
  DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority=DMA_Priority_High;
  DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;
  DMA_Init(DMA1_Channel4,&DMA_InitStructure);
  DMA_DeInit(DMA1_Channel3);
  DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)SPI1_DR_Addr;
   DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)SPI1_Buffer_Tx;
  DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST;
  DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_BufferSize=BufferSize;
  DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority=DMA_Priority_High;
  DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;
  DMA_Init(DMA1_Channel3,&DMA_InitStructure);
  DMA_Cmd(DMA1_Channel3,ENABLE);
  DMA_Cmd(DMA1_Channel4,ENABLE);
}
void SPI_Config(void)
{
  SPI_InitTypeDef SPI_InitStructure;
  SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode=SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize=SPI_DataSize_16b;
  SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge;
   SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_2;
  SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial=7;
  SPI_Init(SPI1,&SPI_InitStructure);
  SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode=SPI_Mode_Slave;
  SPI_Init(SPI2,&SPI_InitStructure);
  SPI_Cmd(SPI1,ENABLE);
  SPI_Cmd(SPI2,ENABLE);
  SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Rx,ENABLE);
  SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,ENABLE);
   /*
  while(Idex < BufferSize)
   {
         while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);
         SPI_I2S_SendData(SPI1,SPI1_Buffer_Tx[Idex++]);
         //SPI1只管发送数据然后 如果SPI2数据寄存器中数据满的话 会发出DMA请求接着DMA干活
         while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)==RESET);
         SPI2_Buffer_Rx[Idex++]=SPI_I2S_ReceiveData(SPI2);
   }
   */
  while(DMA_GetFlagStatus(DMA1_FLAG_TC3)==RESET);
  while(DMA_GetFlagStatus(DMA1_FLAG_TC4)==RESET);
  textstatus=TempComp(SPI1_Buffer_Tx,SPI2_Buffer_Rx,BufferSize);
}
TextStatus TempComp(uint16_t*temp1,uint16_t* temp2,uint16_t length)
{
while(length--)
  {
  if(*temp1 != *temp2)
   {
         return FAILED;
   }
  temp1++;
  temp2++;
  }
  return PASSED;
}
——————————————


使用特权

评论回复
地板
稳稳の幸福| | 2016-9-28 17:05 | 只看该作者
网上找了个,你看看能用不。既然有,肯定可以。

使用特权

评论回复
5
donsbin|  楼主 | 2016-9-28 17:10 | 只看该作者
稳稳の幸福 发表于 2016-9-28 17:01
absolutely。
你完全可以。

DMA转换完成后必然要进完成中断,这时候我就必须重新使能和加载地址。毕竟寄存器到寄存器每次只能半个字转换,而我需要拷贝的数据>65535,DMA中断也就会大量消耗调CPU资源?

使用特权

评论回复
6
玄德| | 2016-9-29 08:51 | 只看该作者
donsbin 发表于 2016-9-28 17:10
DMA转换完成后必然要进完成中断,这时候我就必须重新使能和加载地址。毕竟寄存器到寄存器每次只能半个字 ...


重新使能、加载,很耗时吗?
何况65536才中断一次。


使用特权

评论回复
7
玄德| | 2016-9-29 08:52 | 只看该作者

思路没问题,
具体操作会有情况。

SPI1和SPI2之间可能做不到,
但SPI2和SPI3之间能做到。

使用特权

评论回复
8
donsbin|  楼主 | 2016-9-29 09:39 | 只看该作者
玄德 发表于 2016-9-29 08:52
思路没问题,
具体操作会有情况。

感谢回复。
DMA控制寄存器到寄存器的通信我一直卡在一个问题上,在没有CPU参与下,就是SPI2怎么知道SPI1已经读取完成呢?
最初的思路是SPI2->DR指向SPI1->DR,中间不损耗内存

使用特权

评论回复
9
donsbin|  楼主 | 2016-9-29 20:26 | 只看该作者
目前开了一个两级的BUFF,一边读一边写。调完LZ贴代码

使用特权

评论回复
10
mingtai86| | 2017-10-17 16:22 | 只看该作者
donsbin 发表于 2016-9-29 20:26
目前开了一个两级的BUFF,一边读一边写。调完LZ贴代码

楼主你好,我也要DMA实现SPI1与SPI2通信,你开发的程序能够帖出来,让我学习一下。
我的联系方式是mingtai86@163.com

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:思亘七险,点落九宫,神游八极,纵横十方。

20

主题

96

帖子

2

粉丝