Forum: Mikrocontroller und Digitale Elektronik Schieberegister ersetzen


von Falk B. (falk)


Lesenswert?

MaWin schrieb:
> Falk B. schrieb:
>> Stimmt, aber Mr. AVR meint, das wäre in ASM einfach.
>
> Ist es auch, SPI Slave mit externem Takt (der ggf. trotzdem von innen
> stammt per PWM Pin) und schon btauchtan keine PLL.

Lern mal zitieren und sinnerfassendes Lesen, alter Mann. Es war EXPIZIT 
die Rede von einem EXTERNEN, SYNCHRONEN Takt zum Datensignal! Da nützt 
dir ein ASYNCHRONER Takt der nominell gleichen Frequenz herzlich wenig.

>> Ich bezweifle, daß
>> man es überhaupt hinbekommt, auch mit 16 MHz CPU-Takt.
>
> 
https://ww1.microchip.com/downloads/en/Appnotes/Atmel-2585-Setup-and-Use-of-the-SPI_ApplicationNote_AVR151.pdf

Meinst du wirklich, daß ich nicht weiß, wie SPI beim AVR funktioniert? 
OMG!

von Falk B. (falk)


Lesenswert?

avr schrieb:
> Danke, exakt so war das gemeint. SPI Slave und der AVR läuft mit
> internem Takt auf 8 MHz. Und das Problem des einfach gepufferten
> Sendepuffers kann durch Interrupt mit maximal 5 Takte Latenz in
> Assembler gelöst werden. Wie genau habe ich oben beschrieben.

Beweise es mit einem lauffähigen Progamm. Alles andere sind Behauptungen 
und Ausreden.

von Falk B. (falk)


Lesenswert?

c-hater schrieb:
> Ich meine, das ist natürlich eine Sache, über die man eigentlich sowieso
> nicht diskutieren müsste, da jeder mit hinreichender Kompetenz das
> sowieso weiss, aber ich möchte halt, dass du es EXPLIZIT und
> ÖFFENTLICH selber sagst.
>
> Deal?

Ich weiß nicht was in deinem Leben so alles schief gelaufen ist, aber es 
ist eine Menge. Mein aufrichtiges Beileid.

von Rente mit 76 (Gast)


Lesenswert?

Ist wohl mit einem Mikrocontroller wohl doch nicht so easy?
Sry, ist nur ein oberflächlicher Eindruck.

von Falk B. (falk)


Lesenswert?

Rente mit 76 schrieb:
> Ist wohl mit einem Mikrocontroller wohl doch nicht so easy?
> Sry, ist nur ein oberflächlicher Eindruck.

Ja, weil du einen FPGA-Fetisch hast und nicht lesen kannst und willst.

Beitrag "Re: Schieberegister ersetzen"

von avr (Gast)


Lesenswert?

Falk B. schrieb:
>> Ist es auch, SPI Slave mit externem Takt (der ggf. trotzdem von innen
>> stammt per PWM Pin) und schon btauchtan keine PLL.
>
> Lern mal zitieren und sinnerfassendes Lesen, alter Mann. Es war EXPIZIT
> die Rede von einem EXTERNEN, SYNCHRONEN Takt zum Datensignal! Da nützt
> dir ein ASYNCHRONER Takt der nominell gleichen Frequenz herzlich wenig.

Was hast du an "ggf." nicht verstanden? Es steht explizit externer Takt 
im zitierten Text. Über den SPI-Slave wird dieser zum asynchronen 
MCU-Takt einsynchronisiert.

Falk B. schrieb:
> Beweise es mit einem lauffähigen Progamm. Alles andere sind Behauptungen
> und Ausreden.

Ich muss dir gar nichts beweisen. Ich zeige eine Lösung auf und du 
kannst Einwände erheben. Der Einwand "funktioniert nicht, solange du es 
nicht demonstriert" ist ein Totschlagargument und eines Ingenieurs nicht 
würdig. Ich bin bereit über alle Einwände zu diskutieren oder sogar 
ungetesteten Code bereitzustellen, falls du es testen willst. Ich habe 
es wirklich nicht nötig, das auf richtiger Hardware zu testen. Glaube 
mir, diskutier mit mir oder bleib auf deiner Scheibe. Alles was ich hier 
anbiete ist mein Wissen über die AVR-Architektur aus der Zeit, in der 
ich sehr viel Assembler programmiert habe.

von Jobst M. (jobstens-de)


Angehängte Dateien:

Lesenswert?

Kurz: Das AVR-SPI ist eine Zicke!

Ab 18MHz schafft das SPI mit externem SCK Takt von 1MHz rechtzeitig ein 
neues Byte nachzufüllen und zuvor das empfangene zu sichern. Bei 16MHz 
ist's random.

Bild vom Scope:

D2 (kurze negative Pulse, Port D2): Negative Flanke wird NACH dem 
Datenaustausch erzeugt.

