你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

FW_H7 V1.12.1-HAL库DMA双缓冲配置

[复制链接]
talk is cheap 提问时间:2025-8-14 19:39 / 未解决
硬件平台:H750-ART-Pi
软件平台:CubeMX+HAL库 V1.12.1版本


问题背景:需要使用定时器触发DMA-SPI向外部DAC发送数据,由于需要向外部发送的数据量较大且配置SPI总线的多通道,当前需要使用DMA双缓冲配置(从SD卡中读取BIN文件依次填充PingPong-FIFO,使用外扩SDRAM作为DMA-BUF)
遇到的问题:当前已经能够使用单缓冲+定时器触发的方式来向外发送数据,使用双缓冲时,无反应(定时器在工作,当前网络上的一些例程都是基于标准库的,参考作用有限),想求助下HAL库DMA双缓冲案例或者函数调用顺序。
详情参考gitee链接:GIt-CubeMX配置
启动定时器部分代码:HAL_DMAEx_MultiBufferStart_IT这个函数应该是DMA双缓冲的关键 但是开启后无效,即使单缓冲正常工作下也无法看到SPI_TXDR更新,很奇怪
  1. void BSP_DAC_SPI_DMA_Start()
  2. {
  3.         LookUP_BUF_INIT();
  4. //        HAL_DMAEx_MultiBufferStart(&hspi2.hdmatx, LookUP_PingPongBufer.activeBuffer, &hspi2.Instance->TXDR,LookUP_PingPongBufer.readyBuffer,BUFFER_SIZE/4);
  5.         HAL_DMAEx_MultiBufferStart_IT(&hdma_spi2_tx, LookUP_PingPongBufer.activeBuffer, &hspi2.Instance->TXDR, LookUP_PingPongBufer.readyBuffer,BUFFER_SIZE/4);

  6. //        if(HAL_SPI_Transmit_DMA(&hspi2, (uint8_t*)LookUP_PingPongBufer.activeBuffer, BUFFER_SIZE/4)!= HAL_OK)       
  7. //        {
  8. //                printf("BSP_DAC_SPI_DMA_Start  HAL_SPI_Transmit_DMA ERROR !!! \r\n");                  
  9. //        }

  10.         if(HAL_TIM_OC_Start(&htim12, TIM_CHANNEL_1) != HAL_OK)
  11.         {
  12.                 printf("BSP_DAC_SPI_DMA_Start HAL_TIM_OC_Start ERROR !!! \r\n");                  
  13.         }       
  14. }
  15. void LookUP_BUF_INIT(void)
  16. {
  17.         FRESULT result;
  18.         uint32_t bw;
  19.         char path[64];
  20.        
  21.         PingPong_Init(&LookUP_PingPongBufer,LOOKUP_BUF1_ADDR,LOOKUP_BUF2_ADDR);
  22.        

  23.         result = f_mount(&fs, DiskPath, 0);                        /* Mount a logical drive */
  24.         if (result != FR_OK)
  25.         {
  26.                 printf("mount fs failed !!\r\n", FR_Table[result]);
  27.         }

  28.         sprintf(path, "%sTable_hex.bin", DiskPath);
  29.         result = f_open(&file, path, FA_OPEN_EXISTING | FA_READ);
  30.         if (result !=  FR_OK)
  31.         {
  32.                 printf("Don't Find File : Table_hex\r\n");
  33.                 return;
  34.         }

  35.         result = f_read(&file, LookUP_PingPongBufer.activeBuffer , BUFFER_SIZE, &bw);
  36.         if (bw > 0)
  37.         {
  38.                 FsReadBuf[bw] = 0;
  39.         }
  40.        
  41.         result = f_read(&file, LookUP_PingPongBufer.readyBuffer , BUFFER_SIZE, &bw);
  42.         if (bw > 0)
  43.         {
  44.                 FsReadBuf[bw] = 0;
  45.         }


  46. //        f_close(&file);

  47. //        f_mount(NULL, DiskPath, 0);
  48. }
