使用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(); } |
STM32G0B1的CAN自动重发
关于使用STM32G030C8T6的串口收发过程中串口接收问题
STM32F4作为SPI从机,主机发送完数据后,从机没有正确进入中断
用stm32cubeide生成的STM32G030F6P6代码只要一开中断,任何中断程序都会跑飞.
关于stm32g431串口与FDCAN数据不同同时处理问题
STM32G0B1CBT6 双Bank升级,运行Bank2上Flash不能写问题
STM32F4作为SPI从机,在主机时钟结束后,MISO依然有输出。
有关STM32G0B1RET6芯片FLASH擦除问题
L9663驱动开发
STM32G030烧录程序
是在一个开发板上连接主从机测试的吗?看了你的配置,我对了一下自己的代码,没看出什么差别啊,你的工程能否发一份给我看看呢?邮箱szlxhnu@126.com
开启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进行测试。配置文件和主文件发到你邮箱。
已经收到邮件,非常感谢,你的例子里没有实例化两个函数,一个是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)
{
}
看了接收波形,数据和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);
}