cancel
Showing results for 
Search instead for 
Did you mean: 

Use DMAR to update CCR1~4 registers

SongShu007
Associate II

I now need to update the CCR1~CCR3 register at the same time with DMA with DMAR register, I use STM32F103C8T6, I use STM32F10x_StdPeriph_Lib_V3.6.0\Project\STM32F10x_StdPeriph_Examples\TIM\DMABurst example, in the example DMA is Normal mode, I need to keep updating the CCRx registers, so I changed the DMA to Circular mode, but the CCRx registers are not updated as I expected, they are misaligned

 

#define TIM1_DMAR_ADDRESS ((uint32_t)0x40012C4C) /* TIM ARR (Auto Reload Register) address */

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
GPIO_InitTypeDef         GPIO_InitStructure;
DMA_InitTypeDef          DMA_InitStructure;
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef        TIM_OCInitStructure;
uint16_t SRC_Buffer[6] = {0x1234, 0x5678, 0xABCD};

int main(void)
{
  /* TIM1 and GPIOA clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA, ENABLE);

  /* DMA clock enable */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  
  /* GPIOA Configuration: Channel 1 as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);  

  /* TIM1 DeInit */
  TIM_DeInit(TIM1);

  /* DMA1 Channel5 Config */
  DMA_DeInit(DMA1_Channel5);

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM1_DMAR_ADDRESS; 
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SRC_Buffer; 
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  DMA_InitStructure.DMA_BufferSize = 3;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel5, &DMA_InitStructure);
  
  TIM_TimeBaseStructure.TIM_Period = 0xFFFF;          
  TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (SystemCoreClock / 24000000) - 1;       
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;    
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

  /* TIM Configuration in PWM Mode */
  TIM_OCInitStructure.TIM_OCMode =  TIM_OCMode_PWM1;    
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;          
  TIM_OCInitStructure.TIM_Pulse = 0xFFF;  
  TIM_OC1Init(TIM1, &TIM_OCInitStructure); 

  /* TIM1 DMAR Base register and DMA Burst Length Config */
  TIM_DMAConfig(TIM1, TIM_DMABase_CCR1, TIM_DMABurstLength_3Transfers);

  /* TIM1 DMA Update enable */
  TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);

  /* TIM1 enable */
  TIM_Cmd(TIM1, ENABLE);
  
  /* TIM1 PWM Outputs Enable */
  TIM_CtrlPWMOutputs(TIM1, ENABLE);

  /* DMA1 Channel5 enable */
  DMA_Cmd(DMA1_Channel5, ENABLE);

  /* Wait until DMA1 Channel5 end of Transfer */
  while (!DMA_GetFlagStatus(DMA1_FLAG_TC5))
  {
  }

  /* Infinite loop */ 
  while(1)
  {
  }
}

 

 

6 REPLIES 6

What do you mean by "misaligned"?

Read out and check/post content of TIM and DMA registers.

JW

"misaligned" is

first time

CCR1=0x1234

CCR2=0x5678

CCR3=0xABCD

but second

CCR1=0xABCD

CCR2=0x1234

CCR3=0x5678

And then

CCR1=0x5678

CCR2=0xABCD

CCR3=0x1234

 

You can run my code to see the phenomenon

I don't use SPL.

What happens, if you use

TIM_DMAConfig(TIM1, TIM_DMABase_CCR1, TIM_DMABurstLength_2Transfers);

?

JW

HMoens
Associate II

I'm noticing the same issue in my project. It seems to only happen in the debugger mode when I'm live viewing the CCR changes. Maybe your code works as intended when you aren't checking on it. 

I attached a screen recording to show what I mean. I'm basically changing rapidly between 50% duty cycle and 100%. This should look like a stable 75% on the scope. It also does before I go into the live view. Then when I go to live view it starts messing up

Nice catch!

Yes, debugging is intrusive - but I did not guess that that might be the case in the original post.

JW