OpenEdv-开源电子网

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

STM32H7 SPI+DMA传输错误

[复制链接]

2

主题

43

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
484
金钱
484
注册时间
2017-11-6
在线时间
162 小时
发表于 2018-3-5 14:26:43 | 显示全部楼层 |阅读模式
20金钱
  请问一下STM32H7的SPI+DMA该如何配置,之前按照同样的方式配置F4和F7的时候都没有什么问题,这次换了H7的芯片,在移植程序的时候一只卡在SPI+DMA这里无法通过,不加DMA单调试SPI的时候收发都没有问题,就是加上DMA以后一只发生DMA传输错误,请问这是什么原因造成的,附上DPI+DMA的配置代码void SPI1_Init(void)
{
        SPI1_Handler.Instance=SPI1;                         //SP1
        SPI1_Handler.Init.Mode=SPI_MODE_MASTER;             //设置SPI工作模式,设置为主模式
        SPI1_Handler.Init.Direction=SPI_DIRECTION_2LINES;   //设置SPI单向或者双向的数据模式:SPI设置为双线模式
        SPI1_Handler.Init.DataSize=SPI_DATASIZE_16BIT;       //设置SPI的数据大小:SPI发送接收16位帧结构
        SPI1_Handler.Init.CLKPolarity=SPI_POLARITY_LOW;     //串行同步时钟的空闲状态为低电平
        SPI1_Handler.Init.CLKPhase=SPI_PHASE_2EDGE;         //串行同步时钟的第一个跳变沿(上升或下降)数据被采样
        SPI1_Handler.Init.NSS=SPI_NSS_SOFT;                 //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
        SPI1_Handler.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_32;//定义波特率预分频的值:波特率预分频值为8
        SPI1_Handler.Init.FirstBit=SPI_FIRSTBIT_MSB;        //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
        SPI1_Handler.Init.TIMode=SPI_TIMODE_DISABLE;        //关闭TI模式
        SPI1_Handler.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE;//关闭硬件CRC校验
        SPI1_Handler.Init.CRCPolynomial=7;                  //CRC值计算的多项式  

        HAL_SPI_Init(&SPI1_Handler);               
}

void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
        GPIO_InitTypeDef GPIO_Initure;
  if(hspi->Instance == SPI1)
        {
          __HAL_RCC_SPI1_CLK_ENABLE();
                __HAL_RCC_GPIOA_CLK_ENABLE();
                __HAL_RCC_GPIOC_CLK_ENABLE();

    /**SPI1 GPIO Configuration   
    PA4     ------> SPI1_NSS
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI
    */               
               
                // PA5 PA6 PA7
                GPIO_Initure.Pin=  GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 ;                        //PA5 PA6 PA7
                GPIO_Initure.Mode=GPIO_MODE_AF_PP;                //复用推挽输出
                GPIO_Initure.Pull=GPIO_NOPULL;                       
                GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;                //高速
                GPIO_Initure.Alternate=GPIO_AF5_SPI1;        //复用为spi1
                HAL_GPIO_Init(GPIOA,&GPIO_Initure);                   //初始化PI       

    //片选信号 PA4
          GPIO_Initure.Pin= GPIO_PIN_4;                        //PA4
                GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;                //推挽输出
                GPIO_Initure.Pull=GPIO_NOPULL;                       
                GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;                //高速
                HAL_GPIO_Init(GPIOA,&GPIO_Initure);                   //初始化PA       
                SPI_CS_HIGH;   //片选取消
               
    //中断引脚  Pc4
    GPIO_Initure.Pin = GPIO_PIN_4;
    GPIO_Initure.Mode = GPIO_MODE_INPUT;       
                GPIO_Initure.Pull=GPIO_PULLDOWN;                       
                GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;                //高速
                HAL_GPIO_Init(GPIOC,&GPIO_Initure);                   //初始化PB       
          __HAL_SPI_ENABLE(&SPI1_Handler);    //启动SPI       

   SPI1_DMA_Config();
       
        }
}




