打印
[STM32F0]

STM32F0 SPI_DMA RX模式求教

[复制链接]
4311|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
stm32m0 使用SPI-DMA RX接收数据,配置如下:
DMA_InitTypeDef   DMA_InitStructure;
NVIC_InitTypeDef  NVIC_InitStructure;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
  RCC_APB1PeriphClockCmd(A7130_SPI2, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

//SPI2 RX DMA  将数据从外设读取到内部存储器中
DMA_DeInit(DMA1_Channel4);         //
DMA_InitStructure.DMA_PeripheralBaseAddr = SPI2_DR_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t)RfBuf;
DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralSRC;//外设为源地址
//DMA_InitStructure.DMA_BufferSize         = 65;

DMA_InitStructure.DMA_BufferSize         = 64;
DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;        //传输时外设地址不自增
DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;         //内存自增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设传输长度为8 bit
DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;         //内存传输长度为8 bit
DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;         //非循环采集
//DMA_InitStructure.DMA_Priority           = DMA_Priority_High;         //优先级为中
DMA_InitStructure.DMA_Priority           = DMA_Priority_VeryHigh;         //优先级为中
DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;         //非存储器到存储器模式
DMA_Init(DMA1_Channel4, &DMA_InitStructure);


DMA_ITConfig(DMA1_Channel4,DMA_IT_TC | DMA_IT_TE ,ENABLE);
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, DISABLE);
DMA_Cmd(DMA1_Channel4, DISABLE);



DMA_DeInit(DMA1_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr = SPI2_DR_ADDRESS;
//        DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t)A7130_READ_ADDR;

DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t)&A7130_READ_ADDR;
//        DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t)&dummy;
DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralDST;
//DMA_InitStructure.DMA_BufferSize         = 65;

DMA_InitStructure.DMA_BufferSize         = 64;
DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
//        DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority           = DMA_Priority_Low;
DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure);

DMA_ITConfig(DMA1_Channel5,DMA_IT_TC | DMA_IT_TE,ENABLE);
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, DISABLE);
DMA_Cmd(DMA1_Channel5, DISABLE);

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

准备将接收的数据放到RfBuf数组中,在主函数中使能发送和接收,主要如下:

DMA_Cmd(DMA1_Channel5, DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel5,66);    //配置发送数据长度
DMA_Cmd(DMA1_Channel4, DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel4,64);   //配置接收数据长度

DMA_Cmd(DMA1_Channel5, ENABLE);
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx , ENABLE);
DMA_Cmd(DMA1_Channel4, ENABLE);
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);

现在的情况如下:SPI DMA 能收到数据,能放入RfBuf中,当每运行一次,数据的位置都在变化,
例如原本RfBuf的第一次收到的数据为 01,02,03,04.....第二次运行的时候就为00,00,00,01,02,03...第三次运行的时候就为00,00,01,02,03...
第四次运行的时候就为00,01,02,03... 第5次的时候为 01,02,03,04....

还有另外一个问题就是按道理来说,要使用DMA-RX接收数据,需要使用DMA-TX发送时钟,但我发送的时钟已经比接收时钟多两个字节了,却还是先进入发送完成中断先,难道DMA接收和发送的时钟不是同步的吗?

请指教,谢谢!

沙发
sinc_mark|  楼主 | 2014-7-2 18:38 | 只看该作者
自己顶一下,求指导,这个东西折腾了好几天了!

使用特权

评论回复
板凳
airwill| | 2014-7-2 22:12 | 只看该作者
1. 感觉数据长度设置不对, 导致数据错位了.
2. SPI-DMA 收发数据用的是相同的时钟, 所以应该是 TX 先完成, 下半个脉冲后 RX 完成.

使用特权

评论回复
地板
sinc_mark|  楼主 | 2014-7-3 08:15 | 只看该作者
airwill 发表于 2014-7-2 22:12
1. 感觉数据长度设置不对, 导致数据错位了.
2. SPI-DMA 收发数据用的是相同的时钟, 所以应该是 TX 先完成,  ...

