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
Gast
#2829594
Meine eindeutige Antwort: JA.
Ian schrieb: > 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.
Gast
#2829603
>> 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.
Gast
#2829642
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
Gast
#2829675
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?
Autor: Fhutdhb Ufzjjuz (weinbauer) habs jetzt erst gesehen. Danke Fhutdhd, das gibt reichlich anreiz zum nachdenken.
nach rechts shiften? ich denk eher nach links, oder?
ah, ok, erst das MSB setzen ... ja, dann nach rechts shiften.
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.
Das ist doch irgendein Kassetteninterface von nem uralten Heimcomputer. Peter
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 > }
@peda: Kann sein, klingt nach Tarbell von 1978.
Peter Dannegger schrieb: > Das ist doch irgendein Kassetteninterface von nem uralten Heimcomputer. Sowas hör ich zum ersten mal.
"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?
Gast
#2829789
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 ;-)
Gast
#2829833
Hallo Leute, seht euch das hier mal an: http://en.wikipedia.org/wiki/Kansas_City_standard http://en.wikipedia.org/wiki/Audio_frequency-shift_keying Die Fragen und Beiträge des Autors sind allerdings wirklich unter aller Kajüte. Möge dieser Thread schnell zu seiner Fortbildung beitragen.
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.
Gast
#2829869
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.
Ich wollte hier keinen in die Irre führen. Demnächst werde ich meine Fragen sorgfältiger und genauer beschreiben.
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
Gast
#2829971
Habe hier nochwas gefunden. Etwas unklar ob's zum Thema passt, aber den Link wollte ich weitergeben. http://www.codeforge.com/article/141947
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 | |
2 | |
3 | |
4 | |
5 | |
main.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
P.S.: Genutzt wird ein Atmega 2560
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 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
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.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
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 | |
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
Danke Stefan, werde mich mal ransetzen und gucken wie ich das anwenden bzw. lösen kann.
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
Die Protokollspezifikation ist genauso wie beschrieben.
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 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
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.
Gast
#2868365
>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
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.
