硬汉嵌入式论坛

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

[SPI/QSPI] STM32H743 SPI3问题求解

[复制链接]

6

主题

21

回帖

39

积分

新手上路

积分
39
发表于 2024-1-16 15:36:22 | 显示全部楼层 |阅读模式
程序如下当将配置文件中的SPI3改为SPI1后HAL_SPI_TransmitReceive能够正常执行,当为SPI3时HAL_SPI_TransmitReceive就返回错误

#define SPIx                                                        SPI3
#define SPIx_CLK_ENABLE()                                __HAL_RCC_SPI3_CLK_ENABLE()
#define DMAx_CLK_ENABLE()                                __HAL_RCC_DMA2_CLK_ENABLE()

#define SPIx_FORCE_RESET()                                __HAL_RCC_SPI3_FORCE_RESET()
#define SPIx_RELEASE_RESET()                        __HAL_RCC_SPI3_RELEASE_RESET()

#define SPIx_SCK_CLK_ENABLE()                        __HAL_RCC_GPIOB_CLK_ENABLE()
#define SPIx_SCK_GPIO                                        GPIOB
#define SPIx_SCK_PIN                                        GPIO_PIN_3
#define SPIx_SCK_AF                                                GPIO_AF5_SPI3

#define SPIx_MISO_CLK_ENABLE()                        __HAL_RCC_GPIOB_CLK_ENABLE()
#define SPIx_MISO_GPIO                                        GPIOB
#define SPIx_MISO_PIN                                         GPIO_PIN_4
#define SPIx_MISO_AF                                        GPIO_AF5_SPI3

#define SPIx_MOSI_CLK_ENABLE()                        __HAL_RCC_GPIOB_CLK_ENABLE()
#define SPIx_MOSI_GPIO                                        GPIOB
#define SPIx_MOSI_PIN                                         GPIO_PIN_5
#define SPIx_MOSI_AF                                        GPIO_AF5_SPI3

#define ADE7953SPIx_CS_CLK_ENABLE()                __HAL_RCC_GPIOE_CLK_ENABLE()
#define ADE7953SPIx_CS_GPIO                                GPIOE
#define ADE7953SPIx_CS_PIN                                 GPIO_PIN_0

#define ADE7953SPIx_RST_CLK_ENABLE()        __HAL_RCC_GPIOE_CLK_ENABLE()
#define ADE7953SPIx_RST_GPIO                        GPIOE
#define ADE7953SPIx_RST_PIN                         GPIO_PIN_1

#define SPIx_TX_DMA_STREAM              DMA2_Stream3
#define SPIx_RX_DMA_STREAM              DMA2_Stream2

#define SPIx_TX_DMA_REQUEST             DMA_REQUEST_SPI3_TX
#define SPIx_RX_DMA_REQUEST             DMA_REQUEST_SPI3_RX

#define SPIx_DMA_TX_IRQn                DMA2_Stream3_IRQn
#define SPIx_DMA_RX_IRQn                DMA2_Stream2_IRQn

#define SPIx_DMA_TX_IRQHandler          DMA2_Stream3_IRQHandler
#define SPIx_DMA_RX_IRQHandler          DMA2_Stream2_IRQHandler

#define SPIx_IRQn                       SPI3_IRQn
#define SPIx_IRQHandler                 SPI3_IRQHandler

#define   AD7953_CS0()                                        HAL_GPIO_WritePin(GPIOE,GPIO_PIN_0,GPIO_PIN_RESET)
#define   AD7953_CS1()                                        HAL_GPIO_WritePin(GPIOE,GPIO_PIN_0,GPIO_PIN_SET)
#define   AD7953_RST0()                                        HAL_GPIO_WritePin(GPIOE,GPIO_PIN_1,GPIO_PIN_RESET)
#define   AD7953_RST1()                                        HAL_GPIO_WritePin(GPIOE,GPIO_PIN_1,GPIO_PIN_SET)

enum {
        TRANSFER_WAIT,
        TRANSFER_COMPLETE,
        TRANSFER_ERROR
};

