Forum: Mikrocontroller und Digitale Elektronik ATtiny series 1 TCA0


von Lars H. (larsfcfa)


Lesenswert?

Hallo AVR-Profis,

ich habe eine Frage zur Nutzung der Timer in den Series 1 ATtinys 
(momentan ATTiny814).
Ich möchte gerne z.B. alle 64 CPU-Take ein Trigger-Signal ausgeben und 
dann jeden 4096ten Durchlauf davon in einen IRQ Daten übertragen.

Überlicherweise eignet sich dafür der SINGLE_OVF Mode:
1
void TCA0_init(void)
2
{
3
  /* enable overflow interrupt */
4
  TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm;
5
  /* set Normal mode */
6
  TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_NORMAL_gc;
7
  /* disable event counting */
8
  TCA0.SINGLE.EVCTRL &= ~(TCA_SINGLE_CNTEI_bm);
9
  /* set the period */
10
  TCA0.SINGLE.PER = 4096;
11
  TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV64_gc    /* set clock source (sys_clk/64) */
12
  | TCA_SINGLE_ENABLE_bm;                /* start timer */
13
}

Ich möchte nun also an einem Pin, z.B. PB0 =(WO0) den Timer-Takt als 
Trigger ausgeben.
Wie muss ich den TCA0 dazu noch konfigurieren, oder geht das mit dem 
Event-System?
Wer kann mir das weiterhelfen?
PORTMUX scheint beim ATTiny814 nicht zu funktionieren:
1
 PORTMUX.TCAROUTEA = PORTMUX_TCA0_PORTB_gc;

Die ISR steht grundsätzlich auch schon:
1
ISR(TCA0_OVF_vect)
2
{
3
  PORTB.OUTTGL = PIN1_BP; //Pin PB1 toggeln)
4
  TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm;
5
}

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

Geht das nicht mit dem Split-Mode?

von S. Landolt (Gast)


Lesenswert?

Zu dem ATtiny841 kann ich nichts Definitives sagen, aber das 'Register 
Summary' für den TCA0 sieht, zumindest auf den ersten Blick, bei den 
AVRnDx gleich aus, und dort läuft es. Falls es weiterhilft, hier der 
Assemblercode, sollte allgemeinverständlich sein:
1
.org    TCA0_HUNF_vect
2
    lds     tmp0,TCA0_SPLIT_INTFLAGS
3
    sts     TCA0_SPLIT_INTFLAGS,tmp0
4
    reti
5
.
6
.
7
.
8
    sbi     VPORTA_DIR,0
9
    puti    TCA0_SPLIT_CTRLD,0b0000000_1                ; SPLITM
10
    puti    TCA0_SPLIT_CTRLA,0b0_000_100_1              ; /16, enable
11
    puti    TCA0_SPLIT_CTRLB,0b0_000_0_001              ; LCMP0EN
12
    puti    TCA0_SPLIT_LPER,4-1                         ; -> /64
13
    puti    TCA0_SPLIT_LCMP0,2
14
    puti    TCA0_SPLIT_HPER,256-1                       ; -> /4096
15
    puti    TCA0_SPLIT_INTCTRL,0b0_000_00_10            ; HUNF
16
    sei

von Lars H. (larsfcfa)


Lesenswert?

Hallo,

vielen Dank für die schnelle Antwort!
Den Split mode hatte ich wegen der schlechter dokumentierten Handhabung 
und Aufteilung 16bit-> 2x8Bit bei 4096 Schritten bislang nicht 
berücksichtigt.
Ich habe es letztlich geschafft, die passenden gcc-Makros dazu zu 
finden.

So wie ich es verstehe, nutzt du den Split-Mode (der ja nur 8-Bit hat) 
um in 2 Schritten auf 4096 zu kommen, richtig?

Und die beiden 8-Bit "Pseudo-PWMs" (mit Länge 2) werden nun auf den WO0 
und WO1 ausgegeben und könnten als Trigger genutzt werden?
Wird auch der TCA0-Haupttakt (CLKSEL_DIV16) auf einem Pin ausgegeben, 
denn den brauche ich ja auf jeden Fall?

Die zugehörige ISR, läuft die mit (CLKSEL_DIV16) oder 
CLKSEL_DIV16/4/256?

von S. Landolt (Gast)


