Wie verwende ich den Timer 3 eines STM32F030F4 im Eingangserfassungsmodus, um die Impulsbreite zu messen?

Aktualisieren

Ich habe das Blockdiagramm des Timers 3 noch einmal überprüft

Blockdiagramm

Es sieht so aus, als gäbe es keine Verbindung zwischen channel 4und dem Triggereingang TRGI. Ist das richtig?

Kann ich Kanal 4 für den Gated-Modus verwenden?

ursprüngliche Frage

Ich habe das folgende Signal mit unterschiedlicher Impulsbreite. (hoch)

Impulse

Ich möchte die Impulsbreite mit einem STM32F030F4 messen (Link wegen Reputationslimit entfernt).

Das Signal wird an Pin 14, PB1 angeschlossen. Ich habe überprüft, dass das Signal direkt am Pin des µC erfasst werden kann, also sollte es dort sein. Ich möchte Timer 3 verwenden, weil sein Kanal 4 mit diesem Pin verbunden ist.

Kapitel 13.3.19 TIMx und externe Trigger-Synchronisation des Referenzhandbuchs beschreibt einen Modus, der genau das ist, was ich suche.

Slave-Modus: Gated-Modus

Der Zähler kann abhängig vom Pegel eines ausgewählten Eingangs aktiviert werden.

Auch dafür gibt es ein Beispiel:

A.8.13 Codebeispiel für den Gated-Modus

/* (1) Configure channel 1 to detect low level on the TI1 input       
by writing CC1S = ‘01’,       
and configure the input filter duration by writing the IC1F[3:0]       
bits in the TIMx_CCMR1 register (if no filter is needed,       
keep IC1F=0000). */ 

/* (2) Select polarity by writing CC1P=1 in the TIMx_CCER register */ 

/* (3) Configure the timer in gated mode by writing SMS=101       
Select TI1 as the trigger input source by writing TS=101       
in the TIMx_SMCR register. */ 

/* (4) Set prescaler to 12000-1 in order to get an increment each 250us */ 

/* (5) Enable the counter by writing CEN=1 in the TIMx_CR1 register. */ 

TIMx->CCMR1 |= TIM_CCMR1_CC1S_0; /* (1)*/ 
TIMx->CCER |= TIM_CCER_CC1P; /* (2) */ 
TIMx->SMCR |= TIM_SMCR_SMS_2 | TIM_SMCR_SMS_0 | TIM_SMCR_TS_2 | TIM_SMCR_TS_0; /* (3) */ 
TIMx->PSC = 11999; /* (4) */ 
TIMx->CR1 |= TIM_CR1_CEN; /* (5) */

Ich habe versucht, das Beispiel an meine Bedürfnisse anzupassen und es sieht so aus:

// based on example A.8.13

/* (1) Configure channel 4 to detect low level on the TI4 input
 * by writing CC4S = ‘01’,
 * and configure the input filter duration by writing the IC1F[3:0]
 * bits in the TIMx_CCMR1 register (if no filter is needed,
 * keep IC1F=0000). */

/* (2) Select polarity by writing CC4P=1 in the TIMx_CCER register */

/* (3) Configure the timer in gated mode by writing SMS=101
 * Select TI1 as the trigger input source by writing TS=101
 * in the TIMx_SMCR register. */

/* (4) Set prescaler to 12000-1 in order to get an increment each 250us */

/* (5) Enable the counter by writing CEN=1 in the TIMx_CR1 register. */

TIM3->CCMR2 |= TIM_CCMR2_CC4S_0; /* (1) */
TIM3->CCER |= TIM_CCER_CC4P; /* (2) */
TIM3->SMCR |= TIM_SMCR_SMS_2 | TIM_SMCR_SMS_0 | TIM_SMCR_TS_2 | TIM_SMCR_TS_0; /* (3) */
TIM3->PSC = 11999; /* (4) */
TIM3->CR1 |= TIM_CR1_CEN; /* (5) */

Ich würde erwarten, dass sich das Zählerregister von Timer 3 TIM3->CNTim Laufe der Zeit ändert, wenn die Impulse hereinkitzeln.

