Guten morgen,
an meinem Atmega2560 hab ich an einem Pin ein TTL-Signal anliegen
welches in undefinierten Zeitabständen ankommt. Und dieses würde ich
auch gerne unter c auswerten, eine CRC-Prüfung über das ankommende
Telegramm bilden und dann per UART weiterleiten.
Wie ist die herangehensweise an diese Problem?
Lese ich das komplette Telegramm (max. 32Byte) komplett in ein array ein
und verarbeite es dann? Sollte ich das mit einer ISR abfangen? Mit einem
Timer arbeiten?
Gibt es Link`s wo ich mich dazu reinlesen könnte?
MFG Alex
>> Meine eindeutige Antwort: JA.>>Danke für die Info. Jetzt hab ich auch die Welt verstanden. Ohne deine>Antwort wäre das nicht möglich.
Aber recht hat er, der Ian. Was solle deine Frage, bzw. was willst Du?
Dass ein anderer Dein Problem/Deine Aufgabe löst, nur weil Du zu faul
bist, eine Suchmaschine zu bedienen zu lesen nachzudenken?
Stelle eine konkrete Frage zu einem klar beschriebenen konkreten Problem
und Du wirst konkrete Antworten erhalten
Alex W. schrieb:> Guten morgen,> an meinem Atmega2560 hab ich an einem Pin ein TTL-Signal anliegen> welches in undefinierten Zeitabständen ankommt. Und dieses würde ich> auch gerne unter c auswerten, eine CRC-Prüfung über das ankommende> Telegramm bilden und dann per UART weiterleiten.>
Es ist noch zu erwähnen das es ein 2400 Baud Signal ist. Heißt 2400Hz
logisch 0 und 1200Hz logisch 1.
Sorry, mit TTL-Signal ist TTL-Pegel gemeint.
Dies ist die eigentliche, hoffe 'konkrete' Problem. Falls was fehlt an
info, dann ergänze ich es gerne.
Alex W. schrieb:> Gibt es Link`s wo ich mich dazu reinlesen könnte?
Ich bin bereit mich zu informieren und will nicht andere meien Arbeit
machen lassen. Aber das was ich gefunden habe scheint mir nicht für
meinen fall zu sein. Ich finde viel zu Drehgebern und dem dahinter
stehenden Gray-Code, aber das brauch ich nicht.
Alex W. schrieb:> Lese ich das komplette Telegramm (max. 32Byte) komplett in ein array ein> und verarbeite es dann? Sollte ich das mit einer ISR abfangen? Mit einem> Timer arbeiten?
Das waren meine Denkansätze mit welcher Methode man das lösen versuchen
könnte.
Peter schrieb:> Dass ein anderer Dein Problem/Deine Aufgabe löst, nur weil Du zu faul> bist, eine Suchmaschine zu bedienen zu lesen nachzudenken?
Faul bin ich keinster Weise und das ist unverschämt so was zu schreiben
oder zu behaupten.
Wie gesagt gesucht hab ich. Vllt. hab ich die falschen Suchwörter
eingegeben, aber ich suche immer bevor ich was schreibe.
Zurück zum Thema.
Eine weitere ergänzung zur Problemstellung. Mein Signal liegt an einem
PIN mit Interrupt funktion und diese würde ich auch gerne nutzen um
nicht die ganze Zeit im Hauptprogramm auf ein Signal zu warten.
> Es ist noch zu erwähnen das es ein 2400 Baud Signal ist.> Heißt 2400Hz logisch 0 und 1200Hz logisch 1.
Unter "Baud" versteh ich zwar was anderes.
Auch diese Information reicht noch lange nicht, um eindeutig klar zu
stellen, wie denn eigentlich das Eingangssignal aussieht und wie es
auszuwerten ist.
Abhaengig vom Timing koennte man das Signal auch mit einem
timerinterrupt auswerten.
Ob einlesen oder nicht ... Was soll geschehen, wenn das Signal nicht
passt ? Wenn der CRC falsch ist, fortwerfen ?
es stellen sich halt verschiedene Fragen ...
Wenn Dein Signal eh am Interruptpin liegt, liegt es nahe den auch zu
verwenden und sei es um nur ein Flag zu setzen und die Verarbeitung in
der Mainloop vorzunehmen.
Ob Du bei jedem eingehenden Byte die CRC fortschreibst oder am Ende über
alle Zeichen bleibt sich im Prinzip gleich, die Rechenzeit ist die
Selbe, kommt halt drauf an was Dein sonstiger Programmablauf noch so
macht und ob sich n paar Mikrosekunden ab und an oder auf einmal störend
auswirken.
Die Verwendung eines Timers für ein Timeout der Übertragung ist eine
mögliche Programmversion ... bei unsicherer Übertragung wie IR auch
durchaus empfehlenswert. Bei jedem empfangenen Zeichen Timer
zurücksetzen, bei Timerüberlauf n Timout auslösen, CRC prüfen,
verarbeiten und Ringpuffer zurücksetzen ist eine Möglichkeit. Wenn das
Signal 0 und 1200Hz ist kannst Du auch nen Timer verwenden um die
Impulsbreite zu messen, quasi Störsignale ausfiltern, ist
programmtechnisch nicht die einfachste Übung aber schon öfter
angewendet. Dazu evtl. den Interrupt auf Flanken stellen und eben bei
steigender Flanke Timer auslesen und zurücksetzen ... bei Überlauf ist
0, bei Wert zwischen x und y ist 1 ...
Du siehst, es gibt viele Möglichkeiten und die im Einzelnen durchzukauen
sprengt leider die Möglichkeiten eines Forumbeitrages
Alex W. schrieb:> Es ist noch zu erwähnen das es ein 2400 Baud Signal ist. Heißt 2400Hz> logisch 0 und 1200Hz logisch 1.
Aha, es handelt sich also um ein seriell codiertes Protokoll.
"TTL-Signal" ist da ziemlich irreführend.
Ohne eine genaue Code- und Protokollbeschreibung ist da nichts zu
machen.
Man muß schon wissen, wie es ausgewertet werden soll.
Peter
http://de.wikipedia.org/wiki/Logikpegel
Soviel zu deiner Frage.
Du erhælst also ein Logik-Signal mit TTl-Pegeln, wie diese Signalfolge
aussieht kønnen wir nur raten. Interessant wære das Protokoll...
Ok
Das Eingangssignal hat einen Vorlauf von 15 Bits(111111000000000).
Danach 1 Startbit (logisch 1). Jetzt kommen die jeweiligen Bytes mit
Information(je nach Telegramm mit unterschiedlicher Länge(1-20 Bytes)).
Getrennt werden Sie mit einem Stopbit (logisch 1). Im Nachhinein wird
über das Telegramm eine CRC checksum erstellt und hinten angehängt (2
Byte's). Nach der Auswertung wird das Telgramm über RS232 an den PC
weitergeleitet.
Meine Idee wäre:
if(Vorlauf == Bitstruktur(wie oben))
{
while(tu das solange bis 8 bits geschrieben wurden)
{
if(positive Flanke & Dauer von 1200Hz)
{
schreib eine 1 ins Bit Array und shifte um 1 nach rechts
}
if(negative Flanke & Dauer von 2400HZ)
{
schreibe eine 0 ins Bit Array und shifte um 1 nach rechts
}
}
dann verwerfe das StoppBit und führe obiges bis zum ende des Telegramms
aus
}
Es sieht primitiv aus und es fehlen einige Kontrollstrukturen, aber so
ungefähr wollte ich das machen.
Fehlen da irgendwelche grundlegenden Strukturen?
Zwei aufeinander folgende Nullen? Sind eine positive und eine negative
Flanke.
Warum nicht den Pin-Change-Interrupt und einen freilaufenden Timer (mit
Ticker im Bereich 100us)? Dann kannst du gleich kleinere Unterschiede im
Takt zwischen Sender und Empfänger ausgleichen.
Und das Stop Bit nicht verwerfen sondern kontrollieren.
Und noch ne blöde Frage: Warum nicht gleich ein normales asynchrones
Format, wie es jeder UART kann? Gleichstromfrei wirst du mit deinem
Verfahren ohne weitere Klimmzüge auch nicht. Dann doch besser einen
Standard Code (Manchester wäre das Stichwort).
Georg G. schrieb:> Zwei aufeinander folgende Nullen? Sind eine positive und eine negative> Flanke.
Wie gesagt es fehlen noch einige Kontrollstrukturen.
Georg G. schrieb:> Und noch ne blöde Frage: Warum nicht gleich ein normales asynchrones> Format, wie es jeder UART kann? Gleichstromfrei wirst du mit deinem> Verfahren ohne weitere Klimmzüge auch nicht. Dann doch besser einen> Standard Code (Manchester wäre das Stichwort).
Weil diese Norm kurz nach Christis geburt verabschiedet wurde und gesagt
wurde das,dass Telegramm so aussehen muss ;). Und ich muss mich daran
halten.
Also liegt es nicht in meiner Hand.
Reg mich auch drüber auf, das veraltete System nicht modernisiert
werden, wie in meinem Beispiel.
Alex W. schrieb:> Es sieht primitiv aus und es fehlen einige Kontrollstrukturen, aber so> ungefähr wollte ich das machen.> Fehlen da irgendwelche grundlegenden Strukturen?
Gib doch mal einen Link auf die Originalbeschreibung des Senders. Aus
deinem Kauderwelsch wird doch kein Mensch schlau.
Wo kommt denn das Signal her?
Ein Array ist da doch ziemlich unpraktisch oder nicht? Da verbraucht man
pro bit doch ein Byte, wenn man z.B. char arr[160]; nimmt.
Ich hätte das bit in ein Byte geschrieben (MSB oder LSB, ja nach
Protokoll) und dann nach links bzw rechts geschiftet. Solange bis die 8
Bit durch sind und dann eine nächste Variable genommen. Also dann eher
"char arr[20];" und pro 8 bit den Index um 1 erhöhen.
Aus dem CMX469 kommt das Signal (Telegramm) raus. Den Telegrammaufbau
hab ich oben beschrieben.
Michael Skropski schrieb:> Ein Array ist da doch ziemlich unpraktisch oder nicht?
deswegen steht da ja auch Bit-Array.
Alex W. schrieb:> if(positive Flanke & Dauer von 1200Hz)> {> schreib eine 1 ins Bit Array und shifte um 1 nach rechts> }
"CMX469" war ein gutes Stichwort. Peda hat Recht, Steinzeit der
Elektronik.
Dann mal viel Spass. Zu dem Thema gibt es n+1 Beispiel Codes, meist
Assembler (C wurde damals gerade erfunden). Google ist dein Freund.
BTW: Welchen CRC nimmst du? Welches Polynom, welchen Startwert?
Georg G. schrieb:> BTW: Welchen CRC nimmst du? Welches Polynom, welchen Startwert?
Das Generatorpolynom ist wie das IC, sehr eigen. Auf jedenfall nichts
standardmäßiges.
Und Startwert müsst nochmal nachgucken, aber ich glaub der war 0000;
Alex W. schrieb:> Aus dem CMX469 kommt das Signal (Telegramm) raus. Den Telegrammaufbau> hab ich oben beschrieben.
Da ist noch (auf tiefer Ebene) so viel unklar, dass man damit wenig
anfangen kann. Und das nicht zuletzt deshalb, weil nicht klar ist,
inwiefern da überhaupt die Einheit "Herz" reinspielt. "Herz" ist keine
vernünftige Angabe für Pulslängen.
Also: was kommt da überhaupt daher?
Sind das EInzelpulse mit definierten Längen, ist das ganze vielleicht
frequenzmoduliert? Oder wie oder was?
Deine Telegrammschicht in allen Ehren. Aber noch ist überhaupt nicht
klar, wie denn die Bitdarstellung ist und wie man ein 1-Bit von einem
0-Bit unterscheidet. Und ich denke, damit sollte man erst mal anfangen.
Alex W. schrieb:> Aus dem CMX469 kommt das Signal (Telegramm) raus. Den Telegrammaufbau> hab ich oben beschrieben.
Du hast gar nichts beschrieben. Es fehlen mindestens folgende Angaben:
1. Wie lange muss das Signal mit 1/2400 bzw. 1/1200 anliegen,
damit es als eine 0 bzw. 1 erkannt werden muss? Eine tausendstel
Sekunde? Eine hundertstel Sekunde? Oder gar eine Sekunde?
2. Wie erkennt man zwei/drei/vier Einsen hintereinander? Ist da Pause
zwischendurch? Oder ist das Signal dann einfach doppelt/dreifach/
vierfach so lang?
Karl Heinz Buchegger schrieb:> Also: was kommt da überhaupt daher?
Es ist ein einziges, elendes Gestammel.
Anstatt dem TO alles aus der Nase zu ziehen, sollte man ihm an der Nase
ziehen oder sonstwohin treten. Wenn ich dann noch 'Firma: FH' lese, dann
ist das doch eine erschreckende Vorstellung.
Alex W. schrieb:> Das Eingangssignal hat einen Vorlauf von 15 Bits(111111000000000).> Danach 1 Startbit (logisch 1). Jetzt kommen die jeweiligen Bytes mit> Information(je nach Telegramm mit unterschiedlicher Länge(1-20 Bytes)).> Getrennt werden Sie mit einem Stopbit (logisch 1). Im Nachhinein wird> über das Telegramm eine CRC checksum erstellt und hinten angehängt (2> Byte's).
Könnte glatt ein POCSAG-Telegramm sein... Dazu passt auch der antike
KCS.
Grüße
Stefan
hmmm ... wenn ich mir das Datenblatt anschau:
http://www.datasheetarchive.com/dataframe.php?file=DSA-138162.pdf&dir=Datasheets-7&part=CMX469A#
schaut das für mich nach FM-Übertragung aus, sprich die 0 ist nich "kein
Signal", sondern hohe Frequenz, 1 ist niedrige Frequenz ... ne Kippstufe
als Eingang und Impulslänge mit Timer messen, wird nicht anders gehen
aus meiner Sicht.
Welcher Interrupt ob Pin Change oder Flanke kommt auf die
Eingangsschaltung an.
> Aus dem CMX469 kommt das Signal (Telegramm) raus.
Ach, da ist ein Frequenzdemodulator im Spiel.
Na super. Schön das man diese Information dann auch nach 3 Seiten
Postings auch schon bekommt.
Damit wird dann Franks Nachfrage
Beitrag "Re: TTL Signal Verarbeitung"
zur relevanten.
Ich habe mir ausgehend von
http://dtusat1.dtusat.dtu.dk/group.php?c_gid=7
das Datenblatt
http://dtusat1.dtusat.dtu.dk/files/filedl.php?fileid=1289
mal angeschaut.
Das, was ich da sehe, sind schöne Sinussignale am TX. Das ganze ist also
ein analoges Modem. Einfach das als TTL-Pegel bezeichnen würde ich das
nicht.
Wenn ich mir darin die "Interface Timing Diagrams" anschaue, wird eine 1
mit einer einzigen(!) Halbwelle bzw. 0 mit einer Vollwelle der doppelten
Frequenz ausgegeben. Das passt natürlich zu den Angaben des TO, dass die
Baudrate 2400Bd beträgt, aber eine "1" durch lediglich 1200Bd
repräsentiert wird.
Wenn der TO wirklich da ein TTL-Rechtecksignal "sieht" (durch
irgendeinen Sinus-nach-Rechteck-Wandler), dann wird eine "1" durch eine
Pegellänge von 833µs, eine "0" durch zwei Pegellängen von je 417µs
ausgegeben.
Wie man diesen Wellensalat nun z.B. auf Bytegrenzen synchronisiert, habe
ich jetzt aber nicht mehr aus dem Datenblatt herauslesen wollen.
Frank M. schrieb:> Wie man diesen Wellensalat nun z.B. auf Bytegrenzen synchronisiert, habe> ich jetzt aber nicht mehr aus dem Datenblatt herauslesen wollen.
Ich antworte mir mal selbst:
Das steht auch gar nicht drin, für das Protokoll ist das Modem gar nicht
zuständig. Vermutlich gibt es da ein Startbit, 8 Bit Daten und ein
Stopbit.
Das könnte man mit einer einfachen Anpassung im IRMP erschlagen,
indem man die Puls-/Pausenverhältnisse als neues
Pulse-Distance-Protokoll parametrisiert - mit der Besonderheit, dass die
"0" zwei Pegellängen besitzt statt einer. Ich halte aber die ganze
Anwendung für zu exotisch, um mir das antun zu wollen ;-)
Jetzt, wo die Signalform klar ist, zur ursprünglichen Frage:
Alex W. schrieb:> Lese ich das komplette Telegramm (max. 32Byte) komplett in ein array ein> und verarbeite es dann? Sollte ich das mit einer ISR abfangen? Mit einem> Timer arbeiten?
Setze einen Timer auf, wo Du in der ISR die Pulslängen misst. Fülle in
der ISR Dein 32-Byte-Array auf und setze ein Flag, sobald die 32 Byte
eingelesen sind.
Werte dann Dein Array im Hauptprogramm aus, sobald das Ready-Flag
gesetzt ist. So macht das IRMP auch.
Viel Glück,
Frank
Jetzt hab ich endlich das Oszi, hier noch einmal das Signal bzw.
Telegramm. blau geht als NF-Signal in den CMX und türkis kommt als
serielles Telegramm raus.
In diesem Fall trifft es den Nagel auf den Kopf. Bilder sagen mehr als
tausend Worte.
Hallo
Das sieht doch wunderbar aus.
Startbit, 9 Datenbits, Stopbit.
Geschwindigkeit ausrechnen.
Pegel anpassen
An UART anschließen
UART richtig einstellen
Daten empfangen
Gruß
Joachim
Ach ja, hast du eigentlich das Datenblatt vom CMX469 (kein CMX469A?)
gelesen?
Am Ausgang RxSync hast du den zurückgewonnen Bittakt. Du musst nur auf
der fallenden Flanke sampeln.
Der Anschluss des Modems sieht also so aus:
Ein Portbit als Dateneingang (braucht nicht interruptfähig sein).
RxSync auf einen externen IRQ legen und auf der fallenden Flanke
auslösen lassen. In der Interruptroutine liest du dann das aktuelle Bit
vom anderen Port ein.
Wie du die Bits zusammensetzen und ob du Füllbits entfernen musst, sagt
dir die (immer noch nicht benannte) Protokollspezifikation.
Grüße
Stefan
XXX schrieb:> Das sieht doch wunderbar aus.> Startbit, 9 Datenbits, Stopbit.
Vorsicht! Der CMX469 wurde gern für POCSAG-Anwendungen und
vergleichbares verwendet. Das sind in der Regel bitsynchrone Protokolle,
nichts asynchrones.
Grüße
Stefan
Stefan Wagner schrieb:> Ach ja, hast du eigentlich das Datenblatt vom CMX469 (kein CMX469A?)> gelesen?
Um Missverständnisse zu vermeiden: Die Frage ging an den OP.
Grüße
Stefan
Danke Stefan.
Ja ich hatte mir nur CMX469A durchgelesen. Die Idee mit dem RxSync ist
super und wenn mich nicht alles täuscht auch nicht schwer zu
implementieren.
Mache mich mal auf die Socken und versuche das zu implementieren.
XXX schrieb:> Startbit, 9 Datenbits, Stopbit.
Das sind 8 bits + Stopbit.
Alex W. schrieb:> In diesem Fall trifft es den Nagel auf den Kopf. Bilder sagen mehr als> tausend Worte.
Ach, Du hängst auf der digitalen Seite und nicht auf der analogen Seite
des CMX? Sag das doch gleich, dann hätte man sich die Rätselei mit
"1=1200Bd" und "0=2400Bd" absolut sparen können.
Suboptimal, dass hier die Informationen nur tröpfchenweise geflossen
sind.
Alex W. schrieb:> Mache mich mal auf die Socken und versuche das zu implementieren.
Das Einlesen des einzelnen Bits ist nur ein Teil des Ganzen.
> Das sind 8 bits + Stopbit.
Ich halte es für sehr unwahrscheinlich, dass auf einen bereits
bitsynchronisierten Bitstrom noch ein asynchrones Framing draufgepackt
wurde. Das wäre schlicht überflüssig.
Anhand des bis jetzt bekannten Hintergrunds erscheint mir viel
wahrscheinlicher, dass über eine Flag-Sequenz auf den Telegrammstart
synchronisiert wird und dann entweder eine fixe Telegrammlänge erwartet
wird oder aber die jeweils zu erwartenden Telegrammlänge über einen
vordefinierten Header codiert ist. Das bedeutet, du liest so viele Bits
ein, wie vordefiniert bzw. im Header angegeben, dann die Bits der FCS
(Frame Check Sequence, meist ein CRC). Dann ist das Telegramm komplett
und das Programm wartet wieder auf die Flagsequenz.
Typische Beispiele für solche Protokolle sind FMS und POCSAG.
Aber welches Protokoll ist es denn nun in deinem Fall? Ohne die Info
kommt man nicht weiter.
Grüße
Stefan
So gestern hat es mit em Starten nicht geklappt. Aber heute und ich
komme gerade nicht weiter. Habe auch die Register so gesetzt wie im
DAtenblatt steht aber der Interrupt will bei mir nicht. Hab ich
eventuell ein Register oder iwas anderes vergessen zu setzten oder kann
der Code aus anderen Gründen nicht funktionieren?
Hier ist ein Ausschnit aus dem Code. Es handelt sich nur um eine
Testfunktion, ob der Int0 überhaupt was tut.
steht in Telegramm.h und wird in main.c eingebunden.
1
volatileuint8_tgetBit;
2
ISR(INT0_vect)
3
{
4
getBit=1;
5
}
main.c
1
// Initialisierungen externen Interrupt des dig. Signals
2
EIMSK|=(1<<INT0);// Maske für den Int0
3
EICRA|=(1<<ISC01);// INT0 auslösen bei fallender Flanke
Alex W. schrieb:> Hier ist ein Ausschnit aus dem Code. Es handelt sich nur um eine> Testfunktion, ob der Int0 überhaupt was tut.
Punkt 1:
Testprogramme können nicht einfach genug sein.
Welchen Sinn hat es die 15 Zeilen eines Testprogramms auf möglichst
viele Files aufzuteilen? Das führt doch nur dazu, dass man überhaupt
nichts mehr sieht
Punkt 2:
Auch wenn das nur ein Testprogramm ist, ist eine ordentliche
Codestrukturierung ein absolutes MUSS. Immer! Dazu gehören auch
vernünftige Einrückungen. Die sind nicht Selbstzweck oder dienen dazu
damit der Boss happy ist, sondern die sind dein Werkzeug um dir optisch
die Struktur eines Codes klar zu machen. Und die muss man konsequent
einsetzen.
Dann fällt dir zb auch auf, dass in deiner Hauptschleife nur das erste
if enthalten ist, weil du die { } Blockklammern beim while vergessen
hast
Punkt 3:
Poste immer vollständigen Code! Dadurch gibst du uns auf der anderen
Seite des Bildschirms die Möglichkeit, deinen Code auch mal
auszuprobieren. Und: Es kommt gar nicht so selten vor, dass das
eigentliche Problem im Code gar nicht dort ist, wo du denkst, das es
wäre, sondern ganz woanders. Da du aber die Reste deines Codes nicht
zeigst, kann das hier auch keiner sehen. Speziell bei einfachen
Testprogrammen ist der Code nicht umfangreich. Den kompletten Code
posten ist also auch für dich weniger Aufwand und auf dieser Seite des
Bildschirms sieht man alles, was man sehen muss und wir brauchen nicht
blöd nachfragen. Ein BWL-er würde sagen: eine Win-Win Situation.
Ich dachte ich tue einen gefallen und poste nicht alles, damit das nicht
zu viel wird und von der Hauptsache ablenkt. Eine Codestrukturierung
versuche ich immer einzuhalten. In diesem Fall hab ich sie nur ausser
acht gelassen, da es sich um einen Test handelt und keine fertige bzw.
endgültige Version.
Ansonsten ist im Anhang der komplette Code.
Ratschlag mit KomplettCodeAnhängung wargenommen und akzeptiert.
Schmeiss doch erst mal den ganzen restlichen Schwachsinn raus, ok?
Ein Testprogramm hat eine Aufgabe. Dein Testprogramm soll feststellen ob
dein INT0 funktioniert. Nicht mehr und nicht weniger. Also mach das auch
- nicht mehr und nicht weniger. Kein Mensch braucht dabei Kommandos, die
zu einem Gerät geschickt werden (oder auch nicht), Kommandos die von
einem PC kommen (oder auch nicht), Taster die dafür sorgen das Kommandos
geschickt werden (oder auch nicht). Und im Regelfall wird auch die UART
Kommunikation reibungslos funktionieren, wenn sie erst mal funktionirt,
d.h. Frame Errors kann man in einem Testprogramm erst mal ignorieren.
Und plötzlich ist dein Testprogramm ganz kurz und konzentriert sich auf
das was du testen willst. Dass deine UART funktioniert glaub ich dir
auch so. Das brauchst du nicht testen. (zumindest jetzt nicht mehr, wenn
sie gestern funktioniert hat, funktioniert sie auch heute)
An welchen Pin hast du deinen Eingang angeschlossen?
INT0 ist am Pin PD0.
Dort liegt auch SCL. Ist an dem Pin sonst noch was angeschlossen? (zb
ein ISP Programmer?)
Karl Heinz Buchegger schrieb:> An welchen Pin hast du deinen Eingang angeschlossen?
Hast du überhaupt dein Gerät angeschlossen?
Wenn es nur darum geht, den Interrupt zu testen würde ich das gar nicht
tun.
Taster an den Interupt Eingang, der nach Masse schaltet. Pullup
Widerstand dazuschalten und passt schon. Jede Komponente mehr bringt nur
mehr zusätzliche mögliche Fehlerquellen.
1
#define F_CPU 4000000UL
2
#define BAUD_RATE 9600
3
4
#include<stdlib.h>
5
#include<avr/io.h>
6
#include<avr/interrupt.h>
7
8
#include"uart.h"
9
10
volatileuint8_tgetBit;
11
12
ISR(INT0_vect)
13
{
14
getBit=1;
15
}
16
17
intmain(void)
18
{
19
DDRD=0x00;// Port D als Eingang setzen
20
PORTD=0x01;// INT0 liegt an PD0
21
22
uart2_init(UBRR_BERECHNUNG(BAUD_RATE,F_CPU));
23
24
EIMSK|=(1<<INT0);// Maske für den Int0
25
EICRA|=(1<<ISC01);// INT0 auslösen bei fallender Flanke
26
27
sei();
28
29
uart2_puts("Und scharf!\n");
30
31
while(1)
32
{
33
if(getBit)
34
uart2_putc('1');
35
else
36
uart2_putc('0');
37
}
38
}
reicht schon. Damit kann man schon testen. Die UART ist zwar eine
mögliche zusätzliche Fehlerquelle aber durch die Ausgabe des Textes vor
dem eigentlichen arbeiten hat man eine Kontrolle, ob die UART
funktioniert. Programm laufen lassen und auf den Taster latschen und
nachsehen ob sich die Dauerausgabe von 0 auf 1 ändert. Wenn ja -
Gratulation: der INT0 funktioniert erst mal.
Hab ihn.
Hatte den ISP net an im AS. Dachte mir auch gerade warum er mir auf die
Pinabfragen antwortet wobei die gar net verwendet werden.
Aufmerksamkeitsfehler höchsten Grades.
Aber an sich funktioniert jetzt alles einwandfrei, INT0 löst aus und
uart sendet dann auch as Zeichen.
Danke für die Erkenntnis wie man Fehler einkreist und eliminiert.
Alex W. schrieb:> Hab ihn.>> Hatte den ISP net an im AS. Dachte mir auch gerade warum er mir auf die> Pinabfragen antwortet wobei die gar net verwendet werden.> Aufmerksamkeitsfehler höchsten Grades.
Siehst du.
Und genau deshalb ist es SO wichtig, dass Testprogramme einfach sind. Je
weniger Fehlermöglichkeiten du einbaust, desto weniger Fehler kannst du
auch tatsächlich machen.
So ich hab nach einer privaten Pause mal damit angefangen meine
ankommenden Daten auszuwerten.
Doch leider macht das mein Code nicht so wie ich will. ;)
Kurz zum Code: An meinem INT0 kommt das digitale Sync Signal an(2400
baud). Mit der fallenden Flanke am INT0 frage ich den Pin D2 ab, wo mein
digitales Signal(1200/2400 Baud) ankommt. Um die Bits in ein Byte zu
schreiben frage ich nach dem Interrupt Flag ab und schreibe dann die
entsprechenden Bits per shift in eine 16 Bit variable.
Angefügt, als Bild, hab ich noch die ankommenden Daten am PC die mir der
µC ausgibt und den Code.
Ich empfange unterschiedliche Anzahlen von eingelesenen Bit's, ich gebe
doch mit meiner for-Schleife vor das es nur 8 Bits sein sollen?
Erst dachte ich das pro for-Schleifen Durchlauf die Zeit ein Rolle
spielt, dann hab ich jedoch gerechnet und 1 Takt dauert bei 4Mhz ca.
0,25µs wobei die Daten jede 0,42ms ankommen. D.h. das zwischen den
jeweiligen eingelesenen Bits 1680 Takte liegen. Braucht mein
For-Schleife denn soviel Takte? Sollte ich eine Abbruchbedingung für 8
eingelese bits einfügen wie z.B. if (n==8){break;}?
Ist das richtig das ich nur 2Byte shiften kann, also ein int? D.h. das
ich dann z.B. die 16 bit variable so ausgeben muss
tmpcheck = (byte[0] << 8) + byte[1]; ?
Alex W. schrieb:> Doch leider macht das mein Code nicht so wie ich will.
Offen gesagt: Das wundert mich nicht. Du scheinst immer noch vieles nur
halb oder gar nicht verstanden zu haben.
> Kurz zum Code: An meinem INT0 kommt das digitale Sync Signal an 2400> baud). Mit der fallenden Flanke am INT0 frage ich den Pin D2 ab, wo> mein digitales Signal(1200/2400 Baud) ankommt.
Du solltest die richtigen Begriffe verwenden: Der Ausgang RxSync des
Modem-IC ist der Bittakt, auf dessen fallender Flanke das demodulierte
Empfangssignal gültig ist. INT0 wird also durch die fallende Flanke des
Bittakts getriggert. Zu diesem Zeitpunkt liest du das an PD2 anliegende
Bit ein.
Der Bittakt hat übrigens eine fixe Frequenz von 2400 Hz. Die Einheit
"Baud" ist hier falsch! Das Empfangssignal hat eine Bitrate von 2400
bit/s (auch hier ist "Baud" nicht richtig). Ansonsten:
http://de.wikipedia.org/wiki/Baud> Um die Bits in ein Byte zu schreiben frage ich nach dem Interrupt> Flag ab und schreibe dann die entsprechenden Bits per shift in eine> 16 Bit variable.
Das ist extrem umständlich und unnötig. Diese Bitschieberei gehört in
die ISR. Dorthin gehört sinnvollerweise auch die Byte- bzw.
Telegrammsynchronisation (Vergleich mit dem Startwort bzw. Flag).
Hier ein Beispiel, bei dem das MSB zuerst übertragen wird und die
Bytesynchronisation über ein 8 Bit breites Flag erfolgt.
#define BB_MSB_1 0x80 // Maske für 1 am MSB von bitbuf
18
#define FLAG 0x7e // vom Protokoll vorgegeben
19
20
ISR(INT0_vect)
21
{
22
staticuint8_tbitbuf=0;
23
staticuint8_tbitcnt;
24
staticboolbytesync=FALSE;
25
26
bitbuf>>=1;// Platz für das neue Bit schaffen
27
if(PIND&DATA_IN)// und in das MSB schreiben
28
{
29
bitbuf|=BB_MSB_1;
30
}
31
32
if(bytesync)
33
{
34
if(--bitcnt==0)// 8 Bit eingelesen
35
{
36
// bitbuf weiterreichen, z.B. in einen Ringpuffer
37
38
bitcnt=BITBUF_BITS;
39
}
40
}
41
elseif(bitbuf==FLAG)
42
{
43
bytesync=TRUE;
44
bitcnt=BITBUF_BITS;
45
}
46
}
Der Code ist rein als Beispiel gedacht und ungetestet.
Was fehlt, ist das Erkennen des Verlusts der Bytesynchronisation, weil
das sehr protokollabhängig ist. Ebenso fehlen Mechanismen für ein
eventuelles Bit- oder Bytestuffing.
Erfolgt die Synchronisation mit einem 16 Bit oder 32 Bit breiten Wort,
musst du bitbuf auf uint16_t bzw. uint32_t ändern und natürlich
BITBUF_BITS und BB_MSB_1 anpassen.
Ansonsten, wie gesagt: Eigne dir die Grundlagen an! Du wirst sonst
weiter massive Probleme haben.
Grüße
Stefan
PS: Separat kompilierte C-Quelltextdateien mit Daten- und/oder
Funktionsdeklarationen erhalten üblicherweise die Extension ".c". Die
Extension ".h" ist für Dateien vorgesehen, die ausschließlich
Definitionen oder Präprozessor-Makros enthalten und über #include
eingebunden werden.
Alex W. schrieb:
Abgesehen von dem was Stefan schon gesagt hat
> digitales Signal(1200/2400 Baud) ankommt. Um die Bits in ein Byte zu> schreiben frage ich nach dem Interrupt Flag ab
Aber sicher nicht so
1
if(INTF0==0)
Wie fragt man denn ein Bit in einem Register ab?
Ausserdem: Das Interrupt Flag wird automatisch gelöscht, sobald die ISR
betreten wird. D.h selbst wenn du die ABfrage hier richtig stellst wird
das nicht funktionieren (zumindest nicht in 95% aller Fälle), weil du
das Interrupt Flag gar nicht gesetzt erwischt (weil es längst durch den
Aufruf der ISR wieder gelöscht wurde)
Stefan Wagner schrieb:>> Kurz zum Code: An meinem INT0 kommt das digitale Sync Signal an 2400>> baud). Mit der fallenden Flanke am INT0 frage ich den Pin D2 ab, wo>> mein digitales Signal(1200/2400 Baud) ankommt.>> Du solltest die richtigen Begriffe verwenden: Der Ausgang RxSync des> Modem-IC ist der Bittakt, auf dessen fallender Flanke das demodulierte> Empfangssignal gültig ist. INT0 wird also durch die fallende Flanke des> Bittakts getriggert. Zu diesem Zeitpunkt liest du das an PD2 anliegende> Bit ein.> Der Bittakt hat übrigens eine fixe Frequenz von 2400 Hz. Die Einheit> "Baud" ist hier falsch! Das Empfangssignal hat eine Bitrate von 2400> bit/s (auch hier ist "Baud" nicht richtig). Ansonsten:> http://de.wikipedia.org/wiki/Baud
erstens das und zweitens interessiert das nur insofern, als
sichergestellt sein muss, dass die Interrupts nicht zu schnell kommen
und den AVR überfordern. Mit 2400Hz ist man aber weit weg von jeglicher
Gefahr. So gesehen interessiert diese Zahlenangabe keinen.
Die Flanke kommt - der Dateneingang wird ausgewertet, nach 8 Flanken hat
man ein Byte beisammen. Mehr braucht man nicht. Einzig das Herstellen
der Bytesynchronisierung ist eine knifflige Sache. Aber auch dafür hast
du ja schon was vorgesehen (obwohl ich mir nicht sicher bin ob das so in
seinem konkreten Fall funktioniert)
Ich hab mir die Grundlagen angeignet, nur viele (meisten) Sachen lernt
mit der Zeit und an Beispielen.
z.B. hab ich gelesen das die Interrupts so kurz wie möglich gehalten
werden sollen, ergo hab ich das gemacht.
Und die Daten extern in einer Funktion verareitet.
Vielen Dank, für das Beispiel. Merke daran das ich gewisse Sachen anders
realisiseren müsste.
Stefan Wagner schrieb:> static bool bytesync = FALSE;
Wird das nicht nach jedem Interrupt FALSE gesetzt, sodass dies
if (bytesync) nie eintreffen kann?
Alex W. schrieb:> Ich hab mir die Grundlagen angeignet, nur viele (meisten) Sachen lernt> mit der Zeit und an Beispielen.> z.B. hab ich gelesen das die Interrupts so kurz wie möglich gehalten> werden sollen, ergo hab ich das gemacht.
so kurz wie möglich heißt nicht, das man gar nichts machen darf.
Wenn sich dadurch der restliche Code extrem verkompliziert oder
fehleranfällig wird, dann ist man übers Ziel hinausgeschossen.
Du bist es. Ein paar Bits zurecht zu schieben, ein paar Variablen zu
inkrementieren und abzufragen, ist noch lange nicht am Limit von 'so
kurz wie möglich'. Das sind in Summe vielleicht 10 oder 20
Prozessortakte, die da verbraucht werden. Bei ein paar Mhz Taktfrequenz
ist das ein verschwindend geringer Anteil an der Gesamtzeit.
Quadratische Gleichungen lösen, die Bibel per serieller Schnittstelle zu
verschicken, auf Tasterbetätigung durch den Benutzer warten, _delay_ms
verwenden, .... das wären Beispiele davon, wo gegen 'so kurz wie
möglich' verstossen wird.
Du hast ja auch das umgekehrte Problem:
Was nützt es dir, wenn deine ISR mit Volldampf Bits generieren kann,
wenn die Hauptschleife dann gar nicht mehr nachkommt?
Alex W. schrieb:>> static bool bytesync = FALSE;>> Wird das nicht nach jedem Interrupt FALSE gesetzt, sodass dies>> if (bytesync) nie eintreffen kann?
Soviel zu
> Ich hab mir die Grundlagen angeignet
Was macht denn das static an dieser Stelle?
Karl Heinz Buchegger schrieb:> Was macht denn das static an dieser Stelle?
ich hatte das static in diesem Fall als Gültigkeitsbereichdefiniton im
Kopf. Wird natürlich nicht immer wieder neu erzeugt. Sorry, mein Fehler.
Stefan Wagner schrieb:> Was fehlt, ist das Erkennen des Verlusts der Bytesynchronisation, weil> das sehr protokollabhängig ist. Ebenso fehlen Mechanismen für ein> eventuelles Bit- oder Bytestuffing.
Was ist mit Verlust der Bytesynchronisation gemeint?
Alex W. schrieb:> Was ist mit Verlust der Bytesynchronisation gemeint?
Bei einem bitseriellen Datenstrom hast du keine "eingebaute" Erkennung
der Grenzen des Datenworts (in der Regel sind das Oktette, also Bytes).
Irgendwie muss also auch eine Information über die Wortgrenze mit
übertragen werden. Gleiches gilt für Beginn und Ende eines Datenblocks
(Telegramm, Frame).
In der Regel nimmt man dafür eine spezielle Bitsequenz (Flag), die
ausschließlich zum Kennzeichnen eines Blockanfangs verwendet wird. Damit
es zu keiner Fehlerkennung kommt, müssen Datenwerte, die dem Flag
gleichen, über ein definiertes Verfahren "maskiert" werden. (Dazu weiter
unten mehr.)
Bei kurzen Datenblöcken, die immer gleich aufgebaut und gleichlang sind
(z.B. Funkruf-Telegramme) reicht in vielen Fällen das Flag-Wort am
Beginn. Das Ende des Datenblocks kann durch simples Abzählen der seit
dem Flag empfangenen erkannt werden.
Bei Protokollen, die variable Blocklängen und beliebige Inhalte
zulassen, wird entweder ein kurzer, definierter Kopf, der einen
Längenzähler enthält, verwendet, oder man kennzeichnet das Ende
ebenfalls durch ein Flag. (Beispiel: HDLC)
Sender und Empfänger können nach Aufbau der Bit- und Bytesynchronität
durch Störungen "aus dem Tritt kommen" und ein einzelnes Bit geht
verloren. Danach ist die Bytesynchronität ebenfalls weg.
(Siehe z.B. http://de.wikipedia.org/wiki/Bitslip )
Man muss also regelmäßige "Synchronpunkte" einbauen.
Jetzt noch zur "Maskierung" von Datenwerten, die gleich dem Flag sind.
Es gibt zwei grundsätzliche Verfahren, die Bitstuffing bzw. Bytestuffing
genannt werden.
Bitstuffing wird z.B. bei HDLC verwendet. Das Flagbyte bei HDLC hat den
Wert 0b01111110 (0x7e), also 6 '1'-Bits umrahmt von je einem '0'-Bit.
Damit es zu keiner Verwechselung kommt, wird vom Sender bei den Daten
nach fünf aufeinander folgenden '1'-Bits immer ein '0'-Bit eingefügt
("dazwischengestopft", daher auch der Name "Bitstuffing". Der Empfänger
entfernt entsprechend immer ein nach 5 '1'-Bits in Folge auftretendes
'0'-Bit.
Bytestuffing ist das Äquivalent auf Byteebene. Tritt ein Datenbyte auf,
dass gleich einem reservierten Wert ist, wird ein spezielles
Markierungsbyte in den Datenstrom eingefügt, das Datenbyte nach einer
vordefinierten Regel (reversibel) umgewandelt und hinter das
Maskierungsbyte gehängt. (Verwendet z.B. bei PPP.)
Grüße
Stefan
Stefan Wagner schrieb:> Das Ende des Datenblocks kann durch simples Abzählen der seit> dem Flag empfangenen erkannt werden.
Das muss heißen: "der seit dem Flag empfangenen Bits"
Grüße
Stefan
Protokoll-Aufbau:
2 Bytes Vorlauf (weiter unten), die Infobytes 1-3 und 2 Bytes für die
CRC Prüfung. Zusatzbytes werden entsprechende des verwendeten
Telegramms, diese werden nach den Infobytes eingefügt. Die Anzahl der zu
ergänzenden Zusatzbytes steht im 2. Infobyte in den Bits 0-3.
Zur Synchronisation dient ein 15 Bit langer Flag. Dieser hat führend
sechs Bits logisch 1 zur Bitsynchronisation und folgend neun Bits
logisch 0 für die Rahmensynchronisierung. Der Vorlauf wird mit einem
Startbit abgeschlossen und der Anfang der Informationswörter
eingeleitet.
Gesendet werden die Info- bzw. Zusatzbytes gedreht(Als Sender wird hier
der CMX bezwichnet, der den Bitstrom bzw. Bytestrom an den µC
sendet)d.h. LSB-First.
Zwischen jedem gesendeten Byte wird ein Sperrbit eingeschoben um die
Informationswörter von einander zu trennen.
Bitstuffing wäre in diesem Fall nicht nötig, wohl eher "Bitdestuffing"
um die jeweiligen Sperrbits zu entfernen.Das Telegram später per RS232
weitergeschickt.
/*
Bitweises Einlesen der synchronen Daten vom Modem.
INT0 wird auf der fallenden Flanke des Bittakts getriggert,
das Datenbit an PD2 ist zu diesem Zeitpunkt gültig.
Die empfangenen Bits werden in den Empfangspuffer bitbuf geschoben.
Die byteweise Synchronisation wird über den Vergleich mit dem Flag
ermittelt. Sobald bitbuf == FLAG ist, ist das nächste Bit das erste
des folgenden Bytes.
Das Flag bytesync gibt an, ob die Byte-Synchronität erreicht ist.
bitcnt ist der Zähler für die jeweils empfangenen Bits je Byte.
/*
#define DATA_IN (1<<PD2)
#define BITBUF_BITS 8 // Größe von bitbuf in Bits
#define BB_MSB_1 0x80 // Maske für 1 am MSB von bitbuf
#define FLAG 0x7e // vom Protokoll vorgegeben
ISR(INT0_vect)
{
static uint8_t bitbuf = 0;
static uint8_t bitcnt;
static bool bytesync = FALSE;
bitbuf >>= 1; // Platz für das neue Bit schaffen
if (PIND & DATA_IN) // und in das MSB schreiben
{
bitbuf |= BB_MSB_1;
}
if (bytesync)
{
if (--bitcnt == 0) // 8 Bit eingelesen
{
// bitbuf weiterreichen, z.B. in einen Ringpuffer
bitcnt = BITBUF_BITS;
}
}
else if (bitbuf == FLAG)
{
bytesync = TRUE;
bitcnt = BITBUF_BITS;
}
}
Deinen obigen Quellcode habe ich versucht Stefan. Da ist mir was
aufgefallen, manchmal bzw. öfters passiert es das er anstatt 8, nur 7,6
oder gar 5 Bits einließt. Das ist ja dieser sogenannte Bit-Slip. Wie
kann man diesem entgegenwirken bzw. hier müssen ja jetzt die erwähnten
Synchronpunkte eingebracht werden.
MFG Alex
Rafi Dafi schrieb:> Protokoll-Aufbau:> 2 Bytes Vorlauf (weiter unten), die Infobytes 1-3 und 2 Bytes für die> CRC Prüfung. Zusatzbytes werden entsprechende des verwendeten> Telegramms, diese werden nach den Infobytes eingefügt. Die Anzahl der zu> ergänzenden Zusatzbytes steht im 2. Infobyte in den Bits 0-3.> Zur Synchronisation dient ein 15 Bit langer Flag. Dieser hat führend> sechs Bits logisch 1 zur Bitsynchronisation und folgend neun Bits> logisch 0 für die Rahmensynchronisierung. Der Vorlauf wird mit einem> Startbit abgeschlossen und der Anfang der Informationswörter> eingeleitet.
Also
- ein Startwort mit 16 Bit,
- 3 Bytes Telegrammkopf
- n Bytes Zusatzdaten (n <= 0 <= 15)
- 2 Bytes CRC
Zum CRC: Welches Generatorpolynom und welcher Startwert?
> Gesendet werden die Info- bzw. Zusatzbytes gedreht(Als Sender wird hier> der CMX bezeichnet, der den Bitstrom bzw. Bytestrom an den µC> sendet)d.h. LSB-First.
Ok. LSB first ist recht häufig, das würde ich nicht als "gedreht"
bezeichnen.
> Zwischen jedem gesendeten Byte wird ein Sperrbit eingeschoben um die> Informationswörter von einander zu trennen.
Das ist technisch eigentlich unnötig. Steht das in der
Protokollbeschreibung wirklich explizit so drin?
Was ist das denn nun eigentlich für ein Protokoll? Es wäre wirklich
hilfreich, wenn du entweder den Namen nennen würdest oder die
Protokollbeschreibung im Wortlaut zitieren könntest.
> Bitstuffing wäre in diesem Fall nicht nötig, wohl eher "Bitdestuffing"> um die jeweiligen Sperrbits zu entfernen.
Das muss dann eben in der Schieberoutine (in der ISR) berücksichtigt
werden.
> Das Telegramm wird später per RS232 weitergeschickt.
Gibt es da ein vorgegebenes Datenformat?
Noch mal zum Telegrammkopf: Sind das (wie ich vermute) gepackte Felder,
d.h. ein Byte enthält mehrere Informationen? Das müsstest du noch
angeben.
> Deinen obigen Quellcode habe ich versucht Stefan. Da ist mir was> aufgefallen, manchmal bzw. öfters passiert es das er anstatt 8, nur 7,6> oder gar 5 Bits einließt. Das ist ja dieser sogenannte Bit-Slip. Wie> kann man diesem entgegenwirken bzw. hier müssen ja jetzt die erwähnten> Synchronpunkte eingebracht werden.
Der muss sowieso erst mal umgebaut werden. Um dir eine "Anschubhilfe" zu
geben, mach ich mal einen Modulrumpf, den du dann vervollständigen
kannst.
Lies dir zwischenzeitlich mal die UART-FIFO-Routinen von Peter Danegger
oder Norbert Fleury durch, insbesondere wie die FIFOs funktionieren. Die
brauchst du nämlich für die Schnittstelle zum Hauptprogramm.
Grüße
Stefan
Rafi Dafi schrieb:> Der Vorlauf wird mit einem Startbit abgeschlossen und der Anfang der> Informationswörter eingeleitet.> Zwischen jedem gesendeten Byte wird ein Sperrbit eingeschoben um die> Informationswörter von einander zu trennen.
Das fällt mir erst beim zweiten Lesen so richtig auf. Dieses Protokoll
sieht in der Tat so aus, als ob ein asynchrones Zeichenframing einfach
auf einen synchron übertragenen Bitstrom "aufgestülpt" worden wäre.
Was um Himmels willen ist das?
Grüße
Stefan
Stefan Wagner schrieb:> Das ist technisch eigentlich unnötig. Steht das in der> Protokollbeschreibung wirklich explizit so drin?
ja steht es. kann man auch auf dem oszi bild sehen.
Beitrag "Re: TTL Signal Verarbeitung"
schau auf den letzteren teil. da werden 8bit NULLEN gesendet und
zwischen ihnen das Stop-bit 1.
Stefan Wagner schrieb:> Was ist das denn nun eigentlich für ein Protokoll? Es wäre wirklich> hilfreich, wenn du entweder den Namen nennen würdest oder die> Protokollbeschreibung im Wortlaut zitieren könntest.
Es handelt sich um den Nahverkehr und die Übertragung zwischen Bus und
Ampel für eine schnellere Grünschaltung.
Gesendet wird mit dem Datenformat 8N1.
Und ja es sind gepackte Felder. Aber die kann man ja anschließend nach
dem Empfang des Telegramms analysieren und die entsprechende Infos zu
extrahiern, es geht ja auch darum die Daten erst fehlerfrei einzulesen.
Du hattest ja auch bei dir den Vergleich
Rafi Dafi schrieb:> else if (bitbuf == FLAG)> {
verwendet. Würde es dann so gehen das er bei dem ersten eingelesenen Bit
dieses auch mit dem ersten des Flags vergleicht. Beim zweiten
eingelesenen mit dem 2. des Falgs usw.
Müsste ich nicht hier eine Abfrage machen, die jedes Bit auf
Synchronität prüft?
wenn bitbuffer(1.Bit) == Flag(1.bit), dann Flag>>= 1, dann das nächste
eingelesene Bit auf gleichheit prüfen usw.
und wenn das bitpuffer == Flag ist dann die nächsten Bytes einfach
einlesen.
Rafi Dafi schrieb:> Es handelt sich um den Nahverkehr und die Übertragung zwischen Bus und> Ampel für eine schnellere Grünschaltung.
Ich hab mal eben Google angeworfen. Ist das eine VDV-Norm?
> Gesendet wird mit dem Datenformat 8N1.
Damit hätten wir tatsächlich die bizarre Situation, dass auf einen
bereits bitsynchronen Datenstrom noch ein Framing einer asynchronen
Übertragung draufgepackt wurde.
Bei einem echten Framing wie für eine asynchrone Übertragung "8N1"
müsste ein Startbit (immer 0) vor dem Byte und ein Stopbit (immer 1)
danach kommen, also 10 Bits. Deine Beschreibung sagt aber nur was von
einem Stopbit (Trennbit), also müsstest du das noch mal anhand deiner
beispieldaten (siehe das Oszillogramm) prüfen.
Wenn das klar ist un auch klar ist, ob das Framing im ganzen Telegramm
so aussieht, muss die Verarbeitung etwas anders aussehen.
Das angehängte Beispiel für einen bitsynchron übertragenen Datenstrom
ohne zusätzliches Framing müsstest du dann so ändern:
- Das Flag muss eventuell angepasst werden
- In der ISR werden immer 10 (evt nur 9, siehe oben) Bit eingelesen,
(RX_Bits entsprechend anpassen)
- Die Bits des Framings werden dann einfach "abgeschnitten". Das zuletzt
empfangene Stopbit wird durch einen Rechtsshift um ein Bit entfernt, das
Startbit ausmaskiert. ((bitbuf >> 1) & 0xFF)
Grüße
Stefan
Rafi Dafi schrieb:> Es handelt sich um den Nahverkehr und die Übertragung zwischen Bus und> Ampel für eine schnellere Grünschaltung.
Hm, sowas bräuchte ich manchmal auch ...
wär doch mal eine schöne Bastelei, läßt sich bestimmt auch auf "zwischen
PKW und Ampel" portieren ;-)
Stefan Wagner schrieb:> Damit hätten wir tatsächlich die bizarre Situation, dass auf einen> bereits bitsynchronen Datenstrom noch ein Framing einer asynchronen> Übertragung draufgepackt wurde.
Das versteh ich nicht ganz. Wegen des Sperrbit's wird es zu einer
asynchronen Übertragung?
Stefan Wagner schrieb:> Damit hätten wir tatsächlich die bizarre Situation, dass auf einen> bereits bitsynchronen Datenstrom noch ein Framing einer asynchronen> Übertragung draufgepackt wurde.Rafi Dafi schrieb:> Wegen des Sperrbit's wird es zu einer asynchronen Übertragung?
Ja. Eigentlich müsste da auch noch das Startbit herumgeistern.
ich vermute, dass dieses System noch zu Zeiten entworfen wurde, als
phasenkohärente FSK kein Standard war (kam in D im Datenfunk in den 80er
Jahren auf). Die damaligen (vergleichsweise einfachen) Modems hatten nur
einen Eingang bzw. Ausgang für das Datensignal. Man konnte also auch mit
der Modemstrecke zwei UART verbinden. (Dass das wesentlich schlechter
funktioniert, als eine phasenkohärente FSK, steht auf einem anderen
Blatt.)
Zieht man das in Betracht, könnte deine Protokollbeschreibung
tatsächlich auf dem Output eines UART aufbauen.
Bei der heute verwendeten phasenkohärente FSK gibt das Modem den Bittakt
vor, man muss also bitsynchron übertragen. Dein Empfänger ist ein
solches Modem, daher der "seltsame Mischmasch".
Grüße
Stefan
Stefan Wagner schrieb:> Rafi Dafi schrieb:>> Wegen des Sperrbit's wird es zu einer asynchronen Übertragung?>> Ja. Eigentlich müsste da auch noch das Startbit herumgeistern.
Das einzige Startbit ist das LSB-bit des Low-Byte's im Flag. Also die 1
in 0xFC01.
Das hatte ich nicht erwähnt da es ja sogesagt zum Flag gehört und dann
wäre es ja noch irreführender.
Rafi Dafi schrieb:> Das einzige Startbit ist das LSB-bit des Low-Byte's im Flag. Also die 1> in 0xFC01.
Beim asynchronen Framing ist das Startbit aber immer 0, das Stopbit (und
der Ruhepegel der Strecke) immer 1. Ein 1-Bit kann also kein Startbit
eines asynchronen Frames (Zeichens) sein. In der Beschreibung passt also
etwas nicht.
Und es erscheint mir extrem unwahrscheinlich, dass da etwas definiert
worden ist, das zum Zeitpunkt der Protokolldefinition nur mit extremem
Aufwand hätte implementiert werden können.
Wenn das Protokoll für eine UART-basierte Hardware entworfen wurde, ist
als Ruhezustand der Strecke eine kontinuierliche Folge von 1-Bits zu
erwarten. Die Startbedingung eines Zeichens ist der Wechsel von 1 auf 0
(das Startbit) und die Endbedingung ist der Rücksprung auf den 1-Pegel
nach (hier) 8 Datenbits.
Der "Trenner" zwischen zwei Bytes wäre also immer ein 1-Bit gefolgt von
einem 0-Bit gewesen.
Schau dir die Protokollspezifikation daraufhin noch mal an.
Grüße
Stefan
Ok, dann musst du die ungenutzten Trennbits halt "zu Fuß" herausnehmen.
Lies jeweils ein Byte und das nachfolgende Trennbit (also 9 Bit) ein und
schiebe das Trennbit (das dann LSB in bitbuf ist) nach rechts heraus.
Grüße
Stefan
Hab einen Code geschrieben, denn ich erst morgen testen kann.
Jedoch wollte ich fragen ob ihn sich jemand angucken könnte um
eventuelle Fehler aufzudecken.
Vielen Dank.
Eine Frage:
Hast du auf dem PC einen C-Compiler zur Verfügung?
(Wenn nicht - warum nicht?)
Denn: Im Grunde sind in deinem Code nur 2 Dinge, die tatsächlich
AVR-spezifisch sind.
Da ist zum einen die Tatsache, dass die Funktion eine ISR ist, die
Interrupts also ausgelöst werden müssen.
Und zum anderen fragst du 1 Pin ab.
Das lässt sich aber auch einfach auf dem PC faken. Du gehst ganz einfach
davon aus, dass die Interrupts ausgelöst werden und ersetzt das durch
einen Funktionsaufruf aus main. Und den Eingangspin fakest du mit einem
Array, aus dem das jeweils nächste Bit kommt.
1
...
2
3
unsignedcharBits[]={0,0,
4
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
5
1,0,1,1,0,1,0,0,1,
6
1,....};
7
8
intNextBit=0;
9
10
...
11
12
// ISR(INT0_vect)
13
voidInterrupt()
14
{
15
staticuint16_tbitpuffer=0;
16
staticuint8_tbitzaehler=PUFFERBITS;
17
staticuint8_tInfBytesZaehler=INFBYTES;
18
staticuint8_ttmpBytes=0;
19
staticboolbytesync=false;
20
staticboolVorlaufFlag=false;
21
staticboolInfBytesFlag=false;
22
23
bitpuffer<<=1;
24
25
// if (PIND & (1<<PD2)) // Bei jeder fallenden Flanke des RxSync wird Pin D2 ausgelesen
26
if(Bits[NextBit++])
27
...
28
29
30
31
32
intmain()
33
{
34
while(1){
35
Interrupt();// simulierter Interrupt Aufruf
36
37
// FIFO auswerten oder woran du eben sonst erkennst, dass
38
// ein Byte vorhanden ist und dieses dann ausgeben
39
...
40
}
41
}
D.h. da eine rudimentäre Testumgebung aufzubauen, mit der man diese
Funktionalität auch ohne reale Hardware testen kann, ist kein
allzugroßer Aufwand. Dann kannst du das heute noch testen und hast den
Vorteil, dass die Debug-Umgebung auf einem PC normalerweise wesentlich
besser ist, als das was du auf dem AVR vorfindest.
Und morgen, wenn du auf die reale Hardware gehst, weißt du dann schon
mit Sicherheit, dass deine Bitauswertung und Zusammenfassung zu Bytes,
das Erkennen des Vorlaufs, etc. auf jeden Fall schon mal funktioniert.
Wenns um Algorithmen geht, die eigentlich nicht wirklich von der
AVR-Hardware abhängen, wie zb hier bei dir das Zusammenfassen von Bits
zu Bytes, dann mach ich gerne einen Test am PC, eben weil das da
einfacher zu testen ist und ich leicht eine immer gleichbleibende
Testumgebung zur Verfügung stellen kann. Inklusive eines
kontrollierbaren, reproduzierbaren Inputs in den Algorithmus. Denn:
Reproduzierbarkeit ist das A und O beim Debuggen.
>Das lässt sich aber auch einfach auf dem PC faken.
Eine etwas merkwürdige Bezeichnung.
Üblicherweise nennt sich das "stub".
http://de.wikipedia.org/wiki/Stub_%28Programmierung%29
Das ist Standard in der (professionellen) SW Entwicklung vom embedded
Systemen.
GOOGLE: stub "embedded software"
stub "embedded software" Modultest
ggf. mit Einschränkung <Seiten auf deutsch>
Gruss
Erich schrieb:>>Das lässt sich aber auch einfach auf dem PC faken.>> Eine etwas merkwürdige Bezeichnung.> Üblicherweise nennt sich das "stub".
:-)
Auch recht.
wieder was gelernt.
C-Compiler hab ich hier nicht drauf. Noch nicht. Das ändert sich aber
heute abend und dann werde ich es testen.
Danke für den Vorschlag.
Mir fällt auf Anhieb DevC++ ein. Wenn es etwas besseres bzw.
Verständlicheres als freeware gibt dann bin ich für diese Info dankbar.
MFG Rafi