void SPI1_DMA_Config(void)
{
         u8 res = HAL_ERROR;
          __HAL_RCC_DMA2_CLK_ENABLE();
       
          
    //rx DMA配置
    hdma_spi1_rx.Instance=DMA2_Stream2;                            //数据流选择
    hdma_spi1_rx.Init.Request=DMA_REQUEST_SPI1_RX;                        //通道选择
    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_HALFWORD;    //外设数据长度:8位
    hdma_spi1_rx.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD;       //存储器数据长度:8位
    hdma_spi1_rx.Init.Mode=DMA_NORMAL;                            //外设普通模式
    hdma_spi1_rx.Init.Priority=DMA_PRIORITY_VERY_HIGH;               //优先级 非常高.
          hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
               
    res = HAL_DMA_Init(&hdma_spi1_rx);
                __HAL_LINKDMA(&SPI1_Handler,hdmarx,hdma_spi1_rx);    //将DMA与SPI2联系起来(接受DMA)
       
       
           //tx
       
    //tx DMA配置
    hdma_spi1_tx.Instance=DMA2_Stream3;                            //数据流选择
    hdma_spi1_tx.Init.Request=DMA_REQUEST_SPI1_TX;                        //通道选择
    hdma_spi1_tx.Init.Direction=DMA_MEMORY_TO_PERIPH;               //外设到内存
    hdma_spi1_tx.Init.PeriphInc=DMA_PINC_DISABLE;                 //外设非增量模式
    hdma_spi1_tx.Init.MemInc=DMA_MINC_ENABLE;                     //存储器增量模式
    hdma_spi1_tx.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD;    //外设数据长度:16位
    hdma_spi1_tx.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD;       //存储器数据长度:16位
    hdma_spi1_tx.Init.Mode=DMA_NORMAL;                            //外设普通模式
    hdma_spi1_tx.Init.Priority=DMA_PRIORITY_VERY_HIGH;               //优先级 非常高.
                hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
       
    res = HAL_DMA_Init(&hdma_spi1_tx);
          __HAL_LINKDMA(&SPI1_Handler,hdmatx,hdma_spi1_tx);    //将DMA与SPI2联系起来(接受DMA)
       
       

                HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 1, 3);
                HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
               
                HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 1, 4);
                HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
       

}







最佳答案

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

问题已解决,把HAL库从V1.1.0更新到了V1.2.0问题解决
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

43

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
484
金钱
484
注册时间
2017-11-6
在线时间
162 小时
 楼主| 发表于 2018-3-5 14:26:44 | 显示全部楼层
问题已解决,把HAL库从V1.1.0更新到了V1.2.0问题解决
回复

使用道具 举报

21

主题

2205

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
5137
金钱
5137
注册时间
2014-8-26
在线时间
1316 小时
发表于 2018-3-5 18:33:36 | 显示全部楼层
帮顶。
回复

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2018-6-29
在线时间
8 小时
发表于 2018-7-9 20:49:57 | 显示全部楼层
先留一个……
回复

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2018-6-29
在线时间
8 小时
发表于 2018-7-10 18:38:48 | 显示全部楼层
我这样配置,使用HAL_SPI_Transmit_DMA会一直在忙,请问你有遇到过类似问题吗
回复

使用道具 举报

2

主题

43

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
484
金钱
484
注册时间
2017-11-6
在线时间
162 小时
 楼主| 发表于 2018-7-11 12:03:26 | 显示全部楼层
slh953172510 发表于 2018-7-10 18:38
我这样配置,使用HAL_SPI_Transmit_DMA会一直在忙,请问你有遇到过类似问题吗

遇到过 ,后面改用HAL_SPI_TransmitReceive_DMA就正常了
回复

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2018-6-29
在线时间
8 小时
发表于 2018-7-11 13:39:17 | 显示全部楼层
spica 发表于 2018-7-11 12:03
遇到过 ,后面改用HAL_SPI_TransmitReceive_DMA就正常了

可是我只需要发呀……用HAL_SPI_TransmitReceive_DMA如果从机没有发数据过来会不会有问题
回复

使用道具 举报

2

主题

43

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
484
金钱
484
注册时间
2017-11-6
在线时间
162 小时
 楼主| 发表于 2018-7-11 14:01:27 | 显示全部楼层
slh953172510 发表于 2018-7-11 13:39
可是我只需要发呀……用HAL_SPI_TransmitReceive_DMA如果从机没有发数据过来会不会有问题

SPI是全双工的  你在发的同时从机肯定有数据过来的  只不过你不关心丢弃掉了而已,了解一下SPI的工作机制你就明白了
回复

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2018-6-29
在线时间
8 小时
发表于 2018-7-11 14:58:10 | 显示全部楼层
spica 发表于 2018-7-11 14:01
SPI是全双工的  你在发的同时从机肯定有数据过来的  只不过你不关心丢弃掉了而已,了解一下SPI的工作机制 ...