D3 (SCK und OC0B verbunden): Die 1.024MHz gehören dazu (18,432/18). Die 
negative Flanke VOR dem Puls an D2 beginnt das neue Byte. (Was mich 
etwas verblüfft)

D4 (MOSI hier mit MISO verbunden): Was raus geht, kommt auch wieder 
rein. Wird hier nur 1x zwischengespeichert. 0x0F wurde am Anfang nur 
einmal gesendet. (Nachtrag: es wird beim ersten Durchlauf noch ein 
zweites Mal gesendet, aber dann wird tmp überschrieben.)

Geht mit AVR-SPI also gerade so ...
Aber nicht mit internem Takt.

So, da muss nun nur noch ein Zähler mit Begrenzung rein und ein LD und 
ein ST ...


Gruß
Jobst

: Bearbeitet durch User
von avr (Gast)


Lesenswert?

Interessant, eventuell verliert man mehrere Takte durch die beiden clock 
domains.

Es gibt aber noch Optimierungspotenzial:
- SPIDR erst schreiben, dann lesen
- Interrupt benutzen

Ich hab hier gerade nicht die Möglichkeit das zu testen. Das wäre dein 
Code so modifiziert, dass es meiner Meinung nach das Optimum ist.
1
.include "m328def.inc"
2
.def  tmp    = r16        ; allgemeines Register
3
.org 0x0000            ; Reset Handler
4
rjmp init
5
6
.org 0x0022 ; SPI ISR
7
    out  SPDR, tmp      ; ETWAS etwas später
8
    in  R18, SPDR      ; ETWAS aus SPI holen
9
 wieder hinein schicken
10
    CBI  PORTD, 2
11
    MOV  tmp, R18      
12
    SBI  PORTD, 2
13
    RETI
14
15
init:
16
    ldi tmp, LOW(RAMEND)
17
    out SPL, tmp
18
    ldi tmp, HIGH(RAMEND)
19
    out SPH, tmp
20
  ; Ports
21
    SBI  DDRD, 2        ; Testausgang
22
  ; Timer 0 init
23
    ldi  tmp, 0x23      ; 00: OC0A disconnected
24
              ; 10: OC0B
25
              ; 00: Reserved
26
              ; 01: mit WGM02 aus TCCR0B 101 - Phase correct PWM mit OCRA TOP
27
    out  TCCR0A, tmp
28
    ldi  tmp, 0x09      ; 0000: Reserved
29
              ; 1: Siehe TCCR0A
30
              ; 001: Clock/1
31
    out  TCCR0B, tmp
32
    ldi  tmp, 17        ; TOP (teilt durch 18 - bei 18MHz)
33
    out  OCR0A, tmp
34
    ldi  tmp, 8        ; 50% Tastung
35
    out  OCR0B, tmp
36
    ldi  tmp, 0x01      ; Irq an
37
    sts  TIMSK0, tmp  
38
    SBI  DDRD,  5      ; PD5 PWM-Port als Ausgang
39
  ; SPI init 
40
    LDI  tmp, 0x15
41
    OUT  DDRB, tmp
42
    SBI  PORTD, 5 ; MISO Pullup
43
    LDI  tmp, (1<<SPE)|(0<<MSTR)|(1<<SPIE)  ; IRQ, Enable SPI, MSB-first, Master, set clock rate fck/4
44
    OUT  SPCR, tmp
45
    LDI  tmp, 0        ; No Doublespeed
46
    OUT  SPSR, tmp
47
  ; START!
48
    ldi  tmp, 0x0F
49
    out  SPDR, tmp      ; Etwas hineinwerfen
50
    SBI  PORTD, 2 
51
    sei
52
loop:    ; Hauptschleife
53
    rjmp  loop

von Falk B. (falk)


Lesenswert?

Jobst M. schrieb:
> Kurz: Das AVR-SPI ist eine Zicke!

Nein. Aber das Problem des unterbrechungsfreien Betriebs ist LANGE 
bekannt.
Also nimmt man den UART im SPI-Mode.

Beitrag "Re: Schieberegister ersetzen"

> Ab 18MHz schafft das SPI mit externem SCK Takt von 1MHz rechtzeitig ein
> neues Byte nachzufüllen und zuvor das empfangene zu sichern. Bei 16MHz
> ist's random.

Dein Test ist nur ein Anfang, die eingentliche Verzögerung fehlt. UNd 
die SPI-Takterzeigung durch einen Timer, der dann von außen wieder den 
SPI Takt füttert ist schräg ;-)

von Jobst M. (jobstens-de)


Lesenswert?

avr schrieb:
> - SPIDR erst schreiben, dann lesen

Möglich. Ich bin mir gerade nicht sicher, wie SPDR sich verhält, nachdem 
man eine neue Übertragung angestoßen hat.

> - Interrupt benutzen