Lesenswert?

So richtig verstehe ich die Fragen nicht; ich will es mal aus meiner 
Sicht versuchen:

> Ich möchte gerne z.B. alle 64 CPU-Take ein Trigger-Signal
> ausgeben und dann jeden 4096ten Durchlauf davon in einen
> IRQ Daten übertragen.

Diese Anforderung war der Ausgangspunkt: TCA0 läuft mit dem Vorteiler 16 
(CTRLA); im Low-Byte wird weiter geteilt durch 4 und eine PWM (mit /64) 
für das verlangte 'Trigger-Signal' erzeugt, im High-Byte wird weiter 
geteilt durch 256 für den Interrupt (mit /4096).
  Falls das
> jeden 4096ten Durchlauf davon
sich jedoch nicht auf den CPU-Takt (wie von mir interpretiert), sondern 
auf das Triggersignal bezieht, reichen die 8-bit natürlich nicht aus - 
dann wäre vielleicht ein Softwarezähler auf 16 in der ISR eine Lösung.

von Lars H. (larsfcfa)


Lesenswert?

Hallo,

ich habe das mal ausprobiert:
1
  TCA0.SPLIT.INTCTRL = TCA_SPLIT_LUNF_bm;   // if need interrupt
2
  TCA0.SPLIT.CTRLB = TCA_SPLIT_LCMP0OV_bm    // Low overflow
3
      | TCA_SPLIT_LCMP0EN_bm;    // WO0 output enable

Damit bekomme ich einen IRQ und der Wo0 toggled wie gewünscht, so weit 
sehr gut.
Da der Split-mode aber nur 8 bit hat, habe ich maximal 256 Düchläufe der 
ISR. ich brauche aber 4096.
Hat einer dazu eine Idee?

von Lars H. (larsfcfa)


Lesenswert?

Unsere Antworten haben sich überschnitten, deine Lösung läuft gut, aber 
ja ich benötige 4096 ISR-Durchläufe.

Beim Atmega328/Tiny85 ging so was doch mit dem TIMER0_COMPA_vect,
1
  // CTC with OCR0A as TOP
2
  TCCR0A = (1 << WGM01);
3
  // clk_io/1024 (From prescaler)
4
  TCCR0B = ((1 << CS02) | (1 << CS00));
5
  // Generate an interrupt every 4096 clock cycles
6
  OCR0A = 3;
7
  // Enable Timer/Counter0 Compare Match A interrupt
8
  TIMSK0 |= (1 << OCIE0A);

ich dachte so was sollten die neuen auch beherrschen, irre ich mich?

von S. Landolt (Gast)


Lesenswert?

So ad hoc sehe ich keine Lösung, wenn nicht ein weiterer der bei den 
Tinies raren Timer geopfert werden soll.
  Aber wie wäre es mit dem vorgeschlagenen Zähler in Software? Oder ist 
die Auslastung so hoch?

von Peter D. (peda)


Lesenswert?

Lars H. schrieb:
> Ich möchte gerne z.B. alle 64 CPU-Take ein Trigger-Signal ausgeben und
> dann jeden 4096ten Durchlauf davon in einen IRQ Daten übertragen.

Alle 64 Zyklen ein Interrupt, ist schon recht heftige CPU-Last und 
dürfte auch einen hohen Jitter haben. Außerdem besteht die Gefahr, daß 
andere Interrupts in die Suppe spucken.
Ich würde daher 2 Timer benutzen. Der eine macht den 64 Zyklen-Puls in 
Hardware (Waveform Generation Mode), d.h. ganz ohne CPU-Last.
Der andere Timer macht dann die Aktion alle 262144 Zyklen per Interrupt, 
also völlig zeitunkritisch.
Ob man das per Split-Mode machen kann, weiß ich nicht. Die Timer im 
Tiny814 unterscheiden sich ja extrem zu denen in den Classic-AVRs.

von S. Landolt (Gast)


Lesenswert?

> vielleicht ein Softwarezähler auf 16 in der ISR

Das sollte "auf 64" heißen, bezöge sich ja auf das Triggersignal.

