Attiny 25, USI clock vom Timer 0 compare match

#692178
Lesenswert?

Der Thread ist zwar uralt, aber wie es scheint finden die AVR-Entwickler 
ihr USI selber so bescheuert, daß sie es nicht mal ausprobiert und daher 
den Fehler im Datenblatt nicht bemerkt haben.

Ich hab mich damit abgefunden und ignoriere es einfach.

Master-I2C, Master-SPI, UART mache ich einfach in Software und gut is.
Und Slave-I2C mache ich dann eben mit nem ATmega48.

Slave-SPI kann ja kein AVR gut, da nehme ich dann nen 8051.


Peter
#692255
Lesenswert?

Benedikt K. wrote:
> Peter Dannegger wrote:
>
>> Slave-SPI kann ja kein AVR gut, da nehme ich dann nen 8051.
>
> Nur der mega48 mit der USART im SPI Mode kann das einigermaßen.

Ne, die neueren ATmega könne das alle.

Aber leider bloß als Master, nicht als Slave wo es drauf ankommt.

Als Master ist es aber schon ganz praktisch, wenn man ne MMC möglichst 
schnell zugreifen will. Bringt gegenüber dem ungepufferten SPI richtig 
Speed.


Peter
Gast #2321080
Lesenswert?

> ich will die USI Unit in einem ATTINY 25 mit dem Timer0 compare match
> Ereignis triggern. Leider kann ich aus der Dokumentation nicht
> herauslesen welches Compare Match Ereigniss gemeint ist, das von OCR0A
> oder OCR0B ?

Frage ist immer noch nicht beantwortet, ich steh grad vor dem selben 
Problem beim ATTINY 85. Ich geh mal davon aus, dass er beide Compare 
Matches akzeptiert. Ist das korrekt? Oder kann man irgendwo auswählen, 
welches er denn jetz nehmen soll?
(Firma: TU Chemnitz) #7695835
Lesenswert?

Es verdichten sich die Anzeichen, dass es um Output Compare A geht: Ein gesehenes Beispiel verwendet den CDC-Modus, der nur mit OCR0A geht.

Eine Kombination (ODER-Verknüpfung) beider Output Compare erscheint wenig sinnvoll.

Ich werde das mal zum /flankenpräzisen/ Senden von UART-Daten mit hoher Rate (115200 Baud) bei hoher Interruptlast (5 µs CLI @ 62 kHz; Bitzeit 8,6 µs) von OCR0B untersuchen. Ob der USI-Zähler in Einer- oder Zweierschritten zählt. Das letzte Datenbit und das Stoppbit müssen programmatisch „irgendwann zwischendrin“ ins Datenregister eingepopelt werden. Das geht theoretisch sogar dann, wenn die Interruptsperrzeit größer als eine Bitzeit ist; sie muss aber kleiner als 8 Bitzeiten sein.

#7696152
Lesenswert?

... und wenn sie nicht gestorben sind, dann leben sie noch heute.

Aber Spaß beiseite -

Es verdichten sich die Anzeichen ...

Soll das die Antwort auf die ursprüngliche Frage, vor siebzehneinhalb Jahren gestellt, sein, ob "... OCR0A oder OCR0B"? Verstehe ich nicht ganz.

(Firma: TU Chemnitz) #7696573
Lesenswert?

Nun, die Frage wurde nie beantwortet. Und wenn es 20 Jahre dauern sollte, bis das Problem gelöst wird!

Ja, es ist OCR0A und /nur/ OCR0A, was die USI triggert. Und der 4-Bit-USI-Zähler zählt in Einerschritten.

So habe ich den UART (nur Senden) nun realisiert:

  • Timer0 ist frei laufend (kein CTC-Modus) weil mit OCR0B der A/D-Wandler getriggert wird (=schlau von Atmel, wenigstens da eine Auswahl anzubieten)
  • Beim Output-Compare-Interrupt wird der nächste OCR0A-Wert berechnet, um die Baudrate zu realisieren. Im Format Q8.8 geht das auch mit gebrochenem Baudratenteiler. Und das nächste Bit in USIDR.6 eingesetzt. Indem ich so nur 1 Bit von USIDR nutze, erspare ich mir die umständliche Bitreversion.
  • Der 4-Bit-Zähler wird vor dem Senden mit 6 initialisiert, um 10 Bits abzuzählen. USIDR.6 mit 0 für das Startbit. OCR0A gesetzt, die Taktung mit USICR.2 sowie Output-Compare-Interrupts mit TIFR.4 gelöscht und mit TIMSK.4 freigegeben.
  • Bei erreichtem 4-Bit-Zählerüberlauf wird TIMSK.4 gelöscht und die Taktung via USICR.2 beendet.