Nein, die Zeit hast Du nicht.
Wenn der IRQ auslöst, ist die vorherige Übertragung eigentlich schon 
beendet. Da muss das neue Datenwort dann schon im Register liegen.

(Deshalb bin ich auch so verblüfft, dass das so noch rechtzeitig 
klappt.)

Falk B. schrieb:
> Aber das Problem des unterbrechungsfreien Betriebs ist LANGE
> bekannt.

Ja. Ist trotzdem eine Zicke.

> Also nimmt man den UART im SPI-Mode.

Ich wollte ja genau wissen, wo die Grenze bei SPI ist.

> Dein Test ist nur ein Anfang, die eingentliche Verzögerung fehlt.

Die ist aber recht Zeitunkritisch vor der Warteschleife zu installieren. 
Ich habe ja beschrieben wie. Wollte kein Silbertablett liefern.

> UNd
> die SPI-Takterzeigung durch einen Timer, der dann von außen wieder den
> SPI Takt füttert ist schräg ;-)

Wenn es mich zum Ziel führt, finde ich es angemessen. Da mir IRQs z.B. 
in einigen Fällen (in Verbindung mit Hardware) zu sehr jittern, ist dies 
eine häufig von mir angewandte Methode.


Gruß
Jobst

: Bearbeitet durch User
von avr (Gast)


Lesenswert?

Jobst M. schrieb:
> Möglich. Ich bin mir gerade nicht sicher, wie SPDR sich verhält, nachdem
> man eine neue Übertragung angestoßen hat.

Das steht so im Datenblatt:

The slave may continue to place new data to be sent into SPDR before 
reading the incoming data. The last incoming byte will be
kept in the buffer register for later use.

Jobst M. schrieb:
> Nein, die Zeit hast Du nicht.
> Wenn der IRQ auslöst, ist die vorherige Übertragung eigentlich schon
> beendet. Da muss das neue Datenwort dann schon im Register liegen.

Das gleiche trifft auf Polling zu, das hier im besten Fall 3 Takte 
benötigt, im worst case aber 6. Der Interrupt wird genauso ausgelöst, 
wenn SPIF gesetzt wird und schreibt dann nach 4-5 Takten auf SPDR. Und 
ja, es sind 4-5 Takte. Es gibt bei meinem Beispiel keinen 
"Interruptrahmen", kein Sichern von Status-/Registern.

von Jobst M. (jobstens-de)


Lesenswert?

avr schrieb:
> [...]

Keine Panik, ich werde es nachher ausprobieren.
Im übrigen wäre das Datenblatt an dieser Stelle nicht zum erstem mal 
nicht korrekt, daher prüfe ich immer alles selber.

Gruß
Jobst

von c-hater (Gast)


Lesenswert?

avr schrieb:

> Es gibt bei meinem Beispiel keinen
> "Interruptrahmen"

Es gibt immer einen Interruptrahmen. Selbst dann, wenn garnix gesichert 
oder wiederhergestellt wird und wenn die ISR überhaupt nichts nützliches 
tut, sondern einfach nur durchlaufen wird (also z.B. nur aus einem reti 
direkt im Vektor besteht).

Und dieser Rahmen ist halt im Minimum 8 Takte (plus mindestens einen, 
typisch aber eher zwei "Straftakte" in main(), wenn main nur aus rjmp 
main besteht)

Wer das nichtmal das begreift, hat die Architektur nicht verstanden und 
sollte einfach mal seinen dummen Sabbel halten und die Grundlagen der 
Architektur lernen.

Ende der Ansage.

von avr (Gast)


Lesenswert?

Lol. Das Wort Interruptrahmen gibt es nicht, zumindest habe ich es in 
der Literatur noch nie gesehen. Es gibt Epilog und Prolog im Interrupt 
und dazu gehört die Interruptlatenz (die 4 Takte + pipeline stalls beim 
AVR beträgt) NICHT.

von HildeK (Gast)


Lesenswert?

c-hater schrieb:
> Es gibt immer einen Interruptrahmen. Selbst dann, wenn garnix gesichert
> oder wiederhergestellt wird und wenn die ISR überhaupt nichts nützliches
> tut, sondern einfach nur durchlaufen wird (also z.B. nur aus einem reti
> direkt im Vektor besteht).

Ja, teilweise wird 'ineffizient' gesichert, also auch Register, die in 
main gar nicht benutzt werden. Mach mal eine leere Main und eine ISR und 
schau dir das an.
In dem Fall kann man mit ISR(XXX_vect, ISR_NAKED) den Pro- und Epilog 
verhindern.

von Percy N. (vox_bovi)


Lesenswert?

avr schrieb:
> Das Wort Interruptrahmen gibt es nicht, zumindest habe ich es in der
> Literatur noch nie gesehen.

Üblich ist eher die Bezeichnung Stackrahmen.

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.