Hallo, Ich schreibe grad an meiner Studienarbeit, wo ich auf der Hardwarebasis (ATMega16) meines Vorgängers einen LIN Slaveknoten programmieren soll. Das Empfangen der Frames klappt einwandfrei. Mein Problem liegt beim Versenden eines Frames. Laut Spezifikation von LIN muss jeder Frame mit einem 13 Bitzeit-langen Syncbreak und anschliessend einem Syncfeld (0x55) beginnen. Da der ATMega16 selber kein Break-Syncfeld erzeugen kann, hab ich mich beim implementieren an einen Tipp aus dem Buch LIN-Bus von Andreas Grzemba gehalten: "Ein Standard UART kann das Synchronisationsbreak nicht direkt erzeugen. Man kann sich aber mit einem Trick behelfen. Will man beispielsweise für 19,2 KBits/s das Synchronisationsbreak erzeugen, setzt man die Baudrate auf ca. 13 KBit/s herab und sendet ein 0x00 Datenbyte. Das Senden der 8 Bits zuzüglich des Startbits dauert etwas länger als die notwendigen 677 Mikrosekungen des Synchronisationsbreaks. Anschließend wird die Baudrate wieder auf 19,2 KBit/s gesetzt und das Synchronisationsfeld gesendet." Da die Kommunikation bei mir bei 9600 Bit/s läuft, versuche ich die Baudrate auf 6500 Bit/s herunterzusetzen. Allerdings werden die verschickten Frames nicht als LIN Frames erkannt und laut Oszi ist auch das Synchronisationsbreak zu kurz. Wenn ich zum Testen die Baudrate noch weiter herabsetze, verändert sich die Dauer des Synchronisationsbreak nicht. Daher nehme ich an, dass die Umschaltung der Baudrate nicht funktioniert. Code zum Initialisieren des UART: /** * Quartfrequenz des Lin - Knoten */ #define F_CPU 8000000 // Oszillator-Frequenz in Hz (8MHz) /** * Baudrate für LIN-Kommunikation in bps festlegen */ #define UART_BAUD_RATE_NORMAL 9600 /** * Baudrate für LIN-Kommunikation in bps festlegen * fuer das Sync - Break Feld */ #define UART_BAUD_RATE_BREAKSYNC 6500 /** * Hilfsmakro zur UBRR-Berechnung fuer den ATMega16 * ("Formel" laut Datenblatt) */ #define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1) /* * setzten der Variablen mit den Werten * fuer die Baudrateneinstellung des * UARTs des ATMega16 */ l_UBRRH_Normal = (uint8_t) (UART_UBRR_CALC (UART_BAUD_RATE_NORMAL, F_CPU) >> 8); l_UBRRL_Normal = (uint8_t) UART_UBRR_CALC (UART_BAUD_RATE_NORMAL, F_CPU); l_UBRRH_SyncBreak = (uint8_t) (UART_UBRR_CALC (UART_BAUD_RATE_BREAKSYNC, F_CPU) >> 8); l_UBRRL_SyncBreak = (uint8_t) UART_UBRR_CALC (UART_BAUD_RATE_BREAKSYNC, F_CPU); setBaudNormal (); /* * Frameformat setzen */ UCSRB = (1 << TXEN); // Sender einschalten UCSRB &= ~(1 << RXCIE); // Empfaengerinterrupt ausschalten UCSRB &= ~(1 << RXEN); // Empfaenger ausschalten Code der Baudratenumschaltfunktionen: void setBaudNormal (void) { unsigned char leeren = UDR; UCSRC &= ~(1 << URSEL); UBRRH = l_UBRRH_Normal; // auf Baudrate fuer Normal stellen UBRRL = l_UBRRL_Normal; // auf Baudrate fuer Normal stellen UCSRC |= (1 << URSEL) | (3 << UCSZ0); // Asynchron 8 Bit mit 1 Stoppbit leeren = UDR; } void setBaudSyncBreak (void) { unsigned char leeren = UDR; UCSRC &= ~(1 << URSEL); UBRRH = l_UBRRH_SyncBreak; // auf Baudrate fuer SyncBreak stellen UBRRL = l_UBRRL_SyncBreak; // auf Baudrate fuer SyncBreak stellen UCSRC |= (1 << URSEL) | (3 << UCSZ0); // Asynchron 8 Bit mit 1 Stoppbit leeren = UDR; }
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.