按理解,应该是收发都设置为同样的时钟长度就对的,但我设置为相同的时钟长度,永远都是先完成接收中断。

使用特权

评论回复
5
香水城| | 2014-7-3 11:41 | 只看该作者
F0具体哪颗料号?

对应的勘误手册上有无关于SPI部分的说明?

使用特权

评论回复
6
香水城| | 2014-7-3 12:01 | 只看该作者
第二个问题比较好解释:F0的SPI,接收和发送方向各有4字节的FIFO

正因为如此,发送DMA可以很快的把后两个数据传到FIFO中,就触发【发送DMA完成中断】;而此时FIFO中的后两个数据还排在FIFO中,正等待接收方的第64个字节,也就是发送方的倒数第三个字节,在SPI总线上慢慢的、一位一位的传输呢。当这个正在传输的字节在总线上一位一位的传输完毕后,才触发【接收DMA完成中断】。

使用特权

评论回复
7
sinc_mark|  楼主 | 2014-7-3 12:51 | 只看该作者
香水城 发表于 2014-7-3 11:41
F0具体哪颗料号?

对应的勘误手册上有无关于SPI部分的说明?

STM32F051 ,怎么查有没有对应的勘误手册啊?

使用特权

评论回复
8
香水城| | 2014-7-3 13:03 | 只看该作者
www.st.com/stm32f0

然后页面的左边有Document栏,展开菜单有个Errate sheet(勘误手册)。打开新的页面,是所有F0下的不同料号的勘误手册


点击每个条目前的“...”,可以出现该勘误手册适应的所有料号。

使用特权

评论回复
9
sinc_mark|  楼主 | 2014-7-4 13:49 | 只看该作者
谢谢版主的提醒,看了看勘误手册,并无说spi DMA 有异常的情况,还在纠结这个问题,真的很无语,不明白为什么...

使用特权

评论回复
10
香水城| | 2014-7-4 17:32 | 只看该作者
本帖最后由 香水城 于 2014-7-4 17:35 编辑

你还是把MCU型号报一下吧。

然后,现在就只剩第一个问题了,是吧。那么把SPI的配置代码也贴出来吧。

使用特权

评论回复
11
sinc_mark|  楼主 | 2014-7-5 09:15 | 只看该作者
香水城 发表于 2014-7-4 17:32
你还是把MCU型号报一下吧。

然后,现在就只剩第一个问题了,是吧。那么把SPI的配置代码也贴出来吧。 ...