复制代码
定时器初始化部分代码:
  1. void MX_SPI2_Init(void)
  2. {

  3.   /* USER CODE BEGIN SPI2_Init 0 */

  4.   /* USER CODE END SPI2_Init 0 */

  5.   /* USER CODE BEGIN SPI2_Init 1 */

  6.   /* USER CODE END SPI2_Init 1 */
  7.   hspi2.Instance = SPI2;
  8.   hspi2.Init.Mode = SPI_MODE_MASTER;
  9.   hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  10.   hspi2.Init.DataSize = SPI_DATASIZE_32BIT;
  11.   hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  12.   hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
  13.   hspi2.Init.NSS = SPI_NSS_SOFT;
  14.   hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  15.   hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  16.   hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  17.   hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  18.   hspi2.Init.CRCPolynomial = 0x0;
  19.   hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  20.   hspi2.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
  21.   hspi2.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
  22.   hspi2.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
  23.   hspi2.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
  24.   hspi2.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
  25.   hspi2.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
  26.   hspi2.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
  27.   hspi2.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
  28.   hspi2.Init.IOSwap = SPI_IO_SWAP_DISABLE;
  29.   if (HAL_SPI_Init(&hspi2) != HAL_OK)
  30.   {
  31.     Error_Handler();
  32.   }
  33.   /* USER CODE BEGIN SPI2_Init 2 */

  34.   /* USER CODE END SPI2_Init 2 */

  35. }

  36. void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
  37. {

  38.   GPIO_InitTypeDef GPIO_InitStruct = {0};
  39.   HAL_DMA_MuxSyncConfigTypeDef pSyncConfig= {0};
  40.   RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  41.   if(spiHandle->Instance==SPI2)
  42.   {
  43.   /* USER CODE BEGIN SPI2_MspInit 0 */

  44.   /* USER CODE END SPI2_MspInit 0 */

  45.   /** Initializes the peripherals clock
  46.   */
  47.     PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI2;
  48.     PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_CLKP;
  49.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  50.     {
  51.       Error_Handler();
  52.     }

  53.     /* SPI2 clock enable */
  54.     __HAL_RCC_SPI2_CLK_ENABLE();

  55.     __HAL_RCC_GPIOI_CLK_ENABLE();
  56.     /**SPI2 GPIO Configuration
  57.     PI1     ------> SPI2_SCK
  58.     PI2     ------> SPI2_MISO
  59.     PI3     ------> SPI2_MOSI
  60.     */
  61.     GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
  62.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  63.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  64.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  65.     GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
  66.     HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);

  67.     /* SPI2 DMA Init */
  68.     /* SPI2_TX Init */
  69.     hdma_spi2_tx.Instance = DMA1_Stream0;
  70.     hdma_spi2_tx.Init.Request = DMA_REQUEST_SPI2_TX;
  71.     hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
  72.     hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
  73.     hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
  74.     hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
  75.     hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
  76.     hdma_spi2_tx.Init.Mode = DMA_CIRCULAR;
  77.     hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW;
  78.     hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
  79.     hdma_spi2_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
  80.     hdma_spi2_tx.Init.MemBurst = DMA_MBURST_SINGLE;
  81.     hdma_spi2_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
  82.     if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)
  83.     {
  84.       Error_Handler();
  85.     }

  86.     pSyncConfig.SyncSignalID = HAL_DMAMUX1_SYNC_TIM12_TRGO;
  87.     pSyncConfig.SyncPolarity = HAL_DMAMUX_SYNC_RISING;
  88.     pSyncConfig.SyncEnable = ENABLE;
  89.     pSyncConfig.EventEnable = ENABLE;
  90.     pSyncConfig.RequestNumber = 1;
  91.     if (HAL_DMAEx_ConfigMuxSync(&hdma_spi2_tx, &pSyncConfig) != HAL_OK)
  92.     {
  93.       Error_Handler();
  94.     }

  95.     __HAL_LINKDMA(spiHandle,hdmatx,hdma_spi2_tx);

  96.     /* SPI2 interrupt Init */
  97.     HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0);
  98.     HAL_NVIC_EnableIRQ(SPI2_IRQn);
  99.   /* USER CODE BEGIN SPI2_MspInit 1 */

  100. //                HAL_DMAEx_MultiBufferStart_IT(&hdma_spi2_tx, (uint8_t*)LookUP_PingPongBufer.activeBuffer, (uint32_t)hspi2.Instance->TXDR, (uint8_t*)LookUP_PingPongBufer.readyBuffer,1000);
  101.                
  102.   /* USER CODE END SPI2_MspInit 1 */
  103.   }
  104. }
