AnsweredAssumed Answered

update values for DMA

Question asked by anton.bogdan on Jun 22, 2016
Hello,
i am modulating the ARR and CCR registers of a timer to get a stream of ppm pulses, and squeeze them togheather.
To be honest i am not very familiar with DMA's .
What i want to achive, is to squeze a sum of radio pulses, into one single ppm stream, and not using a fixed period which is dependent by the dutycycle, therefore at Clive's sugestion from another post to use the dma to modulate the timer registers from a "wave buffer"

Right now, i  am using a example value of 1000 for the ppm pulse, and do the math to extract the ARR values and CCR in order to achive trough the timer a signal of 1000us On Time and 300us rest time, total period 1300us...
With the calculated values in the buffer the timer works as expected

But if i want to update the values in loop,  how should i proceed?
I tryied to use the "Transfer Complete" IRQ handler from the dma channel, and update the buufer values there  ( Buffer[0] and Buffer[2])   is there a way to update this values ?

I am asking this, because in the future i will read the ppm channel values from a receiver, and i am planing to update the dma buffer and the dma will modulate acording the timer register



#define TIM1_DMAR_ADDRESS ((uint32_t)0x40012C4C) /* TIM ARR (Auto Reload Register) address */
 
uint16_t Buffer[6] = {0x79E9, 0x0000, 0x5CA7};
   
 uint32_t mARR, mCCR;
 uint16_t dutcycle;
 uint16_t my_value;
 uint16_t  deadtime;
 float fr;
 
 
 
 
 
 
int main()
{
   
    
 my_value = 1000; // this is my pwm value from a unknow source, and bellow i calculate the desired ARR and CCR values to get 1000us Ton, and 300us Off
 
 
 
 
 deadtime = 300; // fixed microseconds Toff
 fr=(float)1.0f/((float)(my_value+300.0f))*1000000.0f;
 mARR=24000000/((uint16_t)(fr-1)); // Get the desired ARR value for loading into DMA buffer
 dutcycle = (float)(my_value /(float)(my_value + deadtime) )* 100; //Compute dutycycle from 0 to 100%
 mCCR =(uint32_t)(dutcycle*(mARR+1));
 mCCR = (uint32_t)(mCCR/100);
 SRC_Buffer[0] = mARR;
 SRC_Buffer[2] =mCCR;
 
 
 
  RCC_ClocksTypeDef ClksFreq;
  RCC_GetClocksFreq(&ClksFreq); // clock view for debug
 
        
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA, ENABLE);
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
   
   
  
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // this pin is used just to toggle in the dma irg handler for logic analyzer view
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
 GPIO_Init(GPIOA, &GPIO_InitStructure);
 
 
     
  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); 
 
   
  TIM_DeInit(TIM1);
 
  
  DMA_DeInit(DMA1_Channel5);
 
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM1_DMAR_ADDRESS;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)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_Normal;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel5, &DMA_InitStructure);
  
     
   NVIC_InitTypeDef NVIC_InitStructure;
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
   NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_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_OCInitStructure.TIM_OCMode =  TIM_OCMode_PWM1;   
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;         
  TIM_OCInitStructure.TIM_Pulse = 0xFFF; 
  TIM_OC1Init(TIM1, &TIM_OCInitStructure);
 
  
  TIM_DMAConfig(TIM1, TIM_DMABase_ARR, TIM_DMABurstLength_3Transfers);
  TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);
  TIM_Cmd(TIM1, ENABLE);
  TIM_CtrlPWMOutputs(TIM1, ENABLE);
  
 DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
 DMA_Cmd(DMA1_Channel5, ENABLE);
 
  
  
   
  while(1){
    
            
     
      }
}
 
 
 
 
 
 
void DMA1_Channel5_IRQHandler(void)
{
  DMA_ClearITPendingBit( DMA1_IT_TC5);
   
  Buffer[0] = 333; // here i update the new values for the DMA?
  Buffer[2] = 222; // here i update the new values for the DMA?
 
 
}



Outcomes