Ändert sich jedoch TIM3->CNTüberhaupt nicht.

Hier ist die Konfiguration, von der ich vermute, dass sie fehlerhaft ist

GPIO

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(tim_baseHandle->Instance==TIM3)
  {
  /* USER CODE BEGIN TIM3_MspInit 0 */

  /* USER CODE END TIM3_MspInit 0 */
    /* Peripheral clock enable */
      __TIM3_CLK_ENABLE();

    /**TIM3 GPIO Configuration
    PB1     ------> TIM3_CH4
    */
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF1_TIM3;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN TIM3_MspInit 1 */

  /* USER CODE END TIM3_MspInit 1 */
  }
}

Timer

/* TIM3 init function */
void MX_TIM3_Init(void)
{

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_SlaveConfigTypeDef sSlaveConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_IC_InitTypeDef sConfigIC;

  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 0;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 0;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }

  if (HAL_TIM_IC_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }

  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED;
  sSlaveConfig.InputTrigger = TIM_TS_ITR0;
  if (HAL_TIM_SlaveConfigSynchronization(&htim3, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }

  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = 0;
  if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }

}

Beim Debuggen kann ich sehen, wie sich die Konfigurationsregister ändern und ihre Werte lesen/schreiben, aber das Zählerregister erhöht sich nicht.

Wo rufst du an __TIM3_CLK_ENABLE();?
@BenceKaulics Entschuldigung, dass ich nicht den vollständigen Code gepostet habe, Frage bearbeitet. Ich habe auch überprüft, ob beide Initialisierungen aufgerufen werden, indem ich jeweils Haltepunkte gesetzt habe. Spielt die Reihenfolge eine Rolle? Der GPIO geht zuerst.
Die Reihenfolge ist so in Ordnung.
@BenceKaulics Ich habe das Blockdiagramm noch einmal überprüft und vielleicht ist das, was ich versuche, mit diesem Timer und Kanal nicht einmal möglich?
Ich kenne diese spezielle Funktion nicht, aber der Trigger-Controller scheint mit allen Kanälen verbunden zu sein. Kanal 4 kann meiner Meinung nach keinen Trigger geben, aber das ist nicht das Problem. Ihre Triggerquelle ist ITR0, aber ich weiß nicht, was diese Leitung ansteuern soll. Ihr Timer empfängt wahrscheinlich keinen Trigger und wird nicht aktiviert. Sie sollten herausfinden, woher ITR0 kommen sollte.
Oder vergessen Sie die getriggerte Freigabe und starten Sie einfach die Eingangserfassung auf dem Kanal mit:HAL_StatusTypeDef HAL_TIM_IC_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
@BenceKaulics Nun, wenn Kanal 4 keinen Trigger geben kann, ist das ein Problem, denn genau das möchte ich tun. Können Sie erklären, wie Kanal 4 mit dem Trigger verbunden ist, weil ich es nicht sehe. Und ich glaube nicht, dass dies ITR0die Triggerquelle in meinem Code ist, da der Beispielcode die Triggerquelle explizit auf setzt TS=101(siehe Kommentare). Wie auch immer, es gibt keinen Wert im Referenzhandbuch für die Triggerquelle, um Kanal 4 zu verwenden, was mich vermuten lässt, dass dies unmöglich ist. Wie wird HAL_TIM_IC_Startes funktionieren?
In deinem Code sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED; sSlaveConfig.InputTrigger = TIM_TS_ITR0;. ITR0 scheint also der Auslöser zu sein. Entschuldigung, ich habe mich mit dem Trigger-Controller geirrt, er treibt nur den CNT-Zähler an, der von allen Kanälen erfasst werden kann.

Antworten (1)

Es sieht so aus, als wäre die Verwendung des Eingangserfassungsmodus nicht möglich, da Kanal 4 nicht als Trigger verwendet werden kann.

Ich gebe auf. Zu viele verschiedene Beispiele im Web mit zu vielen verschiedenen Konfigurationstools, Toolchains usw.