复制代码

SPI初始化部分代码:

  1. /* TIM12 init function */
  2. void MX_TIM12_Init(void)
  3. {

  4.   /* USER CODE BEGIN TIM12_Init 0 */

  5.   /* USER CODE END TIM12_Init 0 */

  6.   TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  7.   TIM_MasterConfigTypeDef sMasterConfig = {0};
  8.   TIM_OC_InitTypeDef sConfigOC = {0};

  9.   /* USER CODE BEGIN TIM12_Init 1 */

  10.   /* USER CODE END TIM12_Init 1 */
  11.   htim12.Instance = TIM12;
  12.   htim12.Init.Prescaler = 240-1;
  13.   htim12.Init.CounterMode = TIM_COUNTERMODE_UP;
  14.   htim12.Init.Period = 1000-1;
  15.   htim12.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  16.   htim12.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  17.   if (HAL_TIM_Base_Init(&htim12) != HAL_OK)
  18.   {
  19.     Error_Handler();
  20.   }
  21.   sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  22.   if (HAL_TIM_ConfigClockSource(&htim12, &sClockSourceConfig) != HAL_OK)
  23.   {
  24.     Error_Handler();
  25.   }
  26.   if (HAL_TIM_PWM_Init(&htim12) != HAL_OK)
  27.   {
  28.     Error_Handler();
  29.   }
  30.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
  31.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  32.   if (HAL_TIMEx_MasterConfigSynchronization(&htim12, &sMasterConfig) != HAL_OK)
  33.   {
  34.     Error_Handler();
  35.   }
  36.   sConfigOC.OCMode = TIM_OCMODE_PWM1;
  37.   sConfigOC.Pulse = (1000)/2-1;
  38.   sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
  39.   sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  40.   if (HAL_TIM_PWM_ConfigChannel(&htim12, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  41.   {
  42.     Error_Handler();
  43.   }
  44.   /* USER CODE BEGIN TIM12_Init 2 */

  45.   /* USER CODE END TIM12_Init 2 */

  46. }

  47. void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
  48. {

  49.   if(tim_baseHandle->Instance==TIM12)
  50.   {
  51.   /* USER CODE BEGIN TIM12_MspInit 0 */

  52.   /* USER CODE END TIM12_MspInit 0 */
  53.     /* TIM12 clock enable */
  54.     __HAL_RCC_TIM12_CLK_ENABLE();

  55.     /* TIM12 interrupt Init */
  56.     HAL_NVIC_SetPriority(TIM8_BRK_TIM12_IRQn, 0, 0);
  57.     HAL_NVIC_EnableIRQ(TIM8_BRK_TIM12_IRQn);
  58.   /* USER CODE BEGIN TIM12_MspInit 1 */

  59.   /* USER CODE END TIM12_MspInit 1 */
  60.   }
  61. }
复制代码

图为使用逻辑分析仪抓取单缓冲数据时刻,SPI总线数据
image.png
收藏 评论0 发布时间:2025-8-14 19:39

举报

0个回答

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版