硬汉哥,你说的是传输完成中断和半传输完成中断吗?
我在H7平台上,使用官方的(即你在1楼贴的代码)基础上,稍作了修改,如果使用hdma_tim.Init.Mode = DMA_NORMAL;的话,则Burst的行为是对的。但是当缓冲区Burst完毕,DMA就停止了,不能再继续了。但如果改成hdma_tim.Init.Mode = DMA_CIRCULAR;则每次Burst变成了1个Word。代码贴在下面。
main.c
[C] 纯文本查看 复制代码 /* Includes ------------------------------------------------------------------*/
#include "main.h"
/** @addtogroup STM32H7xx_HAL_Examples
* @{
*/
/** @addtogroup TIM_DMABurst
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Timer handler declaration */
TIM_HandleTypeDef TimHandle;
/* Timer Output Compare Configuration Structure declaration */
TIM_OC_InitTypeDef sConfig;
/* Capture Compare buffer */
uint32_t aSRC_Buffer[6] = {0x0000FFFF, 0x00000fff, 0x00000555,0x0000FFFF, 0x00000fff, 0x00000556};
/* Timer Period*/
uint32_t uwTimerPeriod = 0;
/* Private function prototypes -----------------------------------------------*/
static void MPU_Config(void);
static void SystemClock_Config(void);
static void Error_Handler(void);
static void CPU_CACHE_Enable(void);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
/* STM32H7xx HAL library initialization:
- Systick timer is configured by default as source of time base, but user
can eventually implement his proper time base source (a general purpose
timer for example or other time source), keeping in mind that Time base
duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
handled in milliseconds basis.
- Set NVIC Group Priority to 4
- Low Level Initialization
*/
/* Configure the MPU attributes */
MPU_Config();
/* Enable the CPU Cache */
CPU_CACHE_Enable();
HAL_Init();
/* Configure the system clock to 400 MHz */
SystemClock_Config();
/* Configure LED2 */
BSP_LED_Init(LED2);
/*##-1- Configure the TIM peripheral #######################################*/
/* -----------------------------------------------------------------------
TIM2 Configuration: generate 1 PWM signal using the DMA burst mode:
TIM2 input clock (TIM2CLK) is set to APB1 clock (PCLK1)x2, since APB1
prescaler is 2.
TIM2CLK = 2*PCLK1
PCLK1 = HCLK/2 since AHB1 prescaler also is set to 2.
=> TIM2CLK = HCLK = SystemCoreClock/2
To get TIM2 counter clock at 20 MHz, the prescaler is computed as follows:
Prescaler = (TIM2CLK / TIM2 counter clock) - 1
Prescaler = ((SystemCoreClock/2) /20 MHz) - 1
The TIM2 Frequency = TIM2 counter clock/(ARR + 1)
= 20 MHz / 4096 = 4.88 KHz
TIM2 Channel1 duty cycle = (TIM2_CCR1/ TIM2_ARR)* 100 = 33.33%
Note:
SystemCoreClock variable holds HCLK frequency and is defined in system_stm32h7xx.c file.
Each time the core clock (HCLK) changes, user had to update SystemCoreClock
variable value. Otherwise, any configuration based on this variable will be incorrect.
This variable is updated in three ways:
1) by calling CMSIS function SystemCoreClockUpdate()
2) by calling HAL API function HAL_RCC_GetSysClockFreq()
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
----------------------------------------------------------------------- */
TimHandle.Instance = TIM2;
TimHandle.Init.Period = 0xFFFF;
TimHandle.Init.Prescaler = ((SystemCoreClock/2) / (1000)) - 1;
TimHandle.Init.ClockDivision = 0;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
if(HAL_TIM_PWM_Init(&TimHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/*##-2- Configure the PWM channel 1 ########################################*/
sConfig.OCMode = TIM_OCMODE_PWM1;
sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfig.Pulse = 0xFFF;
if(HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_1) != HAL_OK)
{
/* Configuration Error */
Error_Handler();
}
/*##-3- Start PWM signal generation in DMA mode ############################*/
if( HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_1) != HAL_OK)
{
/* Starting PWM generation Error */
Error_Handler();
}
/*##-4- Start DMA Burst transfer ###########################################*/
//HAL_TIM_DMABurst_WriteStart(&TimHandle, TIM_DMABASE_ARR, TIM_DMA_UPDATE,
// (uint32_t*)aSRC_Buffer, TIM_DMABURSTLENGTH_3TRANSFERS);
HAL_TIM_DMABurst_MultiWriteStart(&TimHandle, TIM_DMABASE_ARR, TIM_DMA_UPDATE,
(uint32_t*)aSRC_Buffer, TIM_DMABURSTLENGTH_3TRANSFERS, 6);
/* Infinite loop */
while (1)
{
}
}
void DMA1_Stream1_IRQHandler(void)
{
/* 传输完成中断 */
if((DMA1->LISR & DMA_FLAG_TCIF1_5) != RESET)
{
/* 清除标志 */
DMA1->LIFCR = DMA_FLAG_TCIF1_5;
//增加这几行,当首次进入这里后,DMA 第次Burst 3个word变成了每次Burst 1个word
DMA1_Stream1->CR &= ~DMA_SxCR_EN;
DMA1_Stream1->NDTR = 6;
DMA1_Stream1->CR |= DMA_SxCR_EN;
}
/* 半传输完成中断 */
if((DMA1->LISR & DMA_FLAG_HTIF1_5) != RESET)
{
/* 清除标志 */
DMA1->LIFCR = DMA_FLAG_HTIF1_5;
}
/* 传输错误中断 */
if((DMA1->LISR & DMA_FLAG_TEIF1_5) != RESET)
{
/* 清除标志 */
DMA1->LIFCR = DMA_FLAG_TEIF1_5;
}
/* 直接模式错误中断 */
if((DMA1->LISR & DMA_FLAG_DMEIF1_5) != RESET)
{
/* 清除标志 */
DMA1->LIFCR = DMA_FLAG_DMEIF1_5;
}
}
stm32h7xx_hal_msp.c
[C] 纯文本查看 复制代码 void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
GPIO_InitTypeDef GPIO_InitStruct;
static DMA_HandleTypeDef hdma_tim;
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* TIMx clock enable */
TIMx_CLK_ENABLE();
/* Enable GPIO Channel3/3N Clocks */
TIMx_CHANNEL1_GPIO_CLK_ENABLE();
/* Enable DMA clock */
DMAx_CLK_ENABLE();
/* Configure TIM2_Channel1 in output, push-pull & alternate function mode */
GPIO_InitStruct.Pin = GPIO_PIN_CHANNEL1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF_TIMx;
HAL_GPIO_Init(TIMx_GPIO_CHANNEL1_PORT, &GPIO_InitStruct);
/* Set the parameters to be configured */
hdma_tim.Init.Request = DMA_REQUEST_TIM2_UP;
hdma_tim.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim.Init.MemInc = DMA_MINC_ENABLE;
hdma_tim.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD ;
hdma_tim.Init.MemDataAlignment = DMA_MDATAALIGN_WORD ;
hdma_tim.Init.Mode = DMA_NORMAL;
hdma_tim.Init.Priority = DMA_PRIORITY_HIGH;
hdma_tim.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;
hdma_tim.Init.MemBurst = DMA_PBURST_SINGLE;
hdma_tim.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
/* Set hdma_tim instance */
hdma_tim.Instance = TIMx_UPDATE_DMA_INST;
/* Link hdma_tim to hdma[TIM_DMA_ID_UPDATE] (update) */
__HAL_LINKDMA(htim, hdma[TIM_DMA_ID_UPDATE], hdma_tim);
/* Initialize TIMx DMA handle */
HAL_DMA_Init(htim->hdma[TIM_DMA_ID_UPDATE]);
/*##-2- Configure the NVIC for DMA #########################################*/
/* NVIC configuration for DMA transfer complete interrupt */
HAL_NVIC_SetPriority(TIMx_DMA_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIMx_DMA_IRQn);
}
能帮我看一下应该如何设置吗?谢谢 |