硬汉嵌入式论坛

 找回密码
 立即注册
查看: 4080|回复: 8
收起左侧

[SPI/QSPI] 关于SPI传输时间问题

[复制链接]

12

主题

98

回帖

134

积分

初级会员

积分
134
发表于 2020-8-24 12:54:22 | 显示全部楼层 |阅读模式
本帖最后由 yuangt 于 2020-8-24 12:57 编辑

      如题 ,用的是stm32h750芯片,主频480M的,作一个spi的中断传输9个字节,程序如下:
                                GPIOD->BSRRH = GPIO_PIN_7;               
                                wTransferState = TRANSFER_WAIT;
                                if(HAL_SPI_TransmitReceive_IT(&hspi6, (uint8_t*buf0, (uint8_t *)buf0, 9) != HAL_OK)        
                                {
                                        Error_Handler(__FILE__, __LINE__);
                                }
                                while (wTransferState == TRANSFER_WAIT)
                                {
                                        ;
                                }
                                GPIOD->BSRRL = GPIO_PIN_7;               

用示波器量CS、SCLK管脚的波形如下:
cec721a34105d957f45ada5afa457b2.jpg
其中黄色线为CS脚,蓝色为SCLK脚,通过sclk可以看到9个字节的传输时间实际只有2us不到,但是传输前的准备时间以及传输完成成的时间(看黄线)实际却花了14us, 这样不是传输效率太低了吗?
有什么办法让这边传输完成后就可以马上传输下一数据包呢,而不用等好几us的时间
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107604
QQ
发表于 2020-8-24 14:23:45 | 显示全部楼层
SPI DMA
回复

使用道具 举报

12

主题

98

回帖

134

积分

初级会员

积分
134
 楼主| 发表于 2020-8-24 16:17:37 | 显示全部楼层
用DMA就可以了吗?为什么这个中断发送要这么长时间呢?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107604
QQ
发表于 2020-8-24 16:32:15 | 显示全部楼层
如果你用的硬件片选的话,有个参数可以配置:插入到 NSS 有效边沿和第一个数据开始之间的额外延迟。两个数据之间的延迟也可以配置

之前搞DAC856X的SPI DMA倒腾过一次

QQ截图20200824162341.png
回复

使用道具 举报

12

主题

98

回帖

134

积分

初级会员

积分
134
 楼主| 发表于 2020-8-24 20:28:09 | 显示全部楼层

请问,spi6的DMA是下面这样配置吗?




#define SPIx_TX_DMA_STREAM               DMA2_Stream5
#define SPIx_RX_DMA_STREAM               DMA2_Stream6

#define SPIx_TX_DMA_REQUEST              BDMA_REQUEST_SPI6_TX
#define SPIx_RX_DMA_REQUEST              BDMA_REQUEST_SPI6_RX

#define SPIx_DMA_TX_IRQn                 DMA2_Stream5_IRQn
#define SPIx_DMA_RX_IRQn                 DMA2_Stream6_IRQn

#define SPIx_DMA_TX_IRQHandler           DMA2_Stream5_IRQHandler
#define SPIx_DMA_RX_IRQHandler           DMA2_Stream6_IRQHandler

#define SPIx_IRQn                        SPI6_IRQn
#define SPIx_IRQHandler                  SPI6_IRQHandler
回复

使用道具 举报

12

主题

98

回帖

134

积分

初级会员

积分
134
 楼主| 发表于 2020-8-24 20:38:39 | 显示全部楼层
硬汉兄,看看我的spi6配置有没有问题,调了一天没调出来

static DMA_HandleTypeDef hdma_tx;
static DMA_HandleTypeDef hdma_rx;

#define SPIx_TX_DMA_STREAM               DMA2_Stream5
#define SPIx_RX_DMA_STREAM               DMA2_Stream6

#define SPIx_TX_DMA_REQUEST              BDMA_REQUEST_SPI6_TX
#define SPIx_RX_DMA_REQUEST              BDMA_REQUEST_SPI6_RX

#define SPIx_DMA_TX_IRQn                 DMA2_Stream5_IRQn
#define SPIx_DMA_RX_IRQn                 DMA2_Stream6_IRQn

#define SPIx_DMA_TX_IRQHandler           DMA2_Stream5_IRQHandler
#define SPIx_DMA_RX_IRQHandler           DMA2_Stream6_IRQHandler

#define SPIx_IRQn                        SPI6_IRQn
#define SPIx_IRQHandler                  SPI6_IRQHandler


/* SPI6 init function */
void MX_SPI6_Init(void)
{
//        u8        i;
//        u32 tempreg=0;
    __HAL_RCC_SPI6_CLK_ENABLE();


        GPIO_Set(GPIOB,PIN3|PIN4|PIN5,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_FAST,GPIO_PUPD_PU);
        GPIO_AF_Set(GPIOB,3,8);        //PA5,AF5
        GPIO_AF_Set(GPIOB,4,8);        //PA5,AF5
        GPIO_AF_Set(GPIOB,5,8);        //PA5,AF5
//         GPIO_AF_Set(GPIOE,6,8);        //PA6,AF5

    /* SPI6 interrupt Init */
        MY_NVIC_Init(2,2,SPI6_IRQn,2);//组2,最低优先级        
//    HAL_NVIC_SetPriority(SPI4_IRQn, 4, 4);
//    HAL_NVIC_EnableIRQ(SPI4_IRQn);

        /* SPI6 parameter configuration*/
        hspi6.Instance = SPI6;
        hspi6.Init.Mode = SPI_MODE_MASTER;//SPI_MODE_SLAVE;
        hspi6.Init.Direction = SPI_DIRECTION_2LINES;
        hspi6.Init.DataSize = SPI_DATASIZE_8BIT;
        hspi6.Init.CLKPolarity = SPI_POLARITY_HIGH;//SPI_POLARITY_LOW;  SPI_POLARITY_HIGH
        hspi6.Init.CLKPhase = SPI_PHASE_2EDGE;
        hspi6.Init.NSS = SPI_NSS_SOFT;//SPI_NSS_HARD_INPUT;
        hspi6.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
        hspi6.Init.FirstBit = SPI_FIRSTBIT_MSB;
        hspi6.Init.TIMode = SPI_TIMODE_DISABLE;
        hspi6.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
        hspi6.Init.CRCPolynomial = 7;
        if (HAL_SPI_Init(&hspi6) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }

       
       
                /* 使能DMA时钟 */
                __HAL_RCC_DMA2_CLK_ENABLE();      

                /* SPI DMA发送配置 */               
                hdma_tx.Instance                 = SPIx_TX_DMA_STREAM;      /* 例化使用的DMA数据流 */
                hdma_tx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;    /* 禁止FIFO*/
                hdma_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL; /* 禁止FIFO此位不起作用,用于设置阀值 */
                hdma_tx.Init.MemBurst            = DMA_MBURST_SINGLE;            /* 禁止FIFO此位不起作用,用于存储器突发 */
                hdma_tx.Init.PeriphBurst         = DMA_PBURST_SINGLE;            /* 禁止FIFO此位不起作用,用于外设突发 */
                hdma_tx.Init.Request             = SPIx_TX_DMA_REQUEST;     /* 请求类型 */  
                hdma_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;    /* 传输方向是从存储器到外设 */  
                hdma_tx.Init.PeriphInc           = DMA_PINC_DISABLE;        /* 外设地址自增禁止 */
                hdma_tx.Init.MemInc              = DMA_MINC_ENABLE;         /* 存储器地址自增使能 */  
                hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;     /* 外设数据传输位宽选择字节,即8bit */
                hdma_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;     /* 存储器数据传输位宽选择字节,即8bit */   
                hdma_tx.Init.Mode                = DMA_NORMAL;              /* 正常模式 */
                hdma_tx.Init.Priority            = DMA_PRIORITY_LOW;        /* 优先级低 */

                 /* 复位DMA */
                if(HAL_DMA_DeInit(&hdma_tx) != HAL_OK)
                {
                        Error_Handler(__FILE__, __LINE__);     
                }
               
                 /* 初始化DMA */
                if(HAL_DMA_Init(&hdma_tx) != HAL_OK)
                {
                        Error_Handler(__FILE__, __LINE__);     
                }

                /* 关联DMA句柄到SPI */
                __HAL_LINKDMA(&hspi6, hdmatx, hdma_tx);       


                /* SPI DMA接收配置 */       
                hdma_rx.Instance                 = SPIx_RX_DMA_STREAM;     /* 例化使用的DMA数据流 */
                hdma_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;   /* 禁止FIFO*/
                hdma_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;/* 禁止FIFO此位不起作用,用于设置阀值 */
                hdma_rx.Init.MemBurst            = DMA_MBURST_SINGLE;           /* 禁止FIFO此位不起作用,用于存储器突发 */
                hdma_rx.Init.PeriphBurst         = DMA_PBURST_SINGLE;           /* 禁止FIFO此位不起作用,用于外设突发 */
                hdma_rx.Init.Request             = SPIx_RX_DMA_REQUEST;    /* 请求类型 */  
                hdma_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;   /* 传输方向从外设到存储器 */  
                hdma_rx.Init.PeriphInc           = DMA_PINC_DISABLE;       /* 外设地址自增禁止 */   
                hdma_rx.Init.MemInc              = DMA_MINC_ENABLE;        /* 存储器地址自增使能 */   
                hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;    /* 外设数据传输位宽选择字节,即8bit */
                hdma_rx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;    /* 存储器数据传输位宽选择字节,即8bit */   
                hdma_rx.Init.Mode                = DMA_NORMAL;             /* 正常模式 */
                hdma_rx.Init.Priority            = DMA_PRIORITY_HIGH;      /* 优先级低 */

                 /* 复位DMA */
                if(HAL_DMA_DeInit(&hdma_rx) != HAL_OK)
                {
                        Error_Handler(__FILE__, __LINE__);     
                }
               
                 /* 初始化DMA */
                if(HAL_DMA_Init(&hdma_rx) != HAL_OK)
                {
                        Error_Handler(__FILE__, __LINE__);     
                }

                /* 关联DMA句柄到SPI */
           __HAL_LINKDMA(&hspi6, hdmarx, hdma_rx);       

               
                /* 配置DMA接收中断 */
                HAL_NVIC_SetPriority(SPIx_DMA_RX_IRQn, 1, 0);
                HAL_NVIC_EnableIRQ(SPIx_DMA_RX_IRQn);

               
                /* 配置DMA发送中断 */
                HAL_NVIC_SetPriority(SPIx_DMA_TX_IRQn, 1, 0);
                HAL_NVIC_EnableIRQ(SPIx_DMA_TX_IRQn);
               

               
                /* 配置SPI中断 */
                HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0);
                HAL_NVIC_EnableIRQ(SPIx_IRQn);
       

}



        void DMA2_Stream6_IRQHandler(void)
        {
                HAL_DMA_IRQHandler(hspi6.hdmarx);
        }

        void DMA2_Stream5_IRQHandler(void)
        {
                HAL_DMA_IRQHandler(hspi6.hdmatx);
        }
       
        void SPI6_IRQHandler(void)
        {
                HAL_SPI_IRQHandler(&hspi6);
        }

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
//        HAL_SPI_Receive_IT(&hspi4, tt3, 1);
//        HAL_SPI_Receive(&hspi4, tt3, 1,100);
}