von S. Landolt (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Alle 64 Zyklen ein Interrupt

Die 64 Takte gelten für das Trigger-Signal, welches in Hardware per PWM 
erzeugt wird. Die ISR wird derzeit alle 4096 Takte aufgerufen, da 
könnte/sollte dann eine weitere Teilung per Software möglich sein.

von Lars H. (larsfcfa)


Lesenswert?

Wenn es sein muss, kann ich den TCB auch mit nutzen.
Also könnte eine Lösung folgendes sein:?

1. TCA mit Prescaler (z.B. 64) laufen lassen
2. TCB im 8-bit PWM mit diesem Takt das Trigger-Signal erzeugen
3. mit dem TCA den Overlow-mode bei 4096 einen IRQ auslösen, der dann 
entsprechen die Datenausgabe übernimmt.

Was denkt ihr, ginge das?

von Georg M. (g_m)


Lesenswert?

Peter D. schrieb:
> Die Timer im
> Tiny814 unterscheiden sich ja extrem zu denen in den Classic-AVRs.

Was heißt hier "extrem"?

Der TCA ist ein Universaltimer und kann selbstverständlich alles, was 
frühere AVR Timer/Counter machen.
Für weniger anspruchsvolle Aufgaben (z.B. Periodic Interrupt) gibt es 
zusätzlich den TCB, der auch synchron mit dem TCA laufen kann.

von S. Landolt (Gast)


Lesenswert?

Sicher geht das.
(wenn der einzige TCB ohnehin nicht anderweitig benötigt wird)

von Lars H. (larsfcfa)


Lesenswert?

Wenn der TCB genutzt wird, muss ich allerdings einen anderen Port 
nutzen, das wäre ungünstig.

>Der TCA ist ein Universaltimer und kann selbstverständlich alles, was
frühere AVR Timer/Counter machen.

Das versuche ich ja und - soweit ich das sehen kann - hatte der ATtiny85 
Timer0 noch die von mir gesuchte Möglichkeit:
1
 
2
// CTC with OCR0A as TOP
3
  TCCR0A = (1 << WGM01);
4
  // clk_io/64 (From prescaler)
5
  TCCR0B = (1 << CS01) | (1 << CS00);
6
  // Generate an interrupt every (Value_CTC_TOP + 1) * 64 clock cycles
7
  OCR0A = Value_CTC_TOP;
Damit kann - wie von mir benötigt - so weit ich weiß das Triggersignal 
am PB4 ausgegeben werden


Sowas scheint der neue TCA beim ATtiny814 nicht (mehr) zu können, oder 
blicke ich es nur nicht?

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

Es werden doch zwei verschiedene Frequenzen benötigt, oder habe ich das 
falsch verstanden? F_CPU/64 fur das Triggersignal sowie F_CPU/262144 für 
diese Datensende-ISR?
  Und zwei Frequenzen mit dem ATtiny85.Timer0? Nicht dass ich wüsste.

von S. Landolt (Gast)


Lesenswert?

> ... allerdings einen anderen Port  ...
Einfach umdrehen: TCA0 erzeugt den Trigger, TCB0 den Interrupt?

von Veit D. (devil-elec)


Lesenswert?

Hallo,

eine wichtige Nachfrage von S. Landolt blieb noch unbeantwortet. Worauf 
beziehen sich die 4096 Takte? Auf den gleichen Ursprungstakt wie die 64 
Takttriggergeneration oder auf die Triggerauslösung aller 64 Takte? Also 
möchtest du aller 4096 Takte Daten ausgeben oder aller 64*4096?

von Lars H. (larsfcfa)


Lesenswert?

Hallo,

um es klar zu stellen.

Ich benötige:

1. den Systemtakt mit Prescaler -> CLK/64
2. ein Trigger-Ausgang auf einem Port (am besten PB0/Wo0) mit diesem 
Takt (CLK/64)
3. eine ISR mit CLK/64/4096 (am einfachsten TCA OVFL), in der Daten 
rausgeschickt werden

von S. Landolt (Gast)


Lesenswert?

Okay, pas de probleme:

> TCA0 erzeugt den Trigger (kann durchaus im Split-Mode geschehen), TCB0 den 
Interrupt.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

ich glaube jetzt habe ich das verstanden.
a) aller 64 Takte Trigger
b) aller 262144 Takte Datenausgabe oder anders gesagt aller 4096 
"Events" von a).

