xad74 发表于 2024-1-16 15:36:22

STM32H743 SPI3问题求解


程序如下当将配置文件中的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_tg_spi_busy; /* SPI忙状态,0表示不忙,1表示忙 */
__IO uint32_t wTransferState = TRANSFER_WAIT;


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

uint8_t g_spiTxBuf;
uint8_t g_spiRxBuf;

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

uint8_t g_spiTxBuf;   
uint8_t g_spiRxBuf;

/* DMA模式使用的SRAM4 */
#elif defined (USE_SPI_DMA)
    #if defined ( __CC_ARM )    /* IAR *******/
      __attribute__((section (".RAM_D3"))) uint8_t g_spiTxBuf;   
      __attribute__((section (".RAM_D3"))) uint8_t g_spiRxBuf;
    #elif defined (__ICCARM__)   /* MDK ********/
      #pragma location = ".RAM_D3"
      uint8_t g_spiTxBuf;   
      #pragma location = ".RAM_D3"
      uint8_t g_spiRxBuf;
    #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总线参数,时钟分频,时钟相位和时钟极性。
*      形    参: _BaudRatePrescalerSPI总线时钟分频设置,支持的参数如下:
*                                 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_128128分频
*                                 SPI_BAUDRATEPRESCALER_256256分频
*                                                      
*             _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_InitTypeDefGPIO_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=0xAA;
      g_spiTxBuf=0xBB;
      g_spiTxBuf=0xCC;
      g_spiTxBuf=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
}


使用特权更多操作




xad74 发表于 2024-1-16 15:38:11

问题找到GPIO_Initure.Alternate=GPIO_AF6_SPI3;         //复用为SPI3这问题

eric2013 发表于 2024-1-17 08:27:38

xad74 发表于 2024-1-16 15:38
问题找到GPIO_Initure.Alternate=GPIO_AF6_SPI3;         //复用为SPI3这问题

谢谢告知最终原因。
页: [1]
查看完整版本: STM32H743 SPI3问题求解