Wie verwende ich TIMER 2 als einfachen Zähler in STM8S103F3?

Ich bin neu bei STM8S und noch nicht so gut in der Mikrocontroller-Programmierung im Allgemeinen. Ich versuche, etwas über Timer / Zähler in Mikrocontrollern zu lernen.

Ich habe folgenden Code geschrieben, um jede Sekunde eine LED umzuschalten, die am PB5-Pin angeschlossen ist.

#include "stm8s.h"

int main() {
  // Default clock is HSI/8 = 2MHz

  PB_DDR |= (1 << PB5); // PB5 is now output
  PB_CR1 |= (1 << PB5); // PB5 is now pushpull

  TIM2_PSCR = 0b00000111; //  Prescaler = 128
  TIM2_CR1 |= (1 << TIM2_CR1_CEN); // Enable TIM2

  while (1) {
    if ( ( ((uint16_t)TIM2_CNTRH << 8) + (uint16_t)TIM2_CNTRL ) >= 15625 ) {
      // Reset counter back to 0
      TIM2_CNTRH = 0;
      TIM2_CNTRL = 0;

      // Toggle LED.
      PB_ODR ^= (1 << PB5);
    }
  }
}

Mein Mikrocontroller ist nicht mit einer externen Uhr verbunden und verwendet die interne Uhr für den Betrieb.

Nachdem ich das Datenblatt gelesen habe, sehe ich, dass der MCU-Takt standardmäßig HSI / 8 = 2 MHz beträgt. Ich habe 128 als Prescaler für TIM2 eingestellt. Der TIM2-Zähler wird also alle 64 us erhöht. Wenn es also 15625 erreicht, ist es 1 Sekunde (64 * 15625 = 1000000 us = 1 s).

Also nahm ich an, dass die LED jede Sekunde umschaltet.

Das Problem ist, dass die LED die ganze Zeit an bleibt.

Kann mir jemand helfen, das Problem mit meinem Code zu identifizieren?

Vielen Dank im Voraus.

Können Sie dies debuggen und den LED-Pin überwachen? Wenn es im Debugger nicht funktioniert, haben Sie zumindest ausgeschlossen, dass das Problem nicht von Ihrer Hardware herrührt.
Leider muss ich noch etwas über das Debuggen lernen :) Die LED blinkt jedoch gut, wenn ich das Programm mit einer einfachen forSchleife ausführe, um die Verzögerung zu erzeugen.

Antworten (2)

Nachdem ich das Referenzhandbuch weiter gelesen hatte, stellte ich fest, dass wir UGdas Bit setzen müssen TIM2_EGR, um das Ereignis zu generieren und zu aktualisieren, damit die MCU den Prescaler-Wert für TIMER 4 übernimmt.

TIM2_EGR |= (1 << TIM2_EGR_UG);

Der aktualisierte Code lautet also:

#include "stm8s.h"

int main() {
  // Default clock is HSI/8 = 2MHz

  PB_DDR |= (1 << PB5); // PB5 is now output
  PB_CR1 |= (1 << PB5); // PB5 is now pushpull

  TIM2_PSCR = 0b00000111; //  Prescaler = 128
  TIM2_EGR |= (1 << TIM2_EGR_UG); // Generate an update event so prescaler value will be taken into account.
  TIM2_CR1 |= (1 << TIM2_CR1_CEN); // Enable TIM2

  while (1) {
    if ( ( ((uint16_t)TIM2_CNTRH << 8) + (uint16_t)TIM2_CNTRL ) >= 15625 ) {
      // Reset counter back to 0
      TIM2_CNTRH = 0;
      TIM2_CNTRL = 0;

      // Toggle LED.
      PB_ODR ^= (1 << PB5);
    }
  }
}

Jetzt fing die LED an, jede Sekunde umzuschalten !!

Nehmen Sie kleine Änderungen am Code vor: Enthaltener Timer 2-Überlauf-Interrupt.

NOTIZ :

  • Das Programm wurde mit dem SDCC-Compiler kompiliert und der Mikrocontroller mit ST Visual Programmer (STVP) geflasht.

  • Stellen Sie sicher, dass Sie die benutzerdefinierte Header-Datei hier herunterladen: https://github.com/ElectronicCircuitDesignTools/STM8S103F3P6/blob/303d53aded5b4b91b23d1356df89df0c97968d30/stm8s103f3p6_register_map.h

      #define using_io_ports 1
      #define using_tim2 1
      #define TIM2_OVF 13
    
      #include "stm8s103f3p6_register_map.h"
    
      unsigned int prescaler = 4;
      unsigned char led_state = 0x00;
    
      void isr_timer_2_overflow() __interrupt(TIM2_OVF)
      {
          PD_ODR ^= ( 1 << ODR4 );
          TIM2_CNTRH = (unsigned char)(3035 >> 8);        //  Load starting value of timer 2 ( high byte ).
          TIM2_CNTRL = (unsigned char)(3035 & 0xFF);      //  Load starting value of timer 2 ( low byte ).
          TIM2_SR1 = 0x00;                    //  Clear the update interrupt flag.
      }
    
      void main( void )
      {
          PD_DDR = ( 1 << ODR4 );
          PD_CR1 = ( 1 << C14 );
    
          __asm__("sim");             //  Disable all interrupts.
    
          TIM2_CNTRL = 0;             //  Clear Timer 2 counter register ( high byte ).
          TIM2_CNTRH = 0;             //  Clear Timer 2 counter register ( low byte ).
    
          TIM2_PSCR = 0x04;           //  Set Timer 2 clock speed = f_master / 4.
          TIM2_EGR = 0x01;            //  Enable update event.
          TIM2_IER = 0x01;            //  Enable update interrupt.
          TIM2_SR1 = 0x00;            //  Clear the update interrupt flag.
          TIM2_CR1 = 0x01;            //  Enable Timer 2 operation as counter.
    
          __asm__("rim");
    
          while(1)
          {
    
          }
      }
    
PATRICK A JOSEPH – Hi, das sieht aus wie dein GitHub-Repo, auf das du verlinkt hast – ist das richtig? In diesem Fall müssen wir Ihrer Antwort eine geeignete Offenlegung hinzufügen, um die Website-Regeln einzuhalten. Da Sie ein neuer Benutzer sind, antworten Sie bitte unten in einem Kommentar und ich helfe Ihnen dabei. Danke.