mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik atMega88: Timing Probleme


Autor: Roman (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Mikrocontroller Gemeinde,

mittels des Tutorials und der vielen Beitraege habe ich es geschafft mit 
einem atMega88 mein erstes µC Projekt zu erstellen.

Die Aufgabe ist bei einem Takt von 1 MHz nach Erkennen eines Startcodes 
die nachfolgenden 44 Bytes (Nibble) einzulesen. Das Einlesen der Daten 
geschieht unter Ausnutzung der Taktflanke und des externen Interrupts.
Das Warten auf den Startcode führen ich durch Pollen des Portes durch.
Hierbei habe ich das Problem das das Erkennen am Anfang oder am Ende des 
Startcodes liegen kann. Dadurch verliere ich ab und an einen 
Einlesetakt.

Siehe Code Beispiel:
MAIN:
    ldi XL,low(data_in)    ; Set Adress of data_in
    ldi XH,high(data_in)
LOOP_0: 
    ; Wait for Initial Code (0x0F)
    in   temp, PINB
    and  temp,clrinmsk    ; Clear open input pins
    cpi   temp, 0x0f    ; Startsequence
    breq CLEARINT
    rjmp LOOP_0
CLEARINT:
    ; Enable INT0    
    SBI EIMSK,INT0            
WAITINT0:    
    rjmp WAITINT0 
EXTINT0:  
    ;External interrupt store incoming data in X
    in    temp,PINB
    st   X+,temp
    cp   XL,maxdata
    breq CODING  
    reti
CODING:
    CBI   EIMSK, INT0    ; Clear EXTInt 0
           POP   temp      ; Clear Stack from Interrupt
    POP   temp
    sei      ;Global Interrupts Enable, switched off by Interrupt

    ldi  XL,low(data_in)          ; Set Adress of data_in
    ldi  XH,high(data_in)
    

Ich suche jetzt nach einer Moeglichkeit das Erkennen des Startcodes 
innerhalb der Interruptroutine oder snychron zum Takt durchzuführen. 
Allerdings habe ich nur einen Takt Zeit dafür (1µS). Idealerweise dachte 
ich an die Möglichkeit die Sprungadressen für den Interrupt nach 
Erkennen des Startcodes zu tauschen. Oder ein Flag zu setzen, wobei 
dafür und die dauernde Abfrage in der Interruptroutine die Zeit zu kurz 
ist.

Achja, der Controller laueft mit 20MHz. Ein Cycle ist somit 0,05 µS. Die 
Daten sollten ziemlich in der Mitte genommen werden um Verfälschungen 
durch schlechte Flanken zu vermeiden.

Jegliche Hilfe ist willkommen.

Gruss

Roman

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Roman (Gast)

>Die Aufgabe ist bei einem Takt von 1 MHz nach Erkennen eines Startcodes
>die nachfolgenden 44 Bytes (Nibble) einzulesen. Das Einlesen der Daten

Die meinst ein Datenstrom mit 1 Mbit/s, richtig?

>geschieht unter Ausnutzung der Taktflanke und des externen Interrupts.

Das halte ich für gewagt. Selbst bei 20 MHz Takt hat dein uC gerade mal 
20 Takte Zeit, das Datenbit einzulesen, zu verarbeiten und zu speichern. 
Das ist nicht sehr viel.

>Das Warten auf den Startcode führen ich durch Pollen des Portes durch.
>Hierbei habe ich das Problem das das Erkennen am Anfang oder am Ende des
>Startcodes liegen kann. Dadurch verliere ich ab und an einen
>Einlesetakt.

Was für eine Schnittstelle ist es den überhaupt? Wenn du zu deinen Daten 
noch ein Taktsignal am Controller hast, dann solltes du das besser mit 
dem SPI oder USI- Modul machen.

>Ich suche jetzt nach einer Moeglichkeit das Erkennen des Startcodes
>innerhalb der Interruptroutine oder snychron zum Takt durchzuführen.

SPI oder USI. Interrupts kannst du bei DER Geschwindigkeit vergessen, 
das geht nur über Polling.

MFG
Falk

Autor: Roman (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schoenen Dank fuer Deine schnelle Antwort Falk.

Die Geschwindigkeit ist richtig 1 MHz/s. Die Daten liegen parallel an 
PortB bit#0-#3 an und werden nur gespeichert. Die Verarbeitung findet 
spaeter statt, nachdem alle Daten gesammelt sind. SPI, USI usw. geht da 
leider nicht, obwohl ich erst noch das Datenblatt an dieser Stelle 
verstehen muss. Aber keine seriellen Daten, das steht schon mal fest.

Das Speichern der Daten funktioniert ja auch schon. Das Problem ist das 
Erkennen der Startbedingung. Laienhaft mal so gedacht.

Takt:
Interupt bei Flanke geht high.
Holen Daten, pruefen Flag.
Gesetzt = speichern.
   Anzahl erreicht?
   Nein = RETI.
   Ja = Verarbeitung.
Nicht gesetzt = pruefen Startbedingung
   Ja = setzen Flag
   Nein = RETI.
RETI

Fuer 20 Takte/Cycles etwas viel, ich weiss.

Kann ich da vielleicht mit selbstmodifizierendem Code arbeiten.

Startbedingung erfuellt = Setzen der neuen Interruptaddresse Speichern.
Verarbeitung erfolgt = Setzen der Adresse Pruefroutine.

Oder,so? Hat das schon mal jemand gemacht? Hat einer ASM Code dazu?

Gruss

Roman

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Roman (Gast)

>Die Geschwindigkeit ist richtig 1 MHz/s. Die Daten liegen parallel an

Ahhhhh. Was ist DAS denn für eine Einheit???!!

Frequenzen haben die Einheit Hz oder MHz.
Datenübertragungen haben Bit/s oder Mbit/s.

>PortB bit#0-#3 an und werden nur gespeichert. Die Verarbeitung findet

Ach so, hab ich übersehen. Klar, dann is nix mit SPI und USI.

>Kann ich da vielleicht mit selbstmodifizierendem Code arbeiten.

Nein. Erstens weil das per se Murks ist, und zweitens weil der AVR das 
ganz sicher NICHT schnell kann. Vergiss die Idee.

Um das Ganze vielleicht ein wenig zeitlich zu entspannen meine Idee. 
Nimm ein 4 oder 8Bit FlipFlop (74HC273) und nimm es als Zwischenpuffer. 
Die Daten werden mit der jeweils günstigen Flanke in das FlipFlop 
getaktet, gleichzeitig löst der Takt einen Interrupt aus. Nun hat dein 
AVR 20 Takte Zeit, die Daten zu lesen und zu verarbeiten, die kritische 
Abtastung ist schon erfolgt. Das könnte man mit kompakter Programmierung 
im Interrupt machen (Register nicht pop/pushen sondern exklusive 
Nutzung, nur das SREG sichern). Noch besser wäre die Nutung von mehr 
Lokik, entweder als TTL Bausteine oder CPLD.

Aber mal ganz grundsätzlich, was ist das denn für ne komische 
Schnittstelle?

MFG
Falk

Autor: Roman (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Falk,

die Taktfrequenz ist und bleibt 1 MHz / s, aber da man keinen Streit 
drueber.

Das Zwischenpuffern in einem FlipFlop ist sicherlich reizvoll, aber das 
Daten Speichern macht er schon recht ordentlich. Mir geht es nur darum 
das Pollen des Startcodes ab zu verbessern.

Frage: Kann ich den Ausgang eines Schmitt-Triggers 40106 auf die beiden 
externen INT Eingaenge legen? So ohne weiteren Widerstand dazwischen.
Wenn ich an die Digitalen Zeiten zurueckdenke sollte doch ein Ausgang 
zwei Eingaenge versorgen koennen, ohne dabei in die Knie zu gehen oder 
das Signal weiter zu verfaelschen?

Ich wuerde dann naemlich den Interrupt per Interupt umschalten.

Gedankensalat:

Main:
INTEXT01 = ein.
INTEXT01 = Startcode erkannt.
  INTEXT01 aus.
  INTEXT00 aktivieren.
RETI
INTEXT00 = Speichern der Daten bis MaxAnzahl
  MaxAnzahl erreicht = INTEXT00 aus.
  RET.
RETI
Verarbeitung.
RJMP Main

So sollte es doch klappen. Oder?

Gruss

Roman

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Roman (Gast)

>die Taktfrequenz ist und bleibt 1 MHz / s, aber da man keinen Streit
>drueber.

1 Hz = 1 Schwingung / s

1 Hz / s = ???

>Wenn ich an die Digitalen Zeiten zurueckdenke sollte doch ein Ausgang
>zwei Eingaenge versorgen koennen, ohne dabei in die Knie zu gehen oder

Ja.

>So sollte es doch klappen. Oder?

Möglich.

MFg
Falk

Autor: Roman (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Falk,

das gibt ja Anlass zur Hoffnung. Ich weiss zwar das es etwas 
unkonventionell ist, aber nur so werden Ideen geboren.

Achja das Ganze ist in einer elektronischen Orgel verbaut, die 
unablaessig einen Datenstrom zur Peripherie sendet. Daraus sind gezielt 
die von mir genannten 44 Datenhalbytes (Nibbles) heraus zu filtern.

Also doch 1 MHz wie zuerst genannt. Na da bin ich Dir aber auf den Leim 
gegangen. Die Datenrate rechne ich dann mal spaeter aus. Wie gesagt, bin 
Anfaenger aber mit jeder Menge Flausen im Kopf.

Gruss und Danke

Roman

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Falk:
Hz/s sind natürlich Schwingungen / s², also eine Frequenz, die sich mit 
der Zeit ändert.

@Roman:
Selbstmodifizierender Code geht bei den AVRs nicht. Sie können im RAM 
keinen Code ausführen und im Normalbetrieb das Flash nicht ändern. 
Selbst wenn man das Flash ändern könnte, dann würde man dieses mit 
ständigen Änderungen schnell kaputt machen.

Markus

Autor: Roman (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schoenen Dank fuer die Antworten.

Ich habe das Ganze jetzt mal ins Reine geschrieben (siehe Anhang).
Ich werde den Code heute Abend mal testen. Etwas problematisch erscheint 
mir das Warten auf ein Ergeignis in einer Schleife mittels RJMP. 2 
Zyklen verbraucht der Sprung ohne etwas zu tun. Das kalkuiere ich mal 
als Loop Delay (gestrichelte Linien)in meiner Skizze. Gibt es da 
vielleicht eine bessere Loesung.

Roman

Autor: Roman (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Neu mit Anhang ;-).

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Roman (Gast)

>Ich werde den Code heute Abend mal testen. Etwas problematisch erscheint
>mir das Warten auf ein Ergeignis in einer Schleife mittels RJMP. 2
>Zyklen verbraucht der Sprung ohne etwas zu tun. Das kalkuiere ich mal
>als Loop Delay (gestrichelte Linien)in meiner Skizze. Gibt es da
>vielleicht eine bessere Loesung.

Ja, die Nutzung von Interrupts (externer Interrupt oder Pin Change), die 
dauern zwar länger, sind aber dann konstanter in der Verzögerung.

MfG
Falk

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf die Start Condition Interrupt gesteuert warten (Sleep).
Wenn der Interrupt ausgeführt wird alle 20 Takte das Nibble ins RAM
schaufeln (als Byte).
In ewta so

wait_for_start:
ldi zh,1
clr zl
sleep ;wait for start condition

int0:
in r16,pinb
st z+,r16 ;copy to ram 0x100
nop
nop
nop
nop
...
in r16 ,pinb
st z+,r16
...

frißt zwar wahnsinning viele bytes, ist aber dafür verdammt schnell.

Autor: Roman (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen,

das mit dem Interrupt hat geklappt. Der Start ist jetzt genau definiert,
und somit auch das Einlesen. Das mit dem Sleep Modus habe ich immer als 
zeitraubend verstanden. Werde es aber noch mal nach lesen.

@Falk: Da die Orgel auch noch ein drittes Manual hat(Tastenreihe) komme 
ich gerne nochmal auf Deinen Vorschlag mit SPI zurueck. Die 3te 
Tastenreihe muss separat abgetastet werden und der Bewegungssensor mit 
einem ADC erfasst werden. Vielleicht mache ich das autonom mit einem 
Tiny.?. und hole mir die Daten ueber die SPI Schnittstelle. Wie ich den 
Tiny dann ansprechen muss damit er mir die Daten schickt ist mir derzeit 
noch ein Buch mit sieben Siegeln. Aber es gibt ja das Forum.

Nochmals Dank an alle.

Gruss

Roman

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.