Hallo, ich versuche einen LIN-Treiber auf Basis eines TI CC2640 zu entwickeln. Der uC kann den benötigten Frame-Break in einer Längen von <13 Bit erzeugen. Allerdings verstehe ich die Treiberdokumentation von TI noch nicht so ganz. Das entsprechende Register kann man mit der Funktion UARTBreakCtl setzen. In der Dokumentation steht aber folgende Anmerkung dabei: > For proper transmission of a break command, the break must be asserted for > at least two complete frames. Quelle: http://software-dl.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/tirtos/2_18_00_03/exports/tirtos_full_2_18_00_03/products/cc26xxware_2_23_03_17162/doc/driverlib/group__uart__api.html#ga0cb85e7658795a9656fc1065f025b1e5 Kann mir jemand vielleicht einen Tipp geben wie das zu verstehen ist? Warum reicht es nicht, dass Bit zu setzen, 13 Bits zu warten und dann wieder umschalten? Danke und viele Grüße Maximilian
Wenn du mit dem Break die Übertragung eines anderen Bytes unterbrichst, dann sieht der Empfänger erstmal nur ein ungültiges Byte, und kann erst danach den Beginn des Breaks erkennen. Bei einem korrekt arbeitenden LIN-System wird der Break nicht zur Unterbrechung von anderen Daten benutzt, sonder nur, um die Baudratenerkennung in den Empfängern auszulösen. Es genügt also die in der LIN-Spezifikation festgelegte Länge, 13 Bits.
Hmm, okay UARTBreakCtl() ist eine Funktion aus dem UART-Treiber. Ganz toll, kommt man an die Register von dem Controller nicht ran? Setze lieber die Baud-Rate runter und sende ein einzelnes Null-Byte für den Break.
Hallo, Danke für eure Rückmeldungen. Clemens L. schrieb: > Es genügt also die in der LIN-Spezifikation festgelegte Länge, 13 Bits. Wobei es ja heißt, man muss mindestens 13 Bits zum aufwecken der Slaves einen Break senden. Wenn es also zwei Frames sind, ist es auch nicht weiter tragisch. Bist du dir mit der Baudratenerkennung sicher? Dachte die ist sowieso im LDF festgelegt? Rudolph R. schrieb: > Ganz toll, kommt man an die Register von dem Controller nicht ran? Doch, die Fkt macht nichts anderes. Siehe Zeile 700 hier: http://software-dl.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/tirtos/2_18_00_03/exports/tirtos_full_2_18_00_03/products/cc26xxware_2_23_03_17162/doc/driverlib/uart_8h_source.html#l00700 HWREG() ist ein Makro zum ansprechen vom Register. Aber ich verstehe eben nicht, was mit der Anmerkung gemeint sein soll. Wenn ich da Bit setze ist der Bus doch sowieso auf low?? Rudolph R. schrieb: > Setze lieber die Baud-Rate runter und sende ein einzelnes Null-Byte für > den Break. Daran hatte ich auch schon gedacht, würde jedoch lieber den "offiziellen" Weg gehen. Sollte das nicht klappen, mache ich es über die Baudrate.
Maximilian H. schrieb: > Daran hatte ich auch schon gedacht, würde jedoch lieber den > "offiziellen" Weg gehen. Nun ja, da steht nichts von LIN, das ist ein UART-Treiber, mehr nicht. Meinen die mit Break überhaupt das gleiche?
Maximilian H. schrieb: > Bist du dir mit der Baudratenerkennung sicher? Dachte die ist sowieso im > LDF festgelegt? LIN ist für billige Slaves ohne Quarz-Oszillator ausgelegt; wenn der UART mit 9600 baud ± 20 % läuft, dann würde man ohne das Sync-Feld nichts empfangen können.
Rudolph schrieb: > Nun ja, da steht nichts von LIN, das ist ein UART-Treiber, mehr nicht. Wenn für LIN-Master nur ein UART zur Verfügung steht, gibt es zwei Möglichkeiten: für den Sync Break den Pin auf GPIO Output Low umschalten, oder temporär die Baudrate runtersetzen. > Meinen die mit Break überhaupt das gleiche? Vermutlich nicht. Im Zusammenhang mit UART meint Break einen bewusst generierten Frame Error, um die gegnerische Übertragung zu stoppen. Die genaue Länge ist egal, Hauptsache das Stopbit ist low (was in einem normalen UART-Frame unzulässig ist). Bei LIN bedeutet Sync Break quasi das Startbit der kompletten Botschaft. Ein LIN-Frame beginnt mit einer überlangen Low-Periode, gefolgt von einem Rechtecksignal mit der halben Bitrate. Letzteres kann man durch Senden von 0x55 (oder war es 0xAA?) simulieren, ersteres halt nur durch Tricksen. Bei einem LIN Slave reicht es, auf ein Byte mit Frame Error gefolgt von einem weiteren mit dem Inhalt 0x55 (0xAA?) zu warten. Zum Bestehen des Conformance Test muss die Länge des Sync Break bewertet werden, in der Praxis ist das aber egal.
soul e. schrieb: > Wenn für LIN-Master nur ein UART zur Verfügung steht, gibt es zwei > Möglichkeiten: für den Sync Break den Pin auf GPIO Output Low > umschalten, oder temporär die Baudrate runtersetzen. Dritte Möglichkeit: dem UART sagen, er soll einen Break senden. Ich kenne keinen, bei dem das nicht möglich wäre (auch wenn es im einfachsten Fall das Äquivalent eines GPIOs ist, wie hier). >> Meinen die mit Break überhaupt das gleiche? > > Vermutlich nicht. In beiden Fällen ist es ein überlanger Space-Zustand. > Zum Bestehen des Conformance Test muss die Länge des Sync Break bewertet > werden, in der Praxis ist das aber egal. Wie schon erwähnt: in der Praxis wissen viele Slaves nicht, wie schnell (relativ zum Master) sie sind.
Das Sync-Byte nach dem break ist 0x55. Ich dachte eigentlich, das ist zur Synchronisierung zwischen Slave und Master da. Der Break ist doch nur zum Aufwecken da oder? soul e. schrieb: > Die genaue Länge ist egal, Kann ich bestätigen. Habe die Kommunikation schon mal mit einem Arduino und der Software UART aufgebaut. Dort hatte ich einen Fehler in der Zeitberechnung und obwohl der Break viel zu lang war, hat der Slave geantwortet. Clemens L. schrieb: > Dritte Möglichkeit: dem UART sagen, er soll einen Break senden. Ich > kenne keinen, bei dem das nicht möglich wäre Genau das will ich doch, versteh aber nicht ganz wie das zu Bewerkstelligen ist. Siehe Eröffnungspost von mir. Gruß Maximilian
Maximilian H. schrieb: > Clemens L. schrieb: >> dem UART sagen, er soll einen Break senden. > > Genau das will ich doch, versteh aber nicht ganz wie das zu > Bewerkstelligen ist. Bit setzen, mindestens 13 Bit-Times warten, Bit löschen.
Clemens L. schrieb: > Bit setzen, mindestens 13 Bit-Times warten, Bit löschen. Genau das funktioniert eben nicht. Auch nicht wie in dem Note vom Treiber geschrieben, zwei Bytes zu senden. Oder mache ich da was grundsätzlich falsch? Bei unten genanntem Code hängt der uC bei UART_write.
1 | |
2 | while (1) { |
3 | HWREG(UART0_BASE + UART_O_LCRH) = |
4 | (true ? |
5 | (HWREG(UART0_BASE + UART_O_LCRH) | UART_LCRH_BRK) : |
6 | (HWREG(UART0_BASE + UART_O_LCRH) & ~(UART_LCRH_BRK))); |
7 | |
8 | |
9 | GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON); |
10 | UART_write(uart, &Break, 1); |
11 | UART_write(uart, &Break, 1); |
12 | HWREG(UART0_BASE + UART_O_LCRH) = |
13 | (false ? |
14 | (HWREG(UART0_BASE + UART_O_LCRH) | UART_LCRH_BRK) : |
15 | (HWREG(UART0_BASE + UART_O_LCRH) & ~(UART_LCRH_BRK))); |
16 | |
17 | |
18 | Task_sleep(1000 * (1000 / Clock_tickPeriod)); |
19 | GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_OFF); |
20 | }
|
Maximilian H. schrieb: > Genau das funktioniert eben nicht. Vielen Dank für die ausführliche Fehlerbeschreibung. (Du hast wahrscheinlich kein Oszilloskop oder LA?) Zeig doch mal, wie du 13 Bit-Times lang wartest. > Auch nicht wie in dem Note vom Treiber geschrieben, zwei Bytes zu senden. Er verlangt nicht von dir, zwei Bytes zu senden, sondern so lange zu warten, wie zwei Frames brauchen würden. Und wartet UART_write() auch wirklich, bis das Byte komplett gesendet wurde? Gibt es da nicht etwa einen Sendepuffer?
Clemens L. schrieb: > Vielen Dank für die ausführliche Fehlerbeschreibung. (Du hast > wahrscheinlich kein Oszilloskop oder LA?) Oszi habe ich und hab damit auch auf den UART geschaut. Leider ein altes, also keine LA. Hab mir mal zwar einen mit nem Arduino gebaut, funktioniert aber nicht so recht weil der Speicher kaum ausreicht. Wenn ich das Bit über die JTAG-Schnittstelle manuell setze geht der Bus auf Null. Auch das setzen im Code funktioniert -> Der UART TX Pin geht auf Null. Alles andere funktioniert dann irgendwie nicht mehr... Deswegen habe ich mir auch die LEDs mit
1 | GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON); |
ein und wieder ausschalten lassen. Die LED bleibt an, deswegen vermute ich, bleibt der uC "dazwischen" hängen. Warten habe ich schon versucht mit:
1 | Task_sleep( 760 / Clock_tickPeriod); |
Ich hab auch mal im TI-Forum gefragt, aber da weiß bisher auch nicht so genau, wie die note beim Treiber zu verstehen ist. Clemens L. schrieb: > Und wartet UART_write() auch wirklich, bis das Byte komplett gesendet > wurde? Gibt es da nicht etwa einen Sendepuffer? Weiß ich nicht - schau ich mir mal an. Clemens L. schrieb: > Er verlangt nicht von dir, zwei Bytes zu senden, sondern so lange zu > warten, wie zwei Frames brauchen würden. Ich weiß nicht, ich finde das kommt darauf an, wie man asserted übersetzt... Aber ich bin nicht so der Englisch Profi ;-)
Maximilian H. schrieb: > Das Sync-Byte nach dem break ist 0x55. Ich dachte eigentlich, das ist > zur Synchronisierung zwischen Slave und Master da. Ist es ja auch, der Slave kann die Bit-Zeiten messen und bei Bedarf die Baudrate anpassen. Da ich LIN-Slaves nicht in größeren Stückzahlen baue spare ich mir das und hänge da lieber einen Quarz oder Resonator an den Controller. > Der Break ist doch nur zum Aufwecken da oder? Nein, um den Start des Frames zu markieren. Geweckt wird über den Transceiver mit dessen Inibit-Ausgang indem die Spannungs-Versorgung eingeschaltet wird. Wenn ein LIN-Slave ordentlich schläft ist der Controller aus. Um das Break als solches erkennen zu können dürfte der Controller bestenfalls ein wenig schlummern.
Maximilian H. schrieb: > Oszi habe ich und hab damit auch auf den UART geschaut. Leider ein > altes, also keine LA. Hab mir mal zwar einen mit nem Arduino gebaut, > funktioniert aber nicht so recht weil der Speicher kaum ausreicht. Dann sei nich tdumm und hol dir so ein kleines USB-Teilchen wie das hier: ebay #181767474651 Das langt für einfache UART/SPI/I2C Geschichten vollkommen und erspart Dir Stunden und Tage fruchtlosen Suchens. > Ich weiß nicht, ich finde das kommt darauf an, wie man asserted > übersetzt... Aber ich bin nicht so der Englisch Profi ;-) Dann werde es. Im Beruf wirst Du es brauchen. fchk PS: Hast Du überhaupt die LIN-Primärspezifikationen vorliegen? Wenn nicht: Google nach
1 | "LIN specification package" filetype:pdf |
und bediene dich.
Frank K. schrieb: > Dann sei nich tdumm und hol dir so ein kleines USB-Teilchen wie das > hier: > > ebay #181767474651 Hab ich gemacht. Frank K. schrieb: > Dann werde es. Im Beruf wirst Du es brauchen. Bei dem was ich beruflich vorhabe nicht ;-) Aber natürlich hast du recht, hab ich auch festgestellt in meinen 4 Jahren im Job. Ich bin mir dennoch nicht ganz sicher, was mit dem asserted gemeint ist. Den Break will er dennoch ums verrecken nicht senden... Egal ob ich jetzt zwei Bytes warte oder versuche, zwei Bytes zu senden. Mach ich da etwas grundsätzlich falsch?
1 | while(UARTBusy(UART0_BASE)); // wait until UART is available |
2 | |
3 | UARTIntDisable(UART0_BASE, UART_INT_TX); //Disable tx Interrupt |
4 | UARTBreakCtl(UART0_BASE, true); //set Break |
5 | Task_sleep(1050 / Clock_tickPeriod); //assert two frame times |
6 | |
7 | while(UARTBusy(UART0_BASE)); //wait until UART is available |
8 | |
9 | UARTBreakCtl(UART0_BASE, false); //unset Break |
10 | UARTIntEnable(UART0_BASE, UART_INT_TX); //enable UART Interrupt |
Hallo, da ich das mit dem Break einfach nicht hinbekommen habe, habe ich es jetzt mittels Baudratenumschaltung gelöst. Sende ich ein Nullbyte mit 13000 Baud so akzeptiert der Slave die Präambel und antwortet. Das einzige was ich jetzt nicht genau unter Kontrolle habe ist der Inter-Byte Space zwischen Break und Sync. Gruß
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.