void delay(uint32_t us)
{
        uint32_t i=0;
        for(i=us;i>0;i--)
        {
                __NOP();
        }
}
/*
*********************************************************************************************************
*                                                   变量
*********************************************************************************************************
*/
static SPI_HandleTypeDef hspi = {0};
static DMA_HandleTypeDef hdma_tx;
static DMA_HandleTypeDef hdma_rx;
static uint32_t s_BaudRatePrescaler;
static uint32_t s_CLKPhase;
static uint32_t s_CLKPolarity;
uint32_t g_spiLen;      
uint8_t  g_spi_busy; /* SPI忙状态,0表示不忙,1表示忙 */
__IO uint32_t wTransferState = TRANSFER_WAIT;


/* 查询模式 */
#if defined (USE_SPI_POLL)

uint8_t g_spiTxBuf[SPI_BUFFER_SIZE];  
uint8_t g_spiRxBuf[SPI_BUFFER_SIZE];

/* 中断模式 */
#elif defined (USE_SPI_INT)

uint8_t g_spiTxBuf[SPI_BUFFER_SIZE];   
uint8_t g_spiRxBuf[SPI_BUFFER_SIZE];

/* DMA模式使用的SRAM4 */
#elif defined (USE_SPI_DMA)
    #if defined ( __CC_ARM )    /* IAR *******/
        __attribute__((section (".RAM_D3"))) uint8_t g_spiTxBuf[SPI_BUFFER_SIZE];   
        __attribute__((section (".RAM_D3"))) uint8_t g_spiRxBuf[SPI_BUFFER_SIZE];
    #elif defined (__ICCARM__)   /* MDK ********/
        #pragma location = ".RAM_D3"
        uint8_t g_spiTxBuf[SPI_BUFFER_SIZE];   
        #pragma location = ".RAM_D3"
        uint8_t g_spiRxBuf[SPI_BUFFER_SIZE];
    #endif
#endif


