ST意法半导体
直播中

吕珠峰

11年用户 868经验值
擅长:可编程逻辑
私信 关注
[问答]

如何重复调用HAL_SPI_TxCpltCallback() DMA循环模式?

我想使用 SPI 仅传输主模式将移位寄存器(74HC595)与 STM32F103C8T6 MCU 连接起来。
我需要连续写入移位寄存器,以便它不断更新 op 引脚。所以我将 SPI DMA 设置为循环模式,当传输完成时我需要提供锁存时钟,所以我使用 HAL_SPI_TxCpltCallback() 函数但它只在 HAL_SPI_Transmit_DMA() 调用时调用一次。
如何重复调用 HAL_SPI_TxCpltCallback() DMA 循环模式?
我的目标是在 while 循环外使用 DMA 不断更新 SHIFTREISTERs 引脚。
  • /* USER CODE BEGIN Header */
  • /**
  • ******************************************************************************
  • * @file           : main.c
  • * @brief          : Main program body
  • ******************************************************************************
  • * @attention
  • *
  • * Copyright (c) 2022 STMicroelectronics.
  • * All rights reserved.
  • *
  • * This software is licensed under terms that can be found in the LICENSE file
  • * in the root directory of this software component.
  • * If no LICENSE file comes with this software, it is provided AS-IS.
  • *
  • ******************************************************************************
  • */
  • /* USER CODE END Header */
  • /* Includes ------------------------------------------------------------------*/
  • #include "main.h"
  • #include "dma.h"
  • #include "spi.h"
  • #include "gpio.h"
  • /* Private includes ----------------------------------------------------------*/
  • /* USER CODE BEGIN Includes */
  • #include "stdbool.h"
  • /* USER CODE END Includes */
  • /* Private typedef -----------------------------------------------------------*/
  • /* USER CODE BEGIN PTD */
  • /* USER CODE END PTD */
  • /* Private define ------------------------------------------------------------*/
  • /* USER CODE BEGIN PD */
  • #define NO_OF_OP 8
  • /* USER CODE END PD */
  • /* Private macro -------------------------------------------------------------*/
  • /* USER CODE BEGIN PM */
  • /* USER CODE END PM */
  • /* Private variables ---------------------------------------------------------*/
  • /* USER CODE BEGIN PV */
  • bool OP[NO_OF_OP];
  • uint8_t data = 0;
  • /* USER CODE END PV */
  • /* Private function prototypes -----------------------------------------------*/
  • void SystemClock_Config(void);
  • /* USER CODE BEGIN PFP */
  • void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
  • {
  •         HAL_GPIO_WritePin(L_CLK_GPIO_Port, L_CLK_Pin, GPIO_PIN_SET);
  •         HAL_GPIO_WritePin(L_CLK_GPIO_Port, L_CLK_Pin, GPIO_PIN_RESET);
  • }
  • void write_to_reg(){
  •         HAL_GPIO_WritePin(LATCH_CLOCK_GPIO_Port,LATCH_CLOCK_Pin,GPIO_PIN_RESET);
  •         for (int x = NO_OF_OP-1; x >= 0; x--) {
  •                 HAL_GPIO_WritePin(A_GPIO_Port,A_Pin,OP[x]);
  •                 //delay_us(10);
  •                 HAL_GPIO_WritePin(SHIFT_CLK_GPIO_Port,SHIFT_CLK_Pin,GPIO_PIN_RESET);
  •                 //delay_us(50);
  •                 HAL_GPIO_WritePin(SHIFT_CLK_GPIO_Port,SHIFT_CLK_Pin,GPIO_PIN_SET);
  •         }
  •         HAL_GPIO_WritePin(LATCH_CLOCK_GPIO_Port,LATCH_CLOCK_Pin,GPIO_PIN_SET);
  •         //delay_us(100);
  •         HAL_GPIO_WritePin(LATCH_CLOCK_GPIO_Port,LATCH_CLOCK_Pin,GPIO_PIN_RESET);
  • }
  • /* USER CODE END PFP */
  • /* Private user code ---------------------------------------------------------*/
  • /* USER CODE BEGIN 0 */
  • uint8_t bit_to_byte(bool *bitarray){
  •         uint8_t byt = 0x00;
  •         for (uint8_t j = 0; j < 8; ++j) {
  •                 if (bitarray[j]) {
  •                         byt = byt | (1<                }
  •         }
  •         return byt;
  • }
  • /* USER CODE END 0 */
  • /**
  •   * @brief  The application entry point.
  •   * @retval int
  •   */
  • int main(void)
  • {
  •   /* USER CODE BEGIN 1 */
  •   /* USER CODE END 1 */
  •   /* MCU Configuration--------------------------------------------------------*/
  •   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  •   HAL_Init();
  •   /* USER CODE BEGIN Init */
  •   /* USER CODE END Init */
  •   /* Configure the system clock */
  •   SystemClock_Config();
  •   /* USER CODE BEGIN SysInit */
  •   /* USER CODE END SysInit */
  •   /* Initialize all configured peripherals */
  •   MX_GPIO_Init();
  •   MX_DMA_Init();
  •   MX_SPI1_Init();
  •   /* USER CODE BEGIN 2 */
  •         HAL_GPIO_WritePin(OE_GPIO_Port,OE_Pin,GPIO_PIN_RESET);
  •         HAL_GPIO_WritePin(ENABLE_GPIO_Port, ENABLE_Pin, GPIO_PIN_RESET);
  •         HAL_SPI_Transmit_DMA(&hspi1, &data, 1);
  •   /* USER CODE END 2 */
  •   /* Infinite loop */
  •   /* USER CODE BEGIN WHILE */
  •         while (1)
  •         {
  •     /* USER CODE END WHILE */
  •     /* USER CODE BEGIN 3 */
  •                 OP[0] = true;
  •                 OP[1] = true;
  •                 OP[2] = true;
  •                 OP[3] = true;
  •                 OP[4] = false;
  •                 OP[5] = false;
  •                 OP[6] = false;
  •                 OP[7] = false;
  •                 data = bit_to_byte(OP);
  •                 /**
  •                 HAL_SPI_Transmit_DMA(&hspi1,&data,1);
  •                 HAL_GPIO_WritePin(L_CLK_GPIO_Port, L_CLK_Pin, GPIO_PIN_SET);
  •                 HAL_GPIO_WritePin(L_CLK_GPIO_Port, L_CLK_Pin, GPIO_PIN_RESET);
  •                  **/
  •                 HAL_Delay(100);
  •                 OP[0] = false;
  •                 OP[1] = false;
  •                 OP[2] = false;
  •                 OP[3] = false;
  •                 OP[4] = true;
  •                 OP[5] = true;
  •                 OP[6] = true;
  •                 OP[7] = true;
  •                 data = bit_to_byte(OP);
  •                 /**
  •                 HAL_SPI_Transmit_DMA(&hspi1,&data,1);
  •                 HAL_GPIO_WritePin(L_CLK_GPIO_Port, L_CLK_Pin, GPIO_PIN_SET);
  •                 HAL_GPIO_WritePin(L_CLK_GPIO_Port, L_CLK_Pin, GPIO_PIN_RESET);
  •                  **/
  •                 HAL_Delay(100);
  •         }
  •   /* USER CODE END 3 */
  • }
  • /**
  •   * @brief System Clock Configuration
  •   * @retval None
  •   */
  • void SystemClock_Config(void)
  • {
  •   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  •   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  •   /** Initializes the RCC Oscillators according to the specified parameters
  •   * in the RCC_OscInitTypeDef structure.
  •   */
  •   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  •   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  •   RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  •   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  •   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  •   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  •   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  •   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  •   {
  •     Error_Handler();
  •   }
  •   /** Initializes the CPU, AHB and APB buses clocks
  •   */
  •   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  •                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  •   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  •   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  •   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  •   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  •   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  •   {
  •     Error_Handler();
  •   }
  •   /** Enables the Clock Security System
  •   */
  •   HAL_RCC_EnableCSS();
  • }
  • /* USER CODE BEGIN 4 */
  • /* USER CODE END 4 */
  • /**
  •   * @brief  This function is executed in case of error occurrence.
  •   * @retval None
  •   */
  • void Error_Handler(void)
  • {
  •   /* USER CODE BEGIN Error_Handler_Debug */
  •         /* User can add his own implementation to report the HAL error return state */
  •         __disable_irq();
  •         while (1)
  •         {
  •         }
  •   /* USER CODE END Error_Handler_Debug */
  • }
  • #ifdef  USE_FULL_ASSERT
  • /**
  •   * @brief  Reports the name of the source file and the source line number
  •   *         where the assert_param error has occurred.
  •   * @param  file: pointer to the source file name
  •   * @param  line: assert_param error line source number
  •   * @retval None
  •   */
  • void assert_failed(uint8_t *file, uint32_t line)
  • {
  •   /* USER CODE BEGIN 6 */
  •         /* User can add his own implementation to report the file name and line number,
  •      ex: printf("Wrong parameters value: file %s on line %drn", file, line) */
  •   /* USER CODE END 6 */
  • }
  • #endif /* USE_FULL_ASSERT */

  • 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 */
  •   hspi1.Instance = SPI1;
  •   hspi1.Init.Mode = SPI_MODE_MASTER;
  •   hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  •   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_4;
  •   hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  •   hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  •   hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  •   hspi1.Init.CRCPolynomial = 10;
  •   if (HAL_SPI_Init(&hspi1) != HAL_OK)
  •   {
  •     Error_Handler();
  •   }
  •   /* USER CODE BEGIN SPI1_Init 2 */
  •   /* USER CODE END SPI1_Init 2 */
  • }
  • void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
  • {
  •   GPIO_InitTypeDef GPIO_InitStruct = {0};
  •   if(spiHandle->Instance==SPI1)
  •   {
  •   /* USER CODE BEGIN SPI1_MspInit 0 */
  •   /* USER CODE END SPI1_MspInit 0 */
  •     /* SPI1 clock enable */
  •     __HAL_RCC_SPI1_CLK_ENABLE();
  •     __HAL_RCC_GPIOA_CLK_ENABLE();
  •     /**SPI1 GPIO Configuration
  •     PA5     ------> SPI1_SCK
  •     PA7     ------> SPI1_MOSI
  •     */
  •     GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7;
  •     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  •     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  •     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  •     /* SPI1 DMA Init */
  •     /* SPI1_TX Init */
  •     hdma_spi1_tx.Instance = DMA1_Channel3;
  •     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_MEDIUM;
  •     if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
  •     {
  •       Error_Handler();
  •     }
  •     __HAL_LINKDMA(spiHandle,hdmatx,hdma_spi1_tx);
  •   /* USER CODE BEGIN SPI1_MspInit 1 */
  •   /* USER CODE END SPI1_MspInit 1 */
  •   }
  • }



回帖(1)

张珍岚

2022-12-13 10:10:43
hdma_spi1_tx.Init.Mode = DMA_NORMAL;
这是一次性转移。
您需要 DMA_CIRCULAR 进行循环传输。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分