OpenEdv-开源电子网

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

STM32F7 SPI DMA接收 收不到数据

[复制链接]

21

主题

134

帖子

0

精华

高级会员

Rank: 4

积分
624
金钱
624
注册时间
2014-11-11
在线时间
161 小时
发表于 2018-6-3 11:37:55 | 显示全部楼层 |阅读模式
20金钱
各位大神最近在用STM32F7调试SPI,STM32F7作为从机接收,想把接收到的数据DMA到SDRAM里,但是用DMA的时候一直接收不到数据,DMA中断也进不去,但是用 HAL_SPI_Receive(&SPI2_Handler,(vu8*)(Bank5_SDRAM_ADDR + j),1024,1000);这个函数就能接收到数据,不知怎么回事,查了好多资料都没能解决,求帮助。。。[mw_shl_code=applescript,true]#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "spi.h"
#include "sdram.h"
#include "dma.h"

u8 Buffer[1000];
u8 testsram[250000] __attribute__((at(0XC0000000)));//测试用数组

//SDRAM内存测试            
void fsmc_sdram_test(u16 x,u16 y)
{  
        u32 i=0;            
        u32 temp=0;          
        u32 sval=0;        //在地址0读到的数据                                            
//          LCD_ShowString(x,y,180,y+16,16,"Ex Memory Test:    0KB ");
        //每隔16K字节,写入一个数据,总共写入2048个数据,刚好是32M字节
        for(i=0;i<32*1024*1024;i+=2)
        {
                *(vu16*)(Bank5_SDRAM_ADDR+i)=0x55aa;
                temp++;
        }
        //依次读出之前写入的数据,进行校验                  
//         for(i=0;i<32*1024*1024;i+=16*1024)
//        {       
//                  temp=*(vu32*)(Bank5_SDRAM_ADDR+i);
//                if(i==0)sval=temp;
//                 else if(temp<=sval)break;//后面读出的数据一定要比第一次读到的数据大.                             
//                LCD_ShowxNum(x+15*8,y,(u16)(temp-sval+1)*16,5,16,0);        //显示内存容量  
//                printf("SDRAM Capacity:%dKB\r\n",(u16)(temp-sval+1)*16);//打印SDRAM容量
//         }                                         
}       

int main(void)
{
        u8 key;                 

        u32 i=0,j=0;             
        u32 ts=0;
    Cache_Enable();                 //打开L1-Cache
    HAL_Init();                                        //初始化HAL库
    Stm32_Clock_Init(432,25,2,9);   //设置时钟,216Mhz
    delay_init(216);                //延时初始化
        uart_init(115200);                        //串口初始化
    LED_Init();                     //初始化LED
    KEY_Init();                     //初始化按键
    SDRAM_Init();                   //初始化SDRAM
          SPI2_Init();
        MYDMA_Config(DMA1_Stream3,DMA_CHANNEL_0);

//    for(ts=0;ts<250000;ts++)
//        {
//                testsram[ts]=ts;//预存测试数据         
//          }
       
        for(i=0;i<32*1024*1024;i+=1)
        {
                *(vu8*)(Bank5_SDRAM_ADDR+i)=0;

        }
    while(1)
    {
//                        SPI_WR_BUSY(SPI2);
//       while((SPI2->SR & 1<<7)==1);                       
//             HAL_SPI_Receive(&SPI2_Handler,(vu8*)(Bank5_SDRAM_ADDR + j),1024,1000);
//                         i+=1000;
                          delay_ms(1);
//                        HAL_SPI_Receive_DMA(&SPI2_Handler,(vu8*)(Bank5_SDRAM_ADDR + j),10);
          }
}
[/mw_shl_code]

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

21

主题

134

帖子

0

精华

高级会员

Rank: 4

积分
624
金钱
624
注册时间
2014-11-11
在线时间
161 小时
 楼主| 发表于 2018-6-3 11:38:27 | 显示全部楼层
