Я использую библиотеки STM32H7 и HAL. На моей плате SPI6 используется для связи с внешним ЦАП (DAC8734). Связь работает отлично (с DMA). Цель состоит в том, чтобы обновлять ЦАП каждые 8 мкс для имитации сигнала переменного тока. Для этого я использую базовый таймер TIM15. Таймер вызывает внутри своего прерывания функцию передачи DMA. После завершения передачи буфер будет увеличен в DMA_Interrupt_Handler, поскольку я не могу непрерывно отправлять данные в ЦАП (требуется ЦАП и триггер высокого / низкого уровня на линии CS для обновления своего канала). Есть ли способ повысить мою производительность?
здесь код для TIM15:
__HAL_RCC_DMA1_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
__HAL_RCC_BDMA_CLK_ENABLE();
TIM_ClockConfigTypeDef SClockSourceConfigDMA;
TIM_SlaveConfigTypeDef sSlaveConfigDMA;
TIM_MasterConfigTypeDef sMasterConfigDMA;
TIM_IC_InitTypeDef sConfigICDMA;
htim15.Instance = TIM15; //TIM15 must be synchron to TIM5 --> 40 MHz, Baseclock is 200 Mhz
htim15.Init.Prescaler = 300;//300;//15; //Max. for good sin: Pre = 50 & Per = 16 & DIV4
htim15.Init.CounterMode = TIM_COUNTERMODE_UP;
htim15.Init.Period = 5;//4; //Period = 5 & Prescaler = 100 für 200 kHz -->
htim15.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim15.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim15) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
SClockSourceConfigDMA.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim15, &SClockSourceConfigDMA) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
if (HAL_TIM_IC_Init(&htim15) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sSlaveConfigDMA.SlaveMode = TIM_SLAVEMODE_TRIGGER;
sSlaveConfigDMA.InputTrigger = TIM_TS_ITR2;
if (HAL_TIM_SlaveConfigSynchronization(&htim15, &sSlaveConfigDMA) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfigDMA.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfigDMA.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim15, &sMasterConfigDMA) !=
HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sConfigICDMA.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigICDMA.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigICDMA.ICPrescaler = TIM_ICPSC_DIV1;
sConfigICDMA.ICFilter = 1;
if (HAL_TIM_IC_ConfigChannel(&htim15, &sConfigICDMA, TIM_CHANNEL_1) !=
HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
if (HAL_TIM_IC_ConfigChannel(&htim15, &sConfigICDMA, TIM_CHANNEL_2) !=
HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
if (HAL_TIM_IC_ConfigChannel(&htim15, &sConfigICDMA, TIM_CHANNEL_3) !=
HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
if (HAL_TIM_IC_ConfigChannel(&htim15, &sConfigICDMA, TIM_CHANNEL_4) !=
HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
__HAL_TIM_ENABLE_IT(&htim15, TIM_IT_UPDATE);
__HAL_TIM_ENABLE_IT(&htim15, TIM_IT_CC1);
__HAL_TIM_ENABLE_IT(&htim15, TIM_IT_CC2);
__HAL_TIM_ENABLE_IT(&htim15, TIM_IT_CC3);
__HAL_TIM_ENABLE_IT(&htim15, TIM_IT_CC4);
SystemCoreClockUpdate();
}
вот код для DMA:
//Setting the configuration for the DMA tx --> this is the configuration for SPI6 as Trigger
hdma_spi6_tx_init.Instance = BDMA_Channel2; //Choose BDMA, for SPI6 is connected to DMAMUX2
//hdma_spi6_tx_init.DMAmuxChannel->CCR = 0b1100; //Selects SPI6 for DMAMUX2
hdma_spi6_tx_init.Init.Request = BDMA_REQUEST_SPI6_TX; //BDMA (DMAUX2) for TX of SPI6
hdma_spi6_tx_init.Init.Direction = DMA_MEMORY_TO_PERIPH; //Transfering from Memory to Peripherie (2, S.632)
hdma_spi6_tx_init.Init.PeriphInc = DMA_PINC_ENABLE; //Incrementing the address register todo: maybe enable
hdma_spi6_tx_init.Init.MemInc = DMA_MINC_ENABLE; //Incrementing the memory address register
hdma_spi6_tx_init.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; //Data size: Byte, because SPI6 is transferring 8-Bit at the time
hdma_spi6_tx_init.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; //Memory data size: Byte, because thats the size of the other registers
hdma_spi6_tx_init.Init.Mode = DMA_NORMAL; //Peripheral flow control mode (S.632)
hdma_spi6_tx_init.Init.Priority = DMA_PRIORITY_VERY_HIGH; //High Priority for transfer
hdma_spi6_tx_init.Init.FIFOMode = DMA_FIFOMODE_ENABLE; //Direct mode for transfer (todo:FIFO enable)
hdma_spi6_tx_init.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; //Wait for full FIFO
hdma_spi6_tx_init.Init.MemBurst = DMA_MBURST_SINGLE; //One byte sized burst for memory
hdma_spi6_tx_init.Init.PeriphBurst = DMA_PBURST_SINGLE; //One byte sized burst for peripheral
//Setting the configuration for the BDMA (S.653 + S.663)
bdma_spi6_init.CPAR = BDMA_REQUEST_SPI6_TX; //Peripheral register address for SPI6
bdma_spi6_init.CMAR = (uint8_t *) Crrct_Size_Buffer; //Memory register address
bdma_spi6_init.CNDTR = 0xFFFF;//0x1F2; //Total number of data to transfer
bdma_spi6_init.CCR |= 0x3098;
// Bits for CCR (0 << 15) || //Double-buffer mode off
// (0 << 14) || //Memory-to-memory mode off
// (1 << 13) || //Priority level high
// (1 << 12) || //Priority level high
// (0 << 11) || //Memory size: 8-Bit
// (0 << 10) || //Memory size: 8-Bit
// (0 << 9) || //Peripheral size: 8-Bit
// (0 << 8) || //Peripheral size: 8-Bit
// (1 << 7) || //Peripheral as destination, enable Memory increment mode
// (0 << 6) || //Memory as source, disable Peripheral increment mode
// (0 << 5) || //Circular mode disabled
// (1 << 4) || //Read from Memory
// (1 << 3) || //Enable transfer error interrupt
// (0 << 2) || //Disable half transfer interrupt
// (0 << 1) || //Disable transfer complete interrupt
// (0 << 0);
if (HAL_DMA_Init(&hdma_spi6_tx_init) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
__HAL_LINKDMA( hspi, hdmatx, hdma_spi6_tx_init);
Внутри TIM15_IRQHandler я вызываю передачу DMA:
SCB_CleanDCache_by_Addr( (uint8_t *) Crrct_Size_Buffer, sizeof(Crrct_Size_Buffer)/sizeof(Crrct_Size_Buffer[0])); //Clear memory space for TxBuffer
HAL_SPI_Transmit_DMA(&hspi6, (uint8_t *) Crrct_Size_Buffer, 3);
После передачи вызывается обработчик IRQ BDMA:
Crrct_Size_Buffer[0] = Crrct_Size_Buffer[IRQ_Counter[0]+3];
Crrct_Size_Buffer[1] = Crrct_Size_Buffer[IRQ_Counter[0]+4];
Crrct_Size_Buffer[2] = Crrct_Size_Buffer[IRQ_Counter[0]+5];
if(IRQ_Counter[0] < (NumberOfSamples-1)*3 )
{
IRQ_Counter[0] = IRQ_Counter[0] + 3;
}
else
{
IRQ_Counter[0] = 0;
}
HAL_GPIO_WritePin(DAC_LDAC_GPIO_Port,DAC_LDAC_Pin, GPIO_PIN_SET); //LDAC high/low to update the command register
HAL_GPIO_WritePin(DAC_LDAC_GPIO_Port,DAC_LDAC_Pin, GPIO_PIN_RESET);
HAL_DMA_IRQHandler(&hdma_spi6_tx_init);
Моя проблема сейчас в том, что я не получаю никакого увеличения производительности. Я предполагаю, что это потому, что я вручную увеличиваю свой Crrct_Size_Buffer, но я не могу просто отправить все данные сразу, из-за ЦАП (для которого нужен триггер высокого / низкого уровня). У кого-нибудь есть идеи как повысить производительность?
Если вам нужна дополнительная информация, пожалуйста, не стесняйтесь спрашивать. Извините за мой плохой английский я не родной :) 1015 *
Спасибо за вашу помощь!