我使用 STM32F733xx 和通过 SPI 连接的外部 ADC ( ti ADS8588S) 构建了一个自定义系统。当通过阻塞/轮询方法传输数据时,我已验证系统使用STM32 HAL L0_V1.2.8 始终如一地工作。但是,当我将 SPI 配置为使用链接的 DMA 以非阻塞方式运行时,我只能完成一次完整传输。连续传输无法产生 SCLK,如下所示:
这是 SPI 和 DMA 配置代码:
- hspi1.Instance = SPI1;
- hspi1.Init.Mode = SPI_MODE_MASTER;
- hspi1.Init.Direction = SPI_DIRECTION_2LINES;
- hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
- hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
- hspi1.Init.CLKPhase = SPI_PHASE_2EDGE; // Needed for Saleae match
- hspi1.Init.NSS = SPI_NSS_SOFT;
- hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
- hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
- hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
- hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
- hspi1.Init.CRCPolynomial = 7;
- hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
- hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
- if (HAL_SPI_Init(&hspi1) != HAL_OK)
- {
- Error_Handler();
- }
- 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_GPIOA_CLK_ENABLE();
- /**SPI1 GPIO Configuration
- PA5 ------> SPI1_SCK
- PA6 ------> SPI1_MISO
- PA7 ------> SPI1_MOSI
- */
- GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
- 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_SPI1;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- /* SPI1_RX DMA Init */
- __HAL_RCC_DMA2_CLK_ENABLE();
- hdma_spi1_rx.Instance = DMA2_Stream2;
- hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3;
- hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
- hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
- hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
- hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
- hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
- hdma_spi1_rx.Init.Mode = DMA_NORMAL;
- hdma_spi1_rx.Init.Priority = DMA_PRIORITY_HIGH;
- hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
- if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
- {
- Error_Handler();
- }
- HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0); // SPI1 RX - Chan 3
- HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
- __HAL_LINKDMA(hspi,hdmarx,hdma_spi1_rx); /*link DMA2 to SPI1 Rx*/
- /*DMA 1 / channel 0 / stream 5 sends data to SPI (no GPIO pin existent, only needed for clocking in right number of bytes)*/
- __HAL_RCC_DMA2_CLK_ENABLE(); /*DMA clock*/
- hdma_spi1_tx.Instance = DMA2_Stream3;
- hdma_spi1_tx.Init.Channel = DMA_CHANNEL_3;
- hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; /*from memory to SPI*/
- hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE; /*no increment on SPI side*/
- hdma_spi1_tx.Init.MemInc = DMA_MINC_DISABLE; /*no increment sample memory address*/
- hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
- hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
- hdma_spi1_tx.Init.Mode = DMA_NORMAL;
- hdma_spi1_tx.Init.Priority = DMA_PRIORITY_HIGH;
- hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
- if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
- {
- Error_Handler();
- }
- __HAL_LINKDMA(hspi, hdmatx, hdma_spi1_tx); /*link DMA2 to SPI1 Tx*/
- /* USER CODE BEGIN SPI1_MspInit 1 */
- /* USER CODE END SPI1_MspInit 1 */
- }
- }
我要求在 2 条线路 (TX/RX) 上进行 DMA 传输,因此我将 TX 线路设置为仅发送虚拟数据并生成 SCLK:
- static uint16_t ulDummyWord[16]={0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF};
- static uint16_t Adc1RxBuff[16];
- int main(void)
- {
- /* USER CODE BEGIN 1 */
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- HAL_Delay(10);
- HAL_GPIO_WritePin(ADDevice1.AD_pinMapping->CS_gpioPort, ADDevice1.AD_pinMapping->CS_gpioPin, 0); // select ADC1 for SPI transfer
- HAL_SPI_TransmitReceive_DMA(hspi1,(uint8_t *)ulDummyWord,(uint8_t *)Adc1RxBuff, 16); // this only works once
- }
- }
- void DMA2_Stream2_IRQHandler(void)
- {
- /* USER CODE BEGIN DMA2_Stream2_IRQn 0 */
- __HAL_DMA_CLEAR_FLAG(&hdma_spi1_rx,DMA_FLAG_TCIF2_6);
- __HAL_DMA_CLEAR_FLAG(&hdma_spi1_rx,DMA_FLAG_HTIF2_6);
- __HAL_DMA_CLEAR_FLAG(&hdma_spi1_tx,DMA_FLAG_TCIF3_7);
- __HAL_DMA_CLEAR_FLAG(&hdma_spi1_tx,DMA_FLAG_HTIF3_7);
- __HAL_DMA_CLEAR_FLAG(&hdma_spi1_tx,DMA_FLAG_FEIF3_7);
- HAL_GPIO_WritePin(ADDevice1.AD_pinMapping->CS_gpioPort, ADDevice1.AD_pinMapping->CS_gpioPin, 1);
- }
问题是 HAL_SPI_TransmitReceive_DMA 调用在第二次调用 HAL_BUSY 时出错,因为 hspi->State 是 HAL_SPI_STATE_BUSY_TX_RX。我认为根本原因与 SPI Tx 发送虚拟数据和断言 DMA_FLAG_FEIF3_7 标志有关,但清除它没有帮助。
我看不出如何重置 SPI1 DMA 以便可以进行连续传输。我怀疑状态标志(TXE、RXNE),但我看不出有什么问题。
0
|
1个回答
|
|
|