/*
*********************************************************************************************************
*        函 数 名: bsp_InitSPIBus
*        功能说明: 配置SPI总线。
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitSPIBus(void)
{      
        g_spi_busy = 0;
      
        bsp_InitSPIParam(SPI_BAUDRATEPRESCALER_64, SPI_PHASE_2EDGE, SPI_POLARITY_HIGH);
}

/*
*********************************************************************************************************
*        函 数 名: bsp_InitSPIParam
*        功能说明: 配置SPI总线参数,时钟分频,时钟相位和时钟极性。
*        形    参: _BaudRatePrescaler  SPI总线时钟分频设置,支持的参数如下:
*                                 SPI_BAUDRATEPRESCALER_2    2分频
*                                 SPI_BAUDRATEPRESCALER_4    4分频
*                                 SPI_BAUDRATEPRESCALER_8    8分频
*                                 SPI_BAUDRATEPRESCALER_16   16分频
*                                 SPI_BAUDRATEPRESCALER_32   32分频
*                                 SPI_BAUDRATEPRESCALER_64   64分频
*                                 SPI_BAUDRATEPRESCALER_128  128分频
*                                 SPI_BAUDRATEPRESCALER_256  256分频
*                                                        
*             _CLKPhase           时钟相位,支持的参数如下:
*                                 SPI_PHASE_1EDGE     SCK引脚的第1个边沿捕获传输的第1个数据
*                                 SPI_PHASE_2EDGE     SCK引脚的第2个边沿捕获传输的第1个数据
*                                 
*             _CLKPolarity        时钟极性,支持的参数如下:
*                                 SPI_POLARITY_LOW    SCK引脚在空闲状态处于低电平
*                                 SPI_POLARITY_HIGH   SCK引脚在空闲状态处于高电平
*
*        返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitSPIParam(uint32_t _BaudRatePrescaler, uint32_t _CLKPhase, uint32_t _CLKPolarity)
{
        /* 提高执行效率,只有在SPI硬件参数发生变化时,才执行HAL_Init */
        if (s_BaudRatePrescaler == _BaudRatePrescaler && s_CLKPhase == _CLKPhase && s_CLKPolarity == _CLKPolarity)
        {               
                return;
        }

        s_BaudRatePrescaler = _BaudRatePrescaler;      
        s_CLKPhase = _CLKPhase;
        s_CLKPolarity = _CLKPolarity;
      
        /* 设置SPI参数 */
        hspi.Instance               = SPIx;                   /* 例化SPI */
        hspi.Init.BaudRatePrescaler = _BaudRatePrescaler;     /* 设置波特率 */
        hspi.Init.Direction         = SPI_DIRECTION_2LINES;   /* 全双工 */
        hspi.Init.CLKPhase          = _CLKPhase;              /* 配置时钟相位 */
        hspi.Init.CLKPolarity       = _CLKPolarity;           /* 配置时钟极性 */
        hspi.Init.DataSize          = SPI_DATASIZE_8BIT;      /* 设置数据宽度 */
        hspi.Init.FirstBit          = SPI_FIRSTBIT_MSB;       /* 数据传输先传高位 */
        hspi.Init.TIMode            = SPI_TIMODE_DISABLE;     /* 禁止TI模式  */
        hspi.Init.CRCCalculation    = SPI_CRCCALCULATION_DISABLE; /* 禁止CRC */
        hspi.Init.CRCPolynomial     = 7;                       /* 禁止CRC后,此位无效 */
        hspi.Init.CRCLength         = SPI_CRC_LENGTH_8BIT;     /* 禁止CRC后,此位无效 */
        hspi.Init.NSS               = SPI_NSS_SOFT;               /* 使用软件方式管理片选引脚 */
        hspi.Init.FifoThreshold     = SPI_FIFO_THRESHOLD_01DATA;  /* 设置FIFO大小是一个数据项 */
        hspi.Init.NSSPMode          = SPI_NSS_PULSE_DISABLE;      /* 禁止脉冲输出 */
        hspi.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; /* 禁止SPI后,SPI相关引脚保持当前状态 */  
        hspi.Init.Mode                                  = SPI_MODE_MASTER;            /* SPI工作在主控模式 */

        /* 复位配置 */
        if (HAL_SPI_DeInit(&hspi) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }      

        /* 初始化配置 */
        if (HAL_SPI_Init(&hspi) != HAL_OK)
        {
                Error_Handler(__FILE__, __LINE__);
        }      
}

/*
*********************************************************************************************************
*        函 数 名: bsp_InitSPIParam
*        功能说明: 配置SPI总线时钟,GPIO,中断,DMA等
*        形    参: SPI_HandleTypeDef 类型指针变量
*        返 回 值: 无
*********************************************************************************************************
*/
void HAL_SPI_MspInit(SPI_HandleTypeDef *_hspi)
{
        /* 配置 SPI总线GPIO : SCK MOSI MISO */
        {
                GPIO_InitTypeDef  GPIO_InitStruct;
                       
                /* SPI和GPIP时钟 */
                SPIx_SCK_CLK_ENABLE();
                SPIx_MISO_CLK_ENABLE();
                SPIx_MOSI_CLK_ENABLE();
                ADE7953SPIx_CS_CLK_ENABLE();
                SPIx_CLK_ENABLE();

                /* SPI SCK */
                GPIO_InitStruct.Pin       = SPIx_SCK_PIN;
                GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
                GPIO_InitStruct.Pull      = GPIO_PULLUP;
                GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_MEDIUM;
                GPIO_InitStruct.Alternate = SPIx_SCK_AF;
                HAL_GPIO_Init(SPIx_SCK_GPIO, &GPIO_InitStruct);

                /* SPI MISO */
                GPIO_InitStruct.Pin = SPIx_MISO_PIN;
                GPIO_InitStruct.Alternate = SPIx_MISO_AF;
                HAL_GPIO_Init(SPIx_MISO_GPIO, &GPIO_InitStruct);

                /* SPI MOSI */
                GPIO_InitStruct.Pin = SPIx_MOSI_PIN;
                GPIO_InitStruct.Alternate = SPIx_MOSI_AF;
                HAL_GPIO_Init(SPIx_MOSI_GPIO, &GPIO_InitStruct);
               
                GPIO_InitStruct.Pin       = ADE7953SPIx_CS_PIN|ADE7953SPIx_RST_PIN;
                GPIO_InitStruct.Mode      = GPIO_MODE_OUTPUT_PP;
                GPIO_InitStruct.Pull      = GPIO_PULLUP;
                GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_MEDIUM;
                HAL_GPIO_Init(ADE7953SPIx_CS_GPIO, &GPIO_InitStruct);
                delay(10000);
                AD7953_RST0();
                delay(10000);
                AD7953_RST1();
        }

        /* 配置DMA和NVIC */
        #ifdef USE_SPI_DMA
        {
                /* 使能DMA时钟 */
                DMAx_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(_hspi, 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(_hspi, hdmarx, hdma_rx);      

                /* 配置DMA发送中断 */
                HAL_NVIC_SetPriority(SPIx_DMA_TX_IRQn, 1, 0);
                HAL_NVIC_EnableIRQ(SPIx_DMA_TX_IRQn);
               
                /* 配置DMA接收中断 */
                HAL_NVIC_SetPriority(SPIx_DMA_RX_IRQn, 1, 0);
                HAL_NVIC_EnableIRQ(SPIx_DMA_RX_IRQn);
               
                /* 配置SPI中断 */
                HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0);
                HAL_NVIC_EnableIRQ(SPIx_IRQn);
        }
        #endif
      
        #ifdef USE_SPI_INT
                /* 配置SPI中断优先级并使能中断 */
                HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0);
                HAL_NVIC_EnableIRQ(SPIx_IRQn);
        #endif
}
      