Mal eine verrückte Idee für den Fall das ein Timer noch für andere 
Zwecke benötigt wird. Die RTC ist frei? Dann lege den 64er Takt vom 
Timerausgang mit an den externen RTC Takteingang. Intern übers 
Eventsystem verbinden scheint nicht vorgesehen zu sein. Oder ich habe es 
noch nicht gefunden. Laut meines Wissens kann die RTC nur Events 
erzeugen. Dann konfigurierst du die RTC auf aller 4096 Takte was machen. 
Hast die Wahl zwischen Eventsystem oder Interrupt.

von c-hater (Gast)


Lesenswert?

S. Landolt schrieb:

> Peter Dannegger schrieb:
>> Alle 64 Zyklen ein Interrupt
>
> Die 64 Takte gelten für das Trigger-Signal, welches in Hardware per PWM
> erzeugt wird. Die ISR wird derzeit alle 4096 Takte aufgerufen, da
> könnte/sollte dann eine weitere Teilung per Software möglich sein.

Du hast ja schon weiter oben vorgeschlagen, den Timer zu splitten. Wenn 
also die Intention des TO wirklich nicht war, alle 4096 CPU-Takte den 
Interrupt zu erzeugen, sondern vielmehr alle 4096 Zyklen des 
Triggersignals, dann geht natürlich noch mehr, nämlich ein Interrupt 
alle 16384 CPU-Takte.
Klar man muss dann in Software noch eine Variable zyklisch bis 16 
hochzählen lassen, aber das sollte ja wohl spätestens dann wirklich kein 
Problem mehr sein.

Übrigens, zum Split-Betrieb mit Kaskadierung: Scheinbar gibt es keine 
"direkte" Möglichkeit, das zu erreichen, wenn, dann müsste man über das 
Eventsystem gehen. Da wird's allerdings irgendwie etwas dünne mit der 
Doku. Klar ist die Event-Quelle, das ist easy. Aber für den Event-User 
ist das leider weit weniger klar. In dem Abschnitt für den Split-Mode 
taucht die Konfiguration für einen Event-Input garnicht erst auf.

Das könnte heißen: Das geht garnicht. Oder es könnte heißen: Wir haben's 
vergessen zu dokumentieren. Hast du damit schonmal rumgespielt?

Ich würde mal vermuten, dass die Konfiguration wie im Normalmode ist, 
aber sich grundsätzlich nur auf den Lo-Teil bezieht (was natürlich im 
Nicht-Split-Betrieb den gesamen Timer betreffen würde). Wie gesagt: das 
würde ich vermuten, ausprobiert habe ich es nicht, da bisher nie 
benötigt.

Wäre aber schonmal interessant, ob das geht. Wenn es so wäre, wie ich 
vermute, würde es für die konkrete Anwendung des TO bedeuten, dass der 
"schnelle" Timer der Hi-Teil sein muss, der langsame, abhängige der 
Lo-Teil, also genau umgekehrt wie bei der impliziten Kaskadierung im 
Normal-Mode.

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

c-hater schrieb:
> Oder es könnte heißen: Wir haben's
> vergessen zu dokumentieren.

Der neue Dokustil gefällt mir generell nicht. Man kann da nur sehr 
schwer durchsehen. Da ist kein System dahinter.
Die Blockschaltbilder kann man in der Pfeife rauchen, z.B. "Figure 
20-13. Timer/Counter Block Diagram Split Mode." Alles geht in die 
Black-Box "Control Logic". Man könnte vermuten, daß der Prescalerausgang 
auf beide Timer parallel geht.
Dagegen z.B. beim 8051 kapiert den Split-Mode jeder Dödel sofort (siehe 
Bild).

: Bearbeitet durch User
von Lars H. (larsfcfa)


Lesenswert?

Hallo,

vielen Dank für eure Hilfe, ich habe das jetzt mit TCA/TCB umgesetzt:

-TCA läuft mit CLKSEL_DIV64 und erzeugt mit einer "Pseudo-PWM" das 
Takt/Triggersignal an Wo0
-TCB läuft mit TCA-Takt ein Timer mit TCB0.CCMP=4095
    -> damit wird ISR(TCB0_INT_vect) ausgelöst

Das läuft in gcc wunderbar.

Es hat sich gelohnt euch zu fragen, viele gute Ideen und Ratschläge, die 
zur Lösung geführt haben.

Viele Grüße,
Lars

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.