mcu 是32f051r8,
spi配置是:
GPIO_InitTypeDef  GPIO_InitStruct;
          SPI_InitTypeDef   SPI_InitStruct;

  /*!< SD_SPI_CS_GPIO, SD_SPI_MOSI_GPIO, SD_SPI_MISO_GPIO, SD_SPI_DETECT_GPIO
       and SD_SPI_SCK_GPIO Periph clock enable */
  // RCC_AHBPeriphClockCmd(A7130_CS_PIN_SCK|A7130_SCK_PIN_SCK|A7130_MISO_PIN_SCK | A7130_MOSI_PIN_SCK, ENABLE);
  //RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF| RCC_AHBPeriph_GPIOB, ENABLE);
  
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
  /*!< SD_SPI Periph clock enable */
       
  RCC_APB1PeriphClockCmd(A7130_SPI2, ENABLE);

  /*!< Configure SD_SPI pins: SCK */
  GPIO_InitStruct.GPIO_Pin = A7130_SCK_PIN;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStruct.GPIO_PuPd  = GPIO_PuPd_UP;
  GPIO_Init(A7130_SCK_PORT, &GPIO_InitStruct);

  /*!< Configure SD_SPI pins: MISO */
  GPIO_InitStruct.GPIO_Pin = A7130_MISO_PIN;
  GPIO_Init(A7130_MISO_PORT, &GPIO_InitStruct);

  /*!< Configure SD_SPI pins: MOSI */
  GPIO_InitStruct.GPIO_Pin =A7130_MOSI_PIN;
  GPIO_Init(A7130_MOSI_PORT, &GPIO_InitStruct);
  
  /* Connect PXx to SD_SPI_SCK */
  GPIO_PinAFConfig(A7130_SCK_PORT, A7130_SCK_SOURCE, A7130_SCK_AF);

  /* Connect PXx to SD_SPI_MISO */
  GPIO_PinAFConfig(A7130_MISO_PORT, A7130_MISO_SOURCE, A7130_MISO_AF);

  /* Connect PXx to SD_SPI_MOSI */
  GPIO_PinAFConfig(A7130_MOSI_PORT, A7130_MOSI_SOURCE, A7130_MOSI_AF);
       
       
         /*!< Configure SD_SPI_CS_PIN pin: SD Card CS pin */
  GPIO_InitStruct.GPIO_Pin =A7130_CS_PIN;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;
  GPIO_Init(A7130_CS_PORT, &GPIO_InitStruct);
       
  


  SPI_Cmd(SPI2, DISABLE);
  /*!< SD_SPI Config */
  SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
  SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
  SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
  SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStruct.SPI_CRCPolynomial = 7;
  SPI_Init(SPI2, &SPI_InitStruct);
  SPI_RxFIFOThresholdConfig(SPI2, SPI_RxFIFOThreshold_QF);
  SPI_Cmd(SPI2, ENABLE); /*!< SD_SPI enable */
  A7130_CS_HIGH();

DMA配置见帖子开头处,
启动DMA传输:
A7130_SPI_SendByte(0x45);
DMA_Cmd(DMA1_Channel5, DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel5,64);
DMA_Cmd(DMA1_Channel4, DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel4,64);
                               
DMA_Cmd(DMA1_Channel5, ENABLE);
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
DMA_Cmd(DMA1_Channel4, ENABLE);
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);
我是准备用spi的DMA功能读一个2.4Gic传输过来的数据,调试的时候,发现数据在跳变,到现在都没找不数据跳动的原因!

使用特权

评论回复
12
sinc_mark|  楼主 | 2014-7-5 11:29 | 只看该作者
一直没搞懂,为什么第一次出错的时候,是数据帧先往右移动3个字节,然后左移一个字节,一步一步的移动回到正确的位置上,然后继续这个过程。但这个移动并不是每一次运行都发生,是运行一段时间后产生的,而且时间间隔并无规律可言!

使用特权

评论回复
13
sinc_mark|  楼主 | 2014-7-7 17:58 | 只看该作者
依旧困扰在这个地方,到底是不是stm32多通道dma 存在这样的bug呢?为什么程序能正常运行一段时间后才会出现这样的问题..

使用特权

评论回复
14
sinc_mark|  楼主 | 2014-7-18 08:06 | 只看该作者
第一次使用DMA功能,不是我配置的问题,是程序架构导致的!

使用特权

评论回复
15
seawwh| | 2015-8-4 21:48 | 只看该作者
我在F405 SPI DMA 读取24L01 的过程中也发生了数据错位问题,不到千分之一的出错概率。
你的问题解决了吗?

使用特权

评论回复
16
seawwh| | 2015-8-4 21:48 | 只看该作者
我在F405 SPI DMA 读取24L01 的过程中也发生了数据错位问题,不到千分之一的出错概率。
你的问题解决了吗?

使用特权

评论回复
17
Thor9| | 2015-8-5 11:30 | 只看该作者
F0的SPI接收和发送方向各有4字节的FIFO

使用特权

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

本版积分规则

个人签名:教育,就是把娃围起来,一期一期的收钱。 医疗,就是把命围起来,一天一天的收钱。

47

主题

301

帖子

0

粉丝