/*
*********************************************************************************************************
*        函 数 名: bsp_spiTransfer
*        功能说明: 启动数据传输
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
void bsp_spiTransfer(void)
{
        if (g_spiLen > SPI_BUFFER_SIZE)
        {
                return;
        }
      
        /* DMA方式传输 */
#ifdef USE_SPI_DMA
        wTransferState = TRANSFER_WAIT;
      
        if(HAL_SPI_TransmitReceive_DMA(&hspi, (uint8_t*)g_spiTxBuf, (uint8_t *)g_spiRxBuf, g_spiLen) != HAL_OK)      
        {
                Error_Handler(__FILE__, __LINE__);
        }
      
        while (wTransferState == TRANSFER_WAIT)
        {
                ;
        }
#endif

        /* 中断方式传输 */      
#ifdef USE_SPI_INT
        wTransferState = TRANSFER_WAIT;

        if(HAL_SPI_TransmitReceive_IT(&hspi, (uint8_t*)g_spiTxBuf, (uint8_t *)g_spiRxBuf, g_spiLen) != HAL_OK)      
        {
                Error_Handler(__FILE__, __LINE__);
        }
      
        while (wTransferState == TRANSFER_WAIT)
        {
                ;
        }
#endif

        /* 查询方式传输 */      
#ifdef USE_SPI_POLL
        g_spiTxBuf[0]=0xAA;
        g_spiTxBuf[0]=0xBB;
        g_spiTxBuf[0]=0xCC;
        g_spiTxBuf[0]=0xDD;
    AD7953_CS0();
        if(HAL_SPI_TransmitReceive(&hspi, (uint8_t*)g_spiTxBuf, (uint8_t *)g_spiRxBuf, 4, 1000) != HAL_OK)      
        {
                Error_Handler(__FILE__, __LINE__);
        }      
        AD7953_CS1();
#endif
}

[url=]使用特权[/url]
[url=]更多操作[/url]




回复

使用道具 举报

6

主题

21

回帖

39

积分

新手上路

积分
39
 楼主| 发表于 2024-1-16 15:38:11 | 显示全部楼层
问题找到GPIO_Initure.Alternate=GPIO_AF6_SPI3;           //复用为SPI3这问题
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106731
QQ
发表于 2024-1-17 08:27:38 | 显示全部楼层
xad74 发表于 2024-1-16 15:38
问题找到GPIO_Initure.Alternate=GPIO_AF6_SPI3;           //复用为SPI3这问题

谢谢告知最终原因。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-2 22:58 , Processed in 0.345853 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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