Forum: Mikrocontroller und Digitale Elektronik Timer Probleme mit ATtiny1606


von Matthias H. (mhage)


Lesenswert?

Hallo,

ich versuche gerade ein Programm auf den ATtiny1606 zu portieren. Im 
ursprünglichen Projekt, geschrieben für ATmega328, Wird der Timer 
gestartet und im weiteren Programmverlauf gestoppt, das Interval neu 
berechnet und neu gestartet.

Das versuche ich gerade bei dem 1606 mit dem TCA0 zu konfigurieren.
Leider wird der Interrupt scheinbar nicht korrekt ausgeführt und wenn, 
dann hat die Variable timerInterval keinen Einfluss auf die Zeit. Hier 
mein Versuch.
1
void startTimer(uint32_t timerInterval)
2
{
3
  if ( timerInterval > 0 )
4
  {
5
      TCA0.SINGLE.CTRLA = 0;                                        // Stop timer
6
      TCA0.SINGLE.INTFLAGS = TCA_SINGLE_CMP0_bm;                    // Clear interrupt flag
7
8
      TCA0.SINGLE.CTRLB  = TCA_SINGLE_ALUPD_bm;                     // enabled Auto Lock Update
9
      TCA0.SINGLE.CTRLB  = TCA_SINGLE_WGMODE_FRQ_gc;                // Frequency Mode
10
      TCA0.SINGLE.CTRLA  = TCA_SINGLE_CLKSEL_DIV8_gc;               // Prescaler
11
            
12
      if (timerInterval > 65535) {
13
          TCA0.SINGLE.CMP0H = (65535 >> 8);
14
          TCA0.SINGLE.CMP0L = (65535 & 0xFF);
15
      } else {
16
          TCA0.SINGLE.CMP0H = (timerInterval >> 8);
17
          TCA0.SINGLE.CMP0L = (timerInterval & 0xFF);
18
      }
19
20
      TCA0.SINGLE.INTCTRL = TCA_SINGLE_CMP0_bm;
21
      TCA0.SINGLE.CTRLA |= TCA_SINGLE_ENABLE_bm;                    // enable TCA module
22
      timerOn = true;                                                              
23
       
24
  }
25
26
}
27
28
void stopTimer()
29
{
30
  TCA0.SINGLE.CTRLA = 0;                            // Stop timer
31
  TCA0.SINGLE.INTCTRL = 0;                          // Disable interrupts
32
  timerOn = false;
33
  
34
}
35
36
ISR (TCA0_CMP0_vect)
37
{
38
  TCA0.SINGLE.INTFLAGS = TCA_SINGLE_CMP0_bm;  // Clear interrupt flag
39
}


Bin jetzt bereits knapp eine Woche dabei diesen Timer zu bändigen, aber 
ohne Erfolg. Hoffe, Ihr könnt mir helfen.


VG
Matze

von Veit D. (devil-elec)


Lesenswert?

Arduino Forum Crossposting!
Mach das nicht. Sonst arbeiten 2 oder mehr Foren gegeneinander.

: Bearbeitet durch User
von Georg M. (g_m)


Lesenswert?

1
  (65535 >> 8)
2
  (65535 & 0xFF)

Optimiert eigentlich der Compiler solche Ausdrücke?

von Veit D. (devil-elec)


Lesenswert?

Hallo,

es sind Konstanten, deswegen kann er das einfach so optimieren.
Kannste gern ausprobieren mit https://godbolt.org/

Kann man sowieso eindampfen auf TCA0.SINGLE.CMP0 = 65535;

: Bearbeitet durch User
von S. L. (sldt)


Lesenswert?

Ich würde es ja mal nebenher ausprobieren, aber selbst ein Hauptprogramm 
dazu schreiben? Ist etwas viel verlangt, Matthias H.

von Matthias H. (mhage)


Lesenswert?