[mw_shl_code=applescript,true]#include "dma.h"
#include "usart.h"
#include "spi.h"
#include "sdram.h"
//////////////////////////////////////////////////////////////////////////////////         
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F746开发板
//DMA驱动代码          
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2015/12/28
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved                                                                          
//////////////////////////////////////////////////////////////////////////////////        

DMA_HandleTypeDef  SPI2RxDMA_Handler;      //DMA句柄

//DMAx的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式
//DMA_StreamxMA数据流,DMA1_Stream0~7/DMA2_Stream0~7
//chxMA通道选择,@ref DMA_channel DMA_CHANNEL_0~DMA_CHANNEL_7
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u32 chx)
{
        if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
        {
        __HAL_RCC_DMA2_CLK_ENABLE();//DMA2时钟使能       
        }else
        {
        __HAL_RCC_DMA1_CLK_ENABLE();//DMA1时钟使能
        }
   
    __HAL_LINKDMA(&SPI2_Handler,hdmatx,SPI2RxDMA_Handler);    //将DMA与SPI2联系起来(发送DMA)
   
    //Tx DMA配置
    SPI2RxDMA_Handler.Instance=DMA_Streamx;                            //数据流选择
    SPI2RxDMA_Handler.Init.Channel=chx;                                //通道选择
    SPI2RxDMA_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY;             //存储器到外设
    SPI2RxDMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE;                 //外设非增量模式
    SPI2RxDMA_Handler.Init.MemInc=DMA_MINC_ENABLE;                     //存储器增量模式
    SPI2RxDMA_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_BYTE;    //外设数据长度:8位
    SPI2RxDMA_Handler.Init.MemDataAlignment=DMA_MDATAALIGN_BYTE;       //存储器数据长度:8位
    SPI2RxDMA_Handler.Init.Mode=DMA_CIRCULAR;                            //外设流控模式
    SPI2RxDMA_Handler.Init.Priority=DMA_PRIORITY_MEDIUM;               //中等优先级
    SPI2RxDMA_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE;              
    SPI2RxDMA_Handler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;      
    SPI2RxDMA_Handler.Init.MemBurst=DMA_MBURST_SINGLE;                 //存储器突发单次传输
    SPI2RxDMA_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE;              //外设突发单次传输
   
    HAL_DMA_DeInit(&SPI2RxDMA_Handler);   
    HAL_DMA_Init(&SPI2RxDMA_Handler);
//          __HAL_DMA_ENABLE(&SPI2RxDMA_Handler);
                HAL_NVIC_SetPriority(DMA1_Stream3_IRQn,2,1);
                HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
                __HAL_DMA_ENABLE(&SPI2RxDMA_Handler);
//                DMA_Cmd(DMA1_Stream4,ENABLE);
                HAL_SPI_Receive_DMA(&SPI2_Handler,(vu8*)(Bank5_SDRAM_ADDR ),10);

}


void DMA1_Stream3_IRQHandler(void)
{

      HAL_DMA_IRQHandler(&SPI2RxDMA_Handler);
            HAL_SPI_DMAStop(&SPI2_Handler);
         HAL_SPI_Receive_DMA(&SPI2_Handler,(vu8*)(Bank5_SDRAM_ADDR ),10);
}

[/mw_shl_code]
回复

使用道具 举报

21

主题

134

帖子

0

精华

高级会员

Rank: 4

积分
624
金钱
624
注册时间
2014-11-11
在线时间
161 小时
 楼主| 发表于 2018-6-3 11:38:58 | 显示全部楼层
[mw_shl_code=applescript,true]#include "spi.h"
//////////////////////////////////////////////////////////////////////////////////         
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F7开发板
//SPI驱动代码          
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2015/12/30
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved                                                                          
//////////////////////////////////////////////////////////////////////////////////        

SPI_HandleTypeDef SPI2_Handler;  //SPI2句柄

