Wie man einen Timer mit STM32 dynamisch anpasst

Ich habe diesen Timer (TIM4) im PWM-Modus. Ich gebe einen PWM-Kanal aus und möchte etwas warten und dann die neuesten ADC-Samples aus einer DMA-Konvertierung abrufen.

TIM4 -> ARR ist 4096 TIM4 -> CCR1 ist dynamisch, aber es beginnt bei etwa 200

Ich möchte an der steigenden Flanke des TIM4-Impulses beginnen, die Hälfte der Impulse pünktlich abwarten und dann die neuesten und besten DMA-Samples abrufen ... Hier ist ein Ausschnitt dessen, was ich vorhabe:

Wo sich die Dinge zu lösen scheinen, ist die Linie: TIM5->ARR = TIM4->CCR1/2;. Seltsam ist, dass, wenn ich dort eine Konstante einfüge, wie TIM5->ARR = 20;, es gut funktioniert ... Es feuert nicht mitten im On-Puls von TIM4, aber es feuert bei 20 / FCLK, die Sie erwarten würden .

Ich habe DM00236305.pdf gelesen, aber ich konnte nicht verstehen, worüber sie mit Shadow-Registern sprachen, was meiner Meinung nach mein Problem ist. Ich habe auch versucht, dem zu folgen, was hier gesagt wurde, aber das war auch ziemlich vauge, und ich war mir nicht sicher, ob es zutraf, da er eher über Ausgangsvergleiche als über automatische Neuladeregister sprach.

Wie passe ich TIM5->ARR an, um die Hälfte von TIM4->CCR1 zu verfolgen?

void TIM5_IRQHandler(void)
{
  /* USER CODE BEGIN TIM5_IRQn 0 */

    HAL_GPIO_WritePin(GPIOA, TX_Pin, SET);
    HAL_TIM_Base_Stop(&htim5);
    while(!(DMA2->LISR & DMA_LISR_TCIF0));
    motorDummy_FOC.curr_a_sense = ADCValue[0];
    motorDummy_FOC.curr_b_sense = ADCValue[1];
    update_PWM(&motorDummy_FOC);
    HAL_GPIO_WritePin(GPIOA, TX_Pin, RESET);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
  if (htim == &htim4){
    HAL_GPIO_WritePin(GPIOA, RX_Pin, SET);
    GPIOC->ODR = 0b0000000000000110;
    //TIM4->CR1 &= ~(1<<0);
    MX_TIM5_Init();
    TIM5->ARR = (TIM4->CCR1/2);
    HAL_TIM_Base_Start_IT(&htim5);
    HAL_TIM_Base_Start(&htim5);
  }

}
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim){

  if (htim == &htim4){
    GPIOC->ODR = 0b0000000000000100;
    HAL_GPIO_WritePin(GPIOA, RX_Pin, RESET);

  }
}

void update_PWM(motorFOC *c){
  if(c->curr_b_sense < c->curr_b_commanded)
  {c->i_feedback++;}
  else if(c->curr_b_sense > c->curr_b_commanded)
  {c->i_feedback--;}
  TIM4->CCR1 = c->i_feedback;
}
Warum nicht TIM4->CCR2 verwenden?
Die Wahrheit ist, dass dies ein Prototypcode für ein größeres System ist ... Ich habe andere Pläne für TIM4-> CCR2 :)

Antworten (1)

Ich denke, der Fehler, den Sie machen, ist, dass Sie die Timer-Basisuhr in IRQHandler() stoppen und sie in PeriodElapsedCallback() aktualisieren möchten, was innerhalb von IRQHandler() ausgeführt wird.

Das, wonach Sie suchen, ist das Makro __HAL_TIM_SET_AUTORELOAD .

In *_hal_tim.h-Dateien sind einzelne Makros definiert, um die ARR-, CCR- usw. Werte zu aktualisieren. Das Einzige, was Sie tun müssen, ist, den CCR-Wert dynamisch zu erfassen und das Makro zu aktualisieren, Sie müssen den Timer nicht stoppen und starten..! Das gleiche Problem wird hier angesprochen .

Oh, das sieht so aus! Ich kann es kaum erwarten, es morgen früh zu testen, danke. Ich wünschte, ich könnte die Syntax des Makros verstehen, aber das wird ein bisschen mehr Graben erfordern
Ja! das ist das Hauptproblem bei HAL! Es ist schwer, sich durch die Innereien zu wühlen, man kann nur so weit gehen! Bitte erläutern Sie hier, ob Sie herausgefunden haben, wie das Makro definiert ist. Viel Glück!