嗯,现在是这样,如果我不使用DMA发送,只是用HAL_SPI_Transmit这个函数发送的话,是能够发过去的,但是使用DMA的话就只能发送一次数据(96k的数据),然后后面SPI就一直处于OVR状态。
回复

使用道具 举报

0

主题

91

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
261
金钱
261
注册时间
2017-7-19
在线时间
31 小时
发表于 2018-7-11 15:29:01 | 显示全部楼层
学习了学习了
回复

使用道具 举报

38

主题

116

帖子

0

精华

初级会员

Rank: 2

积分
126
金钱
126
注册时间
2016-2-24
在线时间
84 小时
发表于 2018-9-17 13:03:43 | 显示全部楼层
楼主,搞出来了么?我卡了好久,这里!
回复

使用道具 举报

38

主题

116

帖子

0

精华

初级会员

Rank: 2

积分
126
金钱
126
注册时间
2016-2-24
在线时间
84 小时
发表于 2018-10-6 14:06:10 | 显示全部楼层
spica 发表于 2018-3-5 14:26
问题已解决,把HAL库从V1.1.0更新到了V1.2.0问题解决

我 H7  SPI  DMA读的数据一直是0
回复

使用道具 举报

2

主题

43

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
484
金钱
484
注册时间
2017-11-6
在线时间
162 小时
 楼主| 发表于 2018-10-8 11:12:04 | 显示全部楼层
zhanjian 发表于 2018-10-6 14:06
我 H7  SPI  DMA读的数据一直是0

启用了cache要配合SCB_InvalidateDCache_by_Addr()这些函数使用,不然只有第一次能读到数据,后面全是0
回复

使用道具 举报

38

主题

116

帖子

0

精华

初级会员

Rank: 2

积分
126
金钱
126
注册时间
2016-2-24
在线时间
84 小时
发表于 2018-10-8 23:13:51 | 显示全部楼层
spica 发表于 2018-10-8 11:12
启用了cache要配合SCB_InvalidateDCache_by_Addr()这些函数使用,不然只有第一次能读到数据,后面全是0

SCB_InvalidateDCache
SCB_InvalidateDCache_by_Addr
SCB_CleanDCache
SCB_CleanDCache_by_Addr
SCB_DisableDCache();

IRAM2  打√

DMA只接受或者只发送,或者接收发送
都试过,配置也都尝试很多配合,就是不行!
回复

使用道具 举报

0

主题

91

帖子

0

精华

初级会员

Rank: 2

积分
177
金钱
177
注册时间
2018-9-27
在线时间
15 小时
发表于 2018-10-10 10:31:47 | 显示全部楼层
帮顶
回复

使用道具 举报

16

主题

38

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
241
金钱
241
注册时间
2014-7-14
在线时间
40 小时
发表于 2019-2-21 18:05:04 | 显示全部楼层
楼主咋样了,我跟你好像一样的问题,都调一周了,没有进展
回复

使用道具 举报

3

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2019-10-23
在线时间
42 小时
发表于 2020-5-6 18:26:15 | 显示全部楼层
兄台设置过关于h743的spi主从机通信吗?一般的轮询和中断方式是可以做出来的,不过我用dma的方式出现了问题,请问兄台做过主从机通信的例子吗?
回复

使用道具 举报

3

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2019-10-23
在线时间
42 小时
发表于 2020-5-6 21:37:33 | 显示全部楼层
楼主,请问方便把主从机中主函数中的使用的
  1.         if(HAL_SPI_TransmitReceive_DMA(&hspi2, (uint8_t *)SpiTxBuffer, (uint8_t *)SpiRxBuffer, BUFFERSIZE) != HAL_OK)
  2.         {
  3.                         // printf("error\t\n");
  4.                 Error_Handler();
  5.         }
复制代码

这些东西贴出来吗?
回复

使用道具 举报

11

主题

55

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
327
金钱
327
注册时间
2017-9-10
在线时间
80 小时
发表于 2020-7-23 15:11:22 | 显示全部楼层
slh953172510 发表于 2018-7-11 14:58
嗯,现在是这样,如果我不使用DMA发送,只是用HAL_SPI_Transmit这个函数发送的话,是能够发过去的,但是 ...

还在吗?想问下最后解决了吗?
回复

使用道具 举报

10

主题

97

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
490
金钱
490
注册时间
2019-12-6
在线时间
153 小时
发表于 2020-10-13 14:22:26 | 显示全部楼层
spica 发表于 2018-3-5 14:26
问题已解决,把HAL库从V1.1.0更新到了V1.2.0问题解决

完整例程能否给下
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-4-29 22:59

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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