//以下是SPI模块的初始化代码,配置成主机模式                                                   
//SPI口初始化
//这里针是对SPI2的初始化
void SPI2_Init(void)
{
    SPI2_Handler.Instance=SPI2;                      //SP2
    SPI2_Handler.Init.Mode=SPI_MODE_SLAVE;          //设置SPI工作模式,设置为主模式
    SPI2_Handler.Init.Direction=SPI_DIRECTION_2LINES;//设置SPI单向或者双向的数据模式:SPI设置为双线模式
    SPI2_Handler.Init.DataSize=SPI_DATASIZE_8BIT;    //设置SPI的数据大小:SPI发送接收8位帧结构
    SPI2_Handler.Init.CLKPolarity=SPI_POLARITY_HIGH; //串行同步时钟的空闲状态为高电平
    SPI2_Handler.Init.CLKPhase=SPI_PHASE_2EDGE;      //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
    SPI2_Handler.Init.NSS=SPI_NSS_HARD_INPUT;              //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
//    SPI2_Handler.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_256;//定义波特率预分频的值:波特率预分频值为256
    SPI2_Handler.Init.FirstBit=SPI_FIRSTBIT_MSB;     //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
    SPI2_Handler.Init.TIMode=SPI_TIMODE_ENABLE;     //关闭TI模式
    SPI2_Handler.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE;//关闭硬件CRC校验
    SPI2_Handler.Init.CRCPolynomial=7;               //CRC值计算的多项式
    SPI2_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
    HAL_SPI_Init(&SPI2_Handler);
   
    __HAL_SPI_ENABLE(&SPI2_Handler);                 //使能SPI2
//    SPI2_ReadWriteByte(0Xff);                        //启动传输
}

//SPI2底层驱动,时钟使能,引脚配置
//此函数会被HAL_SPI_Init()调用
//hspi:SPI句柄
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
    GPIO_InitTypeDef GPIO_Initure;
   
    __HAL_RCC_GPIOB_CLK_ENABLE();                   //使能GPIOF时钟
          __HAL_RCC_GPIOI_CLK_ENABLE();
    __HAL_RCC_SPI2_CLK_ENABLE();                    //使能SPI2时钟
   
    //PB13,14,15
    GPIO_Initure.Pin=GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
    GPIO_Initure.Mode=GPIO_MODE_AF_PP;              //复用推挽输出
    GPIO_Initure.Pull=GPIO_PULLUP;                  //上拉
    GPIO_Initure.Speed=GPIO_SPEED_FAST;             //快速   
    GPIO_Initure.Alternate=GPIO_AF5_SPI2;           //复用为SPI2
    HAL_GPIO_Init(GPIOB,&GPIO_Initure);             //初始化
//       
          GPIO_Initure.Pin=GPIO_PIN_0;;
    GPIO_Initure.Mode=GPIO_MODE_AF_PP;              //复用推挽输出
    GPIO_Initure.Pull=GPIO_PULLUP;                  //上拉
    GPIO_Initure.Speed=GPIO_SPEED_FAST;             //快速   
    GPIO_Initure.Alternate=GPIO_AF5_SPI2;           //复用为SPI2
    HAL_GPIO_Init(GPIOI,&GPIO_Initure);             //初始化
       
}

//SPI速度设置函数
//SPI速度=fAPB1/分频系数
//@ref SPI_BaudRate_Prescaler:SPI_BAUDRATEPRESCALER_2~SPI_BAUDRATEPRESCALER_2 256
//fAPB1时钟一般为54Mhz:
void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
{
    assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));//判断有效性
    __HAL_SPI_DISABLE(&SPI2_Handler);            //关闭SPI
    SPI2_Handler.Instance->CR1&=0XFFC7;          //位3-5清零,用来设置波特率
    SPI2_Handler.Instance->CR1|=SPI_BaudRatePrescaler;//设置SPI速度
    __HAL_SPI_ENABLE(&SPI2_Handler);             //使能SPI
   
}