/*
*********************************************************************************************************
*        函 数 名: HAL_SPI_TxRxCpltCallback,HAL_SPI_ErrorCallback
*        功能说明: SPI数据传输完成回调和传输错误回调
*        形    参: SPI_HandleTypeDef 类型指针变量
*        返 回 值: 无
*********************************************************************************************************
*/
u8        wTransferState = 0;
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
        wTransferState = TRANSFER_COMPLETE;
}


void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
        wTransferState = TRANSFER_ERROR;
}
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107604
QQ
发表于 2020-8-25 08:55:54 | 显示全部楼层
yuangt 发表于 2020-8-24 20:38
硬汉兄,看看我的spi6配置有没有问题,调了一天没调出来

static DMA_HandleTypeDef hdma_tx;

没看出来有什么问题。
回复

使用道具 举报

12

主题

98

回帖

134

积分

初级会员

积分
134
 楼主| 发表于 2020-8-25 09:20:37 | 显示全部楼层
eric2013 发表于 2020-8-25 08:55
没看出来有什么问题。

调试进去看时,用示波器量就一直没有数据输出,启动传输命令有什么不一样吗,看你的外部flash程序里面,好像每次启动都要重新去设置spi,如下:
void sf_SetCS(uint8_t _Level)
{
        if (_Level == 0)
        {
                bsp_SpiBusEnter();       
                bsp_InitSPIParam(SPI_BAUDRATEPRESCALER_4, SPI_PHASE_1EDGE, SPI_POLARITY_LOW);               
                SF_CS_0();
        }
        else
        {               
                SF_CS_1();       
                bsp_SpiBusExit();               
        }
}
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107604
QQ
发表于 2020-8-25 09:43:12 | 显示全部楼层
yuangt 发表于 2020-8-25 09:20
调试进去看时,用示波器量就一直没有数据输出,启动传输命令有什么不一样吗,看你的外部flash程序里面, ...

我们这里是为了外接各种配置的SPI设备
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-6-7 23:09 , Processed in 0.189744 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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