Das hier war mein Code zum testen....
1
#define COIL_PIN A1  // Beispiel: Pin A1 für die Spule
2
#define timerInterval 2000
3
bool timerOn = false;
4
5
void setup() {
6
  pinMode(COIL_PIN, OUTPUT);  // Setzen des Pins als Ausgang
7
  
8
  takeOverTCA0();                                               // This replaces disabling and resettng the timer, required previously.
9
  TCA0.SINGLE.CTRLA = 0;                                        // disable TCA0 and set divider to 1
10
  TCA0.SINGLE.CTRLESET = TCA_SINGLE_CMD_RESET_gc|0x03;           // set CMD to RESET to do a hard reset of TCA0.
11
  
12
  TCA0.SINGLE.CTRLB  = TCA_SINGLE_WGMODE_FRQ_gc;                // Frequency Mode
13
  TCA0.SINGLE.CTRLA  = TCA_SINGLE_CLKSEL_DIV8_gc;               // Prescaler
14
15
  TCA0.SINGLE.INTCTRL = TCA_SINGLE_CMP0_bm;
16
  
17
  sei();
18
  startTimer();
19
}
20
21
void loop() {
22
  if (!timerOn) {
23
    startTimer();
24
  }
25
}
26
27
void startTimer() {
28
  if ( timerInterval > 0 )
29
  {
30
      
31
      if (timerInterval > 65535) {
32
          TCA0.SINGLE.CMP0BUF = 65535;
33
      } else {
34
          TCA0.SINGLE.CMP0BUF = timerInterval;
35
      }
36
     
37
      TCA0.SINGLE.CTRLA |= TCA_SINGLE_ENABLE_bm;                    // enable TCA module
38
      TCA0.SINGLE.INTFLAGS = TCA_SINGLE_CMP0_bm;                    // Clear interrupt flag
39
      timerOn = true;                                                              
40
       
41
  }
42
}
43
44
void stopTimer() {
45
  TCA0.SINGLE.CTRLA = 0;  // Stop timer
46
  TCA0.SINGLE.INTCTRL = 0;  // Disable interrupts
47
  timerOn = false;
48
  
49
}
50
51
// Interrupt Service Routine für den Timer
52
ISR(TCA0_CMP0_vect) {
53
  digitalWriteFast(COIL_PIN, !digitalReadFast(COIL_PIN));
54
   
55
  stopTimer();
56
    
57
}

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

Matthias H. schrieb:
> Das hier war mein Code zum testen....

'timerOn' sollte m.E. als volatile deklariert werden:

> bool timerOn = false;

Denn
> ISR(TCA0_CMP0_vect) {
(...)
>   stopTimer();

mit:
> void stopTimer() {
(...)
>   timerOn = false;

...und es zeigt sich einmal mehr, dass der gesamte Code relevant für die 
Fehlersuche ist... :-/


Grüßle,
Volker

: Bearbeitet durch User
von S. L. (sldt)


Lesenswert?

Autsch - Arduino: da bin ich eigentlich überfordert.
  Aber:

Wenn der TCA-Interrupt in stopTimer abgeschaltet wird, dann sollte er in 
startTimer wieder eingeschaltet werden, sonst läuft das Ganze nur 
einmalig.

Ähnlich verhält es sich mit dem Prescaler: auch er verschwindet mit dem 
ersten stopTimer.


PS:
Also 'überfordert' in dem Sinne, dass ich es hier nicht so ohne weiteres 
laufen lassen kann.

: Bearbeitet durch User
von Veit D. (devil-elec)


Lesenswert?

S. L. schrieb:
> Autsch - Arduino: da bin ich eigentlich überfordert.

Ja, dass kann nicht jeder. Damit trennt sich die Spreu vom Weizen.  ;-)
Aber du hast du entscheidende Antwort für den TO schon geliefert.

: Bearbeitet durch User
von S. L. (sldt)


Lesenswert?

> Ja, dass kann nicht jeder.

Yô, bis ich das auf 'normales' C umgeschrieben habe, mit meinen 
Assemblerkenntnissen ... ist der Antrieb schon fast erloschen.

an Matthias M.:
Läge COIL_PIN nicht so ungeschickt, käme man ganz ohne start-stop-ISR 
aus.

Nachtrag:
"Antrieb erloschen" - und wieder höre ich meinen alten Geschichtslehrer 
poltern: "Ihnen fehlt der intellektuelle Impetus!" (Friede seiner Asche)

: Bearbeitet durch User
von Georg M. (g_m)


Lesenswert?

1
  takeOverTCA0();
Was ist das? Das sehe ich zum ersten Mal.

von Veit D. (devil-elec)


Lesenswert?

Georg M. schrieb:
>
1
>   takeOverTCA0();
2
>
> Was ist das? Das sehe ich zum ersten Mal.

Das ist das Problem wenn man Crossposting macht.
Der TO programmiert mit Arduino und verwendet den  megaTinyCore von 
SpenceKonde. Besagte Funktion resetet alle Timer Register, die das 
Arduino Framework vorbelegt.
https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/TakingOverTCA0.md

von Matthias H. (mhage)


Lesenswert?

Das Problem mit dem Timer ist gelöst. Ich habe die Zeiten mitgeschrieben 
und auf Plausibilität geprüft. Die Werte passen soweit.

Vielen Dank für eure Hilfe!

VG

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.