//SPI2 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPI2_ReadWriteByte(u8 TxData)
{
    u8 Rxdata;
    HAL_SPI_TransmitReceive(&SPI2_Handler,&TxData,&Rxdata,1, 1000);      
        return Rxdata;                              //返回收到的数据               
}
[/mw_shl_code]
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2018-6-4 01:54:39 | 显示全部楼层
帮顶
回复

使用道具 举报

21

主题

134

帖子

0

精华

高级会员

Rank: 4

积分
624
金钱
624
注册时间
2014-11-11
在线时间
161 小时
 楼主| 发表于 2018-6-4 14:31:09 | 显示全部楼层
顶一下   别沉了
回复

使用道具 举报

21

主题

134

帖子

0

精华

高级会员

Rank: 4

积分
624
金钱
624
注册时间
2014-11-11
在线时间
161 小时
 楼主| 发表于 2018-6-6 16:18:21 | 显示全部楼层
有大神配置过SPI 的接收中断吗
回复

使用道具 举报

4

主题

84

帖子

1

精华

高级会员

Rank: 4

积分
666
金钱
666
注册时间
2013-10-21
在线时间
88 小时
发表于 2018-6-8 15:06:37 | 显示全部楼层
本帖最后由 旮旯旭 于 2018-6-8 15:14 编辑

我在F1 F4上实现过 SPI DMA接收,速度比MCU控制的快3倍
回复

使用道具 举报

4

主题

84

帖子

1

精华

高级会员

Rank: 4

积分
666
金钱
666
注册时间
2013-10-21
在线时间
88 小时
发表于 2018-6-8 15:20:48 | 显示全部楼层
[mw_shl_code=applescript,true]//extern DMA_HandleTypeDef hdma_spi1_rx;
//extern DMA_HandleTypeDef hdma_spi1_tx;
void SPI_Flash_Read_Sector_DMA(u8 *pbuffer,u32 pSector)
{
        pSector*=W25QXX_Sector_Size;
        SPI_FLASH_CS=0;        //使能器件
        SPI_Flash_Start(W25X_ReadData,pSector);

        //__HAL_SPI_DISABLE(&hspi1);//禁止SPI1,设置为只接受,无CLK信号,接收模式需要关闭
        //SET_BIT(hspi1.Instance->CR1, SPI_DIRECTION_2LINES_RXONLY);//设置成只接收模式
       
        HAL_SPI_Receive_DMA(&hspi1,pbuffer,W25QXX_Sector_Size);//DMA接收数据
       
        while(__HAL_DMA_GET_FLAG(&hdma_spi1_rx,DMA_FLAG_TCIF0_4)==RESET);//获取接收完成标志
        while(__HAL_DMA_GET_FLAG(&hdma_spi1_tx,DMA_FLAG_TCIF3_7)==RESET);//获取接收完成标志
        SPI_FLASH_CS=1;        //取消片选

        HAL_DMA_Abort(&hdma_spi1_rx);//停止DMA接收,初始化中断标志和禁用流
        HAL_DMA_Abort(&hdma_spi1_tx);//停止DMA接收,初始化中断标志和禁用流
        //CLEAR_BIT(hspi1.Instance->CR1, SPI_DIRECTION_2LINES_RXONLY);//设置成全双工模式
        SPI_Flash_Wait_Busy();
}


//void SPI_Flash_Read_Sector_DMA(u8 *pbuffer,u32 pSector)
//{
//        pSector*=W25QXX_Sector_Size;
//        SPI_FLASH_CS=0;                                //使能器件
//        SPI_Flash_Start(W25X_ReadData,pSector);
//        SPI1->DR;
//        SET_BIT(hspi1.Instance->CR1, SPI_DIRECTION_2LINES_RXONLY);//设置成只接收模式
//        HAL_SPI_Receive_DMA(&hspi1,pbuffer,W25QXX_Sector_Size);
//        while(__HAL_DMA_GET_FLAG(&hdma_spi1_rx,DMA_FLAG_TCIF0_4)==RESET);//获取接收完成标志
//        SPI_FLASH_CS=1;                            //取消片选
//       
//        CLEAR_BIT(hspi1.Instance->CR1, SPI_DIRECTION_2LINES_RXONLY);//设置成全双工模式
//        HAL_DMA_Abort(&hdma_spi1_rx);//停止DMA接收,初始化中断标志和禁用流
//       
//        SPI_Flash_Wait_Busy();//必须要加,等待空闲
//}

void MX_SPI1_Init(void)
{
        hspi1.Instance                        = SPI1;
        hspi1.Init.Mode                        = SPI_MODE_MASTER;
        hspi1.Init.Direction        = SPI_DIRECTION_2LINES;
        hspi1.Init.DataSize                = SPI_DATASIZE_8BIT;
        hspi1.Init.CLKPolarity        = SPI_POLARITY_HIGH;
        hspi1.Init.CLKPhase                = SPI_PHASE_2EDGE;
        hspi1.Init.NSS                        = SPI_NSS_SOFT;
        hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
        hspi1.Init.FirstBit                = SPI_FIRSTBIT_MSB;
        hspi1.Init.TIMode                = SPI_TIMODE_DISABLE;
        hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
        hspi1.Init.CRCPolynomial        = 10;
        if (HAL_SPI_Init(&hspi1) != HAL_OK)
        {
                _Error_Handler(__FILE__, __LINE__);
        }
}

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(hspi->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */

  /* USER CODE END SPI1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();
          
    /**SPI1 GPIO Configuration   
    PB3     ------> SPI1_SCK
    PB4     ------> SPI1_MISO
    PB5     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* SPI1 DMA Init */
    /* SPI1_RX Init */
    hdma_spi1_rx.Instance                = DMA2_Stream0;
    hdma_spi1_rx.Init.Channel        = DMA_CHANNEL_3;
    hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_rx.Init.MemInc        = DMA_MINC_ENABLE;
    hdma_spi1_rx.Init.PeriphDataAlignment        = DMA_PDATAALIGN_BYTE;
    hdma_spi1_rx.Init.MemDataAlignment                = DMA_MDATAALIGN_BYTE;
    hdma_spi1_rx.Init.Mode                = DMA_NORMAL;
    hdma_spi1_rx.Init.Priority        = DMA_PRIORITY_LOW;
    hdma_spi1_rx.Init.FIFOMode        = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(hspi,hdmarx,hdma_spi1_rx);

    /* SPI1_TX Init */
    hdma_spi1_tx.Instance                = DMA2_Stream3;
    hdma_spi1_tx.Init.Channel        = DMA_CHANNEL_3;
    hdma_spi1_tx.Init.Direction        = DMA_MEMORY_TO_PERIPH;
    hdma_spi1_tx.Init.PeriphInc        = DMA_PINC_DISABLE;
    hdma_spi1_tx.Init.MemInc        = DMA_MINC_DISABLE;
    hdma_spi1_tx.Init.PeriphDataAlignment        = DMA_PDATAALIGN_BYTE;
    hdma_spi1_tx.Init.MemDataAlignment                = DMA_MDATAALIGN_BYTE;
    hdma_spi1_tx.Init.Mode                = DMA_NORMAL;
    hdma_spi1_tx.Init.Priority        = DMA_PRIORITY_LOW;
    hdma_spi1_tx.Init.FIFOMode        = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(hspi,hdmatx,hdma_spi1_tx);

  /* USER CODE BEGIN SPI1_MspInit 1 */

  /* USER CODE END SPI1_MspInit 1 */
  }

}
[/mw_shl_code]
回复

使用道具 举报

0

主题

3

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2020-4-13
在线时间
5 小时
发表于 2022-2-28 15:36:00 | 显示全部楼层
刺客mfl 发表于 2018-6-6 16:18
有大神配置过SPI 的接收中断吗

我遇到了和你一样的问题
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-26 03:07

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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