| 使用SPI CRC校验功能,DMA发送和接收,如果是CRC 8位校验没有问题,改成16位就发生接收数据错误,跟踪调试是进入到SPI_DMAReceiveCplt函数执行到SPI_WaitFlagStateUntilTimeout判断RXNE标志没有置起,记录为CRC错误 有谁用过这个功能吗?求指点!!! if (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT) { if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) { /* Error on the CRC reception */ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); } /* Read 8bit CRC again in case of 16bit CRC in 8bit Data mode */ READ_REG(*(__IO uint8_t *)&hspi->Instance->DR); } 代码配置如下:SPI半双工传输 spi主机配置 hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_1LINE; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT;//SPI_NSS_HARD_OUTPUT;// hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_ENABLE; hspi1.Init.CRCPolynomial = 7; hspi1.Init.CRCLength = SPI_CRC_LENGTH_16BIT; hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } spi从机配置 hspi2.Instance = SPI2; hspi2.Init.Mode = SPI_MODE_SLAVE; hspi2.Init.Direction = SPI_DIRECTION_1LINE; hspi2.Init.DataSize = SPI_DATASIZE_8BIT; hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; hspi2.Init.NSS = SPI_NSS_SOFT;//SPI_NSS_HARD_INPUT;// hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi2.Init.TIMode = SPI_TIMODE_DISABLE; hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_ENABLE; hspi2.Init.CRCPolynomial = 7; hspi2.Init.CRCLength = SPI_CRC_LENGTH_16BIT;// hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; if (HAL_SPI_Init(&hspi2) != HAL_OK) { Error_Handler(); } DMA配置 /* SPI1 DMA Init */ /* SPI1_TX Init */ hdma_spi1_tx.Instance = DMA1_Channel1; 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_BYTE;//DMA_PDATAALIGN_HALFWORD;// hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;//DMA_MDATAALIGN_HALFWORD;// hdma_spi1_tx.Init.Mode = DMA_NORMAL; hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(hspi,hdmatx,hdma_spi1_tx); /* SPI2_RX Init */ hdma_spi2_rx.Instance = DMA1_Channel3; hdma_spi2_rx.Init.Request = DMA_REQUEST_SPI2_RX; hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;//DMA_PDATAALIGN_HALFWORD;// hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;//DMA_MDATAALIGN_HALFWORD;// hdma_spi2_rx.Init.Mode = DMA_NORMAL; hdma_spi2_rx.Init.Priority = DMA_PRIORITY_HIGH; if (HAL_DMA_Init(&hdma_spi2_rx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(hspi,hdmarx,hdma_spi2_rx); 主函数调用: if (HAL_SPI_Receive_DMA(&hspi2,(uint8_t *)spisalver_receive_array, 10) != HAL_OK) { /* Transfer error in transmission process */ Error_Handler(); } if (HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *)spimater_send_array,10) != HAL_OK) { /* Transfer error in transmission process */ Error_Handler(); } |
基于你的反馈,我找到STM32G0开发板做了验证测试。使用SPI1—halfduplex-maseter,SPI2—halfduplex-slave ,主发从收进行测试。 开启crc与否是没有问题的。 当然,我用只发/只收也测试过,CRC选择8位或16位都没有碰到问题。 HAL_SPI_Receive_DMA(&hspi2,RxData, 5); HAL_SPI_Transmit_DMA(&hspi1,TxData, 5); 参考配置代码如下: static void MX_SPI1_Init(void) { /* USER CODE BEGIN SPI1_Init 0 */ /* USER CODE END SPI1_Init 0 */ /* USER CODE BEGIN SPI1_Init 1 */ /* USER CODE END SPI1_Init 1 */ /* SPI1 parameter configuration*/ hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_1LINE; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_ENABLE; hspi1.Init.CRCPolynomial = 7; hspi1.Init.CRCLength = SPI_CRC_LENGTH_16BIT; hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SPI1_Init 2 */ /* USER CODE END SPI1_Init 2 */ } static void MX_SPI2_Init(void) { /* USER CODE BEGIN SPI2_Init 0 */ /* USER CODE END SPI2_Init 0 */ /* USER CODE BEGIN SPI2_Init 1 */ /* USER CODE END SPI2_Init 1 */ /* SPI2 parameter configuration*/ hspi2.Instance = SPI2; hspi2.Init.Mode = SPI_MODE_SLAVE; hspi2.Init.Direction = SPI_DIRECTION_1LINE; hspi2.Init.DataSize = SPI_DATASIZE_8BIT; hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; hspi2.Init.NSS = SPI_NSS_SOFT; hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi2.Init.TIMode = SPI_TIMODE_DISABLE; hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_ENABLE; hspi2.Init.CRCPolynomial = 7; hspi2.Init.CRCLength = SPI_CRC_LENGTH_16BIT; hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; if (HAL_SPI_Init(&hspi2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SPI2_Init 2 */ /* USER CODE END SPI2_Init 2 */ } //DMA configuration void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(hspi->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspInit 0 */ /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /**SPI1 GPIO Configuration PB3 ------>SPI1_SCK PB5 ------>SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF0_SPI1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* SPI1 DMA Init */ /* SPI1_TX Init */ hdma_spi1_tx.Instance = DMA1_Channel2; 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_BYTE; hdma_spi1_tx.Init.MemDataAlignment =DMA_MDATAALIGN_BYTE; hdma_spi1_tx.Init.Mode = DMA_NORMAL; hdma_spi1_tx.Init.Priority =DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_spi1_tx) !=HAL_OK) { Error_Handler(); } __HAL_LINKDMA(hspi,hdmatx,hdma_spi1_tx); /* USER CODE BEGIN SPI1_MspInit 1 */ /* USER CODE END SPI1_MspInit 1 */ } else if(hspi->Instance==SPI2) { /* USER CODE BEGIN SPI2_MspInit 0 */ /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**SPI2 GPIO Configuration PC2 ------>SPI2_MISO PA0 ------>SPI2_SCK */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF1_SPI2; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF0_SPI2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* SPI2 DMA Init */ /* SPI2_RX Init */ hdma_spi2_rx.Instance = DMA1_Channel3; hdma_spi2_rx.Init.Request =DMA_REQUEST_SPI2_RX; hdma_spi2_rx.Init.Direction =DMA_PERIPH_TO_MEMORY; hdma_spi2_rx.Init.PeriphInc =DMA_PINC_DISABLE; hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_spi2_rx.Init.PeriphDataAlignment =DMA_PDATAALIGN_BYTE; hdma_spi2_rx.Init.MemDataAlignment =DMA_MDATAALIGN_BYTE; hdma_spi2_rx.Init.Mode = DMA_NORMAL; hdma_spi2_rx.Init.Priority =DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_spi2_rx) !=HAL_OK) { Error_Handler(); } __HAL_LINKDMA(hspi,hdmarx,hdma_spi2_rx); /* USER CODE BEGIN SPI2_MspInit 1 */ /* USER CODE END SPI2_MspInit 1 */ } }
基于你的反馈,我找到STM32G0开发板做了验证测试。使用SPI1—halfduplex-maseter,SPI2—halfduplex-slave ...
是在一个开发板上连接主从机测试的吗?看了你的配置,我对了一下自己的代码,没看出什么差别啊,你的工程能否发一份给我看看呢?邮箱szlxhnu@126.com
基于你的反馈,我找到STM32G0开发板做了验证测试。使用SPI1—halfduplex-maseter,SPI2—halfduplex-slave ,主发从收进行测试。 开启crc与否是没有问题的。当然,我用只发/只收也测试过,CRC选择8位或16位都没有碰到问题。 HAL_SPI_Receive_DMA(&hspi2, RxData, 5); HAL_SPI_Transmit_DMA(&hspi1, TxData, 5); 参考配置代码如下: static void MX_SPI1_Init(void) { /* USER CODE BEGIN SPI1_Init 0 */ /* USER CODE END SPI1_Init 0 */ /* USER CODE BEGIN SPI1_Init 1 */ /* USER CODE END SPI1_Init 1 */ /* SPI1 parameter configuration*/ hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_1LINE; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_ENABLE; hspi1.Init.CRCPolynomial = 7; hspi1.Init.CRCLength =SPI_CRC_LENGTH_16BIT; hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SPI1_Init 2 */ /* USER CODE END SPI1_Init 2 */ } static void MX_SPI2_Init(void) { /* USER CODE BEGIN SPI2_Init 0 */ /* USER CODE END SPI2_Init 0 */ /* USER CODE BEGIN SPI2_Init 1 */ /* USER CODE END SPI2_Init 1 */ /* SPI2 parameter configuration*/ hspi2.Instance = SPI2; hspi2.Init.Mode = SPI_MODE_SLAVE; hspi2.Init.Direction = SPI_DIRECTION_1LINE; hspi2.Init.DataSize = SPI_DATASIZE_8BIT; hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; hspi2.Init.NSS = SPI_NSS_SOFT; hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi2.Init.TIMode = SPI_TIMODE_DISABLE; hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_ENABLE; hspi2.Init.CRCPolynomial = 7; hspi2.Init.CRCLength =SPI_CRC_LENGTH_16BIT; hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; if (HAL_SPI_Init(&hspi2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SPI2_Init 2 */ /* USER CODE END SPI2_Init 2 */ } //DMA configuration void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(hspi->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspInit 0 */ /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /**SPI1 GPIO Configuration PB3 ------> SPI1_SCK PB5 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF0_SPI1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* SPI1 DMA Init */ /* SPI1_TX Init */ hdma_spi1_tx.Instance = DMA1_Channel2; 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_BYTE; hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_spi1_tx.Init.Mode = DMA_NORMAL; hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(hspi,hdmatx,hdma_spi1_tx); /* USER CODE BEGIN SPI1_MspInit 1 */ /* USER CODE END SPI1_MspInit 1 */ } else if(hspi->Instance==SPI2) { /* USER CODE BEGIN SPI2_MspInit 0 */ /* USER CODE END SPI2_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**SPI2 GPIO Configuration PC2 ------> SPI2_MISO PA0 ------> SPI2_SCK */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF1_SPI2; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF0_SPI2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* SPI2 DMA Init */ /* SPI2_RX Init */ hdma_spi2_rx.Instance = DMA1_Channel3; hdma_spi2_rx.Init.Request = DMA_REQUEST_SPI2_RX; hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_spi2_rx.Init.Mode = DMA_NORMAL; hdma_spi2_rx.Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_spi2_rx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(hspi,hdmarx,hdma_spi2_rx); /* USER CODE BEGIN SPI2_MspInit 1 */ /* USER CODE END SPI2_MspInit 1 */ } }
是在一个开发板上连接主从机测试的吗?看了你的配置,我对了一下自己的代码,没看出什么差别啊,你的工程 ...
我是使用同一块板的SPI1和SPI2进行测试。配置文件和主文件发到你邮箱。
我是使用同一块板的SPI1和SPI2进行测试。配置文件和主文件发到你邮箱。
已经收到邮件,非常感谢,你的例子里没有实例化两个函数,一个是HAL_SPI_RxCpltCallback,一个是HAL_SPI_ErrorCallback调试过程中接收buff数据是对的,但是调试时不会进HAL_SPI_RxCpltCallback,而是进HAL_SPI_ErrorCallback,造成接收完成标志没有设置成功,主函数里就死等这个标志,而发生的错误是CRC错误,我的问题描述不应该说接收数据出错,而是为什么出现了CRC错误? void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) { if(&hspi2 == hspi) { spisalver_ubReceiveflag = 1; wTransferState = TRANSFER_COMPLETE; } } void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { wTransferState = TRANSFER_ERROR; } 主函数调用 if (HAL_SPI_Receive_DMA(&hspi2,(uint8_t *)spisalver_receive_array, SPI_DATA_CNT) != HAL_OK) { /* Transfer error in transmission process */ //Error_Handler(); } if (HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *)spimater_send_array,SPI_DATA_CNT) != HAL_OK) { /* Transfer error in transmission process */ //Error_Handler(); } while (wTransferState != TRANSFER_COMPLETE) { }
我是使用同一块板的SPI1和SPI2进行测试。配置文件和主文件发到你邮箱。
看了接收波形,数据和CRC值都是对的,调试看最后SR寄存器里RXNE标志为0,超时记录为CRC ERROR if (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT) { if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) { /* Error on the CRC reception */ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); } /* Read 8bit CRC again in case of 16bit CRC in 8bit Data mode */ READ_REG(*(__IO uint8_t *)&hspi->Instance->DR); }