本帖最后由 Penguins 于 2025-6-10 15:14 编辑
我使用 H743 采集外部 ADC,通过 DMAMUX 的 SYNC 配合 SPI 以 1 MSPS 接收单路 16-bit 转换结果。但当 HAL_SPI_Receive_DMA(...) 的数量在 15 个及以上时,接收结果错误且仅有前 8 个正确,数量在 14 个及以下时都正确。此处仅进行软件测试,即 SPIx_SCK 悬空,SPIx_MISO 接固定高电平,接收结果应均为 0xFFFF。关闭来自 TIM12_TRGO 的 SYNC 的同步功能,连续接收 16 个 16-bit 数据是正确的;可以排除 DMAMUX 的 Overrun,因为 SPI 时钟为 60 MHz;引脚速度已调整至 Very High,也尝试过使能内部上拉电阻;且相同的 SYNC 配置(仅降低 TIM12 频率至 1 Hz)在串口发送 64 个字符(每次传输 2 个)无异常。经测试发现,接收错误时未能进入 HAL_SPI_RxCpltCallback(...) 接收完成回调函数。请问还有什么检查思路或尝试方案吗?以下为配置代码和测试程序。
[C] 纯文本查看 复制代码 __ZI_AXI_SRAM char gUART1_TxMsg[UART_BUF_SIZE];
__ZI_AXI_SRAM uint16_t gSPI2_RxMsg[32];
__IO uint8_t gSPI2_RxCplt = 0;
myUART_HandleTypeDef myUART = {
.huart = &huart1,
.pTxMsg = gUART1_TxMsg,
.pRxMsg = gUART1_RxMsg,
};
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
if (hspi == &hspi2)
{
gSPI2_RxCplt = 1;
}
}
int main(void)
{
SCB_EnableICache();
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_TIM14_Init();
MX_TIM12_Init();
MX_SPI2_Init();
/* USER CODE BEGIN 2 */
HAL_SPI_Receive_DMA(&hspi2, (uint8_t *)gSPI2_RxMsg, 16);
HAL_TIM_Base_Start(&htim12);
uint32_t tickstart;
tickstart = HAL_GetTick();
while (gSPI2_RxCplt == 0 && HAL_GetTick() - tickstart < 0x3FF);
HAL_TIM_Base_Stop(&htim12);
myUART_Transmit_DMA(&myUART, "status = %s\n", gSPI2_RxCplt ? "SUCCESS!" : "FAILED!");
myUART_Transmit_DMA(&myUART, "rx0 = %x %x %x %x\n", gSPI2_RxMsg[0], gSPI2_RxMsg[1], gSPI2_RxMsg[2], gSPI2_RxMsg[3]);
myUART_Transmit_DMA(&myUART, "rx1 = %x %x %x %x\n", gSPI2_RxMsg[4], gSPI2_RxMsg[5], gSPI2_RxMsg[6], gSPI2_RxMsg[7]);
myUART_Transmit_DMA(&myUART, "rx2 = %x %x %x %x\n", gSPI2_RxMsg[8], gSPI2_RxMsg[9], gSPI2_RxMsg[10], gSPI2_RxMsg[11]);
myUART_Transmit_DMA(&myUART, "rx3 = %x %x %x %x\n", gSPI2_RxMsg[12], gSPI2_RxMsg[13], gSPI2_RxMsg[14], gSPI2_RxMsg[15]);
while (1)
{
}
}
[C] 纯文本查看 复制代码
void MX_SPI2_Init(void)
{
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
hspi2.Init.DataSize = SPI_DATASIZE_16BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 0x0;
hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
hspi2.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi2.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi2.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi2.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi2.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi2.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi2.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi2.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
hspi2.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
HAL_DMA_MuxSyncConfigTypeDef pSyncConfig= {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
if(spiHandle->Instance==SPI2)
{
/** Initializes the peripherals clock */
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI2;
PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* SPI2 clock enable */
__HAL_RCC_SPI2_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI2 GPIO Configuration
PB13 ------> SPI2_SCK
PB14 ------> SPI2_MISO
*/
GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* SPI2 DMA Init */
/* SPI2_RX Init */
hdma_spi2_rx.Instance = DMA2_Stream0;
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_HALFWORD;
hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_spi2_rx.Init.Mode = DMA_NORMAL;
hdma_spi2_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi2_rx) != HAL_OK)
{
Error_Handler();
}
pSyncConfig.SyncSignalID = HAL_DMAMUX1_SYNC_TIM12_TRGO;
pSyncConfig.SyncPolarity = HAL_DMAMUX_SYNC_FALLING;
pSyncConfig.SyncEnable = ENABLE;
pSyncConfig.EventEnable = DISABLE;
pSyncConfig.RequestNumber = 1;
if (HAL_DMAEx_ConfigMuxSync(&hdma_spi2_rx, &pSyncConfig) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(spiHandle,hdmarx,hdma_spi2_rx);
/* SPI2 interrupt Init */
HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI2_IRQn);
}
}
[C] 纯文本查看 复制代码 void MX_TIM12_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim12.Instance = TIM12;
htim12.Init.Prescaler = 23999;
htim12.Init.CounterMode = TIM_COUNTERMODE_UP;
htim12.Init.Period = 9999;
htim12.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim12.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim12) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim12, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim12, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
- 【测试结果1】HAL_SPI_Receive_DMA(...) 接收 14 个 16-bit 时的串口数据
[C] 纯文本查看 复制代码 status = SUCCESS!
rx0 = ffff ffff ffff ffff
rx1 = ffff ffff ffff ffff
rx2 = ffff ffff ffff ffff
rx3 = ffff ffff 0 0
- 【测试结果2】HAL_SPI_Receive_DMA(...) 接收 15 个 16-bit 时的串口数据
[C] 纯文本查看 复制代码 status = FAILED!
rx0 = ffff ffff ffff ffff
rx1 = ffff ffff ffff ffff
rx2 = 0 0 0 0
rx3 = 0 0 0 0
|