Forum: Mikrocontroller und Digitale Elektronik Schieberegister am USI v. ATTiny2313


von Ernst (Gast)


Lesenswert?

Hallo,

Ich brauche 4 Schieberegister (HCT595) hintereinandergeschaltet an
einem ATTiny2313.

Um etwas mehr Geschwindigkeit herauszuholen hab ich die an den USI Port
angeschlossen, somit spare ich mir die Bit-Shifts und lass die vom USI
ausführen.

Das Atmel-Datenblatt (Seite 141) schlägt für eine möglichst schnelle
Übertragung eine ASM-Sequenz vor die mit:
1
out USIDR,r16
2
ldi r16,(1<<USIWM0)|(0<<USICS0)|(1<<USITC)
3
ldi r17,(1<<USIWM0)|(0<<USICS0)|(1<<USITC)|(1<<USICLK)
4
out USICR,r16 ; MSB
5
out USICR,r17
6
out USICR,r16
7
out USICR,r17
8
out USICR,r16
9
...

das Takt-Signal erzeugt und gleichzeitig den internen Counter richtig
mitlaufen lässt.

Den Counter brauche ich nicht, also habe ich das in c (avr-gcc) so
umgesetzt:
1
/* init:  USICR = _BV(USIWM0)|_BV(USICS1)|_BV(USICLK); */
2
3
void usi_send_byte(uint8_t d) {
4
    USIDR=d;
5
    USICR |= _BV(USITC);
6
    USICR |= _BV(USITC);
7
    USICR |= _BV(USITC);
8
    USICR |= _BV(USITC);
9
...(16 Mal)
10
}

was auch in brauchbaren ASM-Code übersetzt wird:
1
 out 47-0x20,r24
2
 sbi 45-0x20,0
3
 sbi 45-0x20,0
4
...


Nun die Frage: geht das evtl. noch schneller? Bei 8MHz Takt messe ich
gerade mal 200KHz auf der Datenleitung für
while(1) usi_send_byte(0x55)

Hab ich mich vielleicht bei der Initialisierung des USI vertan, kann
man den Takt evtl. direkt erzeugen lassen anstatt die Clock-Leitung per
Software zu togglen?

Oder passt das schon und mein billiges Multimeter hat sich bei der
Frequenz vermessen (Soll angeblich bis 5MHz messen können)?

Danke,
/Ernst

von A.K. (Gast)


Lesenswert?

Trotzdem ist die Atmel-Variante schneller als deine, denn OUT braucht
einen Takt, SBI/CBI jedoch zwei. Aber 8/4=2MHz sollte dabei schon
rauskommen.

"USICR |= _BV(USITC);"

Dieser Befehl löscht so nebenbei USICLK, d.h. so schnell dein Takt auch
sein mag, es mögen die dazu passenden Daten fehlen. Und wenn Du das
änderst, dann wird das Register immer noch mit jeder Taktflanke
geschoben, sowohl 0=>1 also auch 1=>0.

M.a.W: Der Atmel-Code schiebt mit CLK/2, schneller geht's einfach
nicht.

von Ernst (Gast)


Lesenswert?

Aha, hat die Op-Code Tabelle also auch für C-Programmierer einen Sinn
:)

Bin bislang von RISC => ein Befehl pro Takt ausgegangen, sind aber
durchaus einige "längere" Befehle dabei. Aber Faktor 2 mit der
kleinen Änderung zu erreichen ist schon super, besten Dank für den
Tipp.

Ob die Daten bislang komplett richtig angekommen sind, weis ich
nichtmal, hab das erstmal nur auf nem Steckbrett zusammengestöpselt und
nur ein paar LEDS hier und da zum Testen angesteckt.

Wenn ich meinen C Code in
<code>
void usi_send_byte(uint8_t d) {
 register uint8_t a=_BV(USIWM0)|_BV(USICS1)|_BV(USITC);
 register uint8_t b=_BV(USIWM0)|_BV(USICS1)|_BV(USICLK)|_BV(USITC);
 USIDR=d;
 USICR = a;
 USICR = b;
 USICR = a;
 ...
</code>
ändere, macht der avr-gcc jetzt 1:1 den Beispiel-Code daraus.

Wg. den 2MHz/200kHZ muss ich nochmal schauen, vielleicht hab ich die
CLKDIV8 Fuse vergessen (peinlich, peinlich), könnte aber mit ein paar
Timer-Interrupts dazwischen schon hinkommen. (Allerdings wundert mich
dann warum die Baudrate des USART stimmt)

/Ernst

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.