Bei 115200 Baud liegt die maximale Interruptsperrzeit bei 8 µs, was bei 16 MHz Taktfrequenz bereits üppige 128 Takte sind. Erst dann gehen Bits verloren, und die UART kommt außer Tritt, dann aber gründlich.

Längere Interruptsperrzeiten oder noch höhere Datenraten erfordern Timer0 im CTC-Modus und das Senden /mehrerer/ Bits. Das ging in meinem Kontext nicht und beißt sich mit gebrochenem Baudratenteiler.

Zum Umgang mit gebrochenem Baudratenteiler (C++11)

1
constexpr unsigned BRT = double(F_CPU)/Timer0Vorteiler/Baudrate*256+0.5;
2
register byte ocr0a_nk asm("r2");  //„Nachkommastellen“ von OCR0A
3

4
ISR(TIMER0_COMPA_vect) {
5
 unsigned u = OCR0A<<8 | ocr0a_nk;
6
 u += BRT;  // mit durchgehendem Carry addieren
7
 OCR0A = byte(u>>8);
8
 ocr0a_nk = byte(u);
9
 ...
10
}

Ohne u würde die Carry-Behandlung elend umständlich. ocr0a_nk muss nicht initialisiert werden.

#7696627
Lesenswert?

Was die eigentliche, die ursprüngliche Frage betrifft, so habe ich es mir leichter gemacht: Timer0 im CTC-Modus triggert USI, in deren Counter-Overflow-ISR das übliche LED-Blinken. Wenn ich danach OCR0A < OCR0B setze, blinkt die LED noch immer (im erwarteten Takt).

PS:

Und wenn es 20 Jahre dauern sollte ...

Na, ich weiß nicht ... In diesem Metier wird die Halbwertszeit von Hardware (wie auch 'Brainware' (== Wissen)) immer kürzer; und wer will heute noch mit diesem unsäglichen USI arbeiten - was z.B. Peter Dannegger schon vor siebzehn Jahren weit von sich wies.

Angehängte Dateien:
#7696950
Lesenswert?

S. L. schrieb:

und wer will heute noch mit diesem unsäglichen USI arbeiten

na ja, die Frage wäre dann eher wollen oder müssen ?!? "Spaß" beiseite, ATtinyx4 und ATtinyx5 sind ja immer noch erhältlich, nicht wirklich grottenschlecht, nur dann, wenn man darauf bspw. eine serielle Schnittstelle haben mag, wirst du um das - zugegebenerweise - unsägliche USI nicht drumrum kommen. Selbst ein ATtiny2313 hatte bspw. eine richtige UART

(Firma: 1984now) #7697218
Lesenswert?

Ralph S. schrieb:

"Spaß" beiseite, ATtinyx4 und ATtinyx5 sind ja immer noch erhältlich, nicht wirklich grottenschlecht

Das sehe ich genau so. Gerade die x5 sind doch ziemlich geil (wegen PLL-Takt für Core und/oder Timer).

nur dann, wenn man darauf bspw. eine serielle Schnittstelle haben mag, wirst du um das - zugegebenerweise - unsägliche USI nicht drumrum kommen.

Naja, "unsäglich" hin oder her: besser eine relativ geringe Hardwareunterstützung als gar keine, wie z.B. beim Attiny13. Hat man mal so'n Teil am Hals, lernt man selbst das USI zu schätzen.

Selbst ein ATtiny2313 hatte bspw. eine richtige UART

Ja schon, aber das war bei den Classic-Tinys definitiv eine Ausnahme. Wenn ich keinen vergessen habe, dann hatten das nur 2313, 2313A, 4313, 441 und 841. Classic-Tinys gab es aber viele Dutzend verschiedene.

(Firma: 1984now) #7697220
Lesenswert?

Peter D. schrieb:

Ralph S. schrieb:

Selbst ein ATtiny2313 hatte bspw. eine richtige UART

Der hat beides, USART und USI. Ich hab mal ein Beispiel gepostet für eine 2. UART (RX und TX) in SW mit Timer1. Das geht immer noch deutlich performanter, als mit dem USI.

Hast du mal 'nen konkreten Link? So gering der Nutzen des USI auch sein mag, es bringt einen Nutzen, wenn man es sinnvoll und effizient einsetzt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren