Hallo Zusammen!
Ich bin langsam echt am verzweifeln. Ich Versuche eine LIN Kommunikation
zu realisieren. Bei dem Evalboard was ich habe ist ein Chip mit einem
ATmega168 und zusätzlichem LIN-Transceiver (ATA6624) drauf.
Nun will ich per USART Zeichen senden (0x00,0x55 und 0x28 im 8N1-Frame).
USART wird initialisiert, 0x00 soll mit halber Baudrate gesendet werden
und der Rest dann mit "normaler" Baudrate. Entsprechend dachte ich,
hätte ich mein Programm geschrieben.
Das Problem was ich jetzt habe ist, dass er weder die Geschwindigkeit
erhöht noch verringern. Außerdem wollte ich, dass nach 0x28 erstmal
nichts gesendet wird sondern nur gewartet wird. Stattdessen sendet er
die Zeichenreihenfolge wieder von vorne.
Wäre schön wenn sich jemand das Prog mal anschaut!
Danke und Gruß
der Basti
Sorry, kann nicht konkret helfen. Aber einen Hinweis zu deinem
Programmierstil:
1
i=PINB;// Zuweisung der Variable i zum Zustand des Ports B
Solche Kommentare sind überflüssig weil der Befehl so offensichtlich
ist. Sie machen das Programm nur umständlicher zu lesen, was genau das
Gegenteil vom eigentlichen Zweck ist. Wenn schon könntest du schreiben,
was die Funktion von Port B ist (LEDs angeschlossen wenn als Ausgang
benutzt, UART oder was auch immer).
Ausserdem ist der Kommentar nicht einmal korrekt, weil du den Wert von
PINB i zuweist, nicht umgekehrt.
1
if(i!=0)// Abfrage ob der Inhalt von i ungleich 0 ist
2
{
3
PORTB|=(1<<PB2);
4
PORTB&=~(1<<PB1);
5
_delay_ms(1000);
6
PORTB|=(1<<PB1);
7
PORTB&=~(1<<PB2);
8
_delay_ms(1000);
9
}
Bei solchen Blöcken ist allerdings ein kurzer Hinweis hilfreiche was der
Block tut. Dein Kommentar beschreibt wieder nur das offensichtliche, was
eh jedem Leser klar ist.
> UCSR0B |= (1<<TXEN0)|(1<<RXEN0)|(1<<TXCIE0);
Das Zulassen eines Interrupts ohne eine entsprechende Interruptroutine,
wird mit sofortigem Prozessorreset bei Auftreten des Ereignisses
bestraft.
+ alles was Jack gesagt hat
und noch etwas ausgeholt
Da steht
1
i=PINB;// Zuweisung der Variable i zum Zustand des Ports B
2
i=i&0x01;// Löschen der 7 MSB
3
if(i!=0)// Abfrage ob der Inhalt von i ungleich 0 ist
4
{
Alles, aber auch wirklich alles, was in den Kommentaren steht, steht
auch im Quelltext. -> Der Kommentar erläutert und erklärt mir NICHTS,
was ich nicht auch im Code sehen würde.
Woran ich als Leser aber interessiert bin:
Was bedeutet es denn, wenn das Bit 0 am PINB auf 1 ist? Geht dann die
Welt unter? Ist ein Schalter betätigt worden? Hat der Feuermelder
ausgelöst?
Das würde mich interessieren! ABer, leider, leider. Das steht nicht
dort. Dort steht nur dass hier eine Abfrage erfolgt ob i ungleich 0 ist.
Also die Programmzeile
if (i !=0)
etwas anders (als deutscher Satz) formuliert.
> UCSR0B |= (1<<TXEN0)|(1<<RXEN0)|(1<<TXCIE0);
^^^^^^^^^^^
Dafür sehe ich keine ISR im Quellcode
> UCSR0A&= ~(1<<U2X0); // Baudrate halbieren (9600)> UCSR0A|= (1<<U2X0); // Baudrate normal (19200)
Unschöner Kommentar. Die Funktion ist eher:
> UCSR0A &= ~(1<<U2X0); // Baudrate normal, d.h. wie Init (9600)> UCSR0A |= (1<<U2X0); // Baudrate verdoppeln (19200)
Einen solchen dynamischer Baudratenwechsel habe ich noch nicht gesehen.
Welches Terminalprogramm auf der Gegenseite benutzt du, um den Erfolg zu
kontrollieren?
> Stattdessen sendet er die Zeichenreihenfolge wieder von vorne.
Ich denke dein AVR stürzt regelmäßig ab (rebootet). Das wird an der
fehlenden ISR liegen. Du könntest eine RESET-Anzeige-LED zu Beginn von
main() einrichten oder eine Statusmeldung auf UART, die dir das anzeigt!
Hallo Zusammen,
danke für die Antworten. Also an PB0 hängt ein Taster, an PB1 und PB2
hängen jeweils LEDs. Das umschalten der Baudrate brauche ich, da beim
LIN-Bus zunächst ein Syncfield mit nominal 13 Bits "low" gesendet werden
muss.
Benutzen tue ich kein Terminalprog sondern nur ein Oszilloskop und
schaue mir das Bussignal an.
Ich dachte mit (1<<TXCIE0) erlaube ich dem USART das schalten vom TXC0
Flag das ich ja abfrage.
Gruß der Basti
Der Basti schrieb:> Ich dachte mit (1<<TXCIE0) erlaube ich dem USART das schalten vom TXC0> Flag das ich ja abfrage.
TX Transmit
C Complete
I Interrupt
E Enable
0 an der Usart 0
ALles zusammen: Wenn ein Zeichen von der UART verschickt wurde, wird ein
Interrupt ausgelöst. Zunächst wird das Transmit Complete Flag TXC0
gesetzt (das wird immer gesetzt, wenn ein Zeichen rausgegangen ist) und
wenn dann mittels sei() die Interrupts auch noch erlaubt sind, wird die
zugehörige ISR angesprungen. Die du nicht hast.
> das schalten vom TXC0> Flag das ich ja abfrage.
Du meinst das hier?
while(TXC0==0)
{}
das ist sowieso Unsinn. Wie fragt man denn ein Bit in einem Register ab,
von dem man den Bitnamen kennt?
Also soviel ist sicher, das er resetet wurde. Wenn ich das TXCIE raus
nehme, dann sendet er die Sache entsprechend mit dem delay. Die Baudrate
verändert er trotzdem nicht. Muss das anders gemacht werden mit dem
Umschalten?
Aus Datenblatt:
• Bit 6 – TXCn: USART Transmit Complete
This flag bit is set when the entire frame in the Transmit Shift
Register has been shifted
out and there are no new data currently present in the transmit buffer
(UDRn). The TXCn
Flag bit is automatically cleared when a transmit complete interrupt is
executed, or it can
be cleared by writing a one to its bit location. The TXCn Flag can
generate a Transmit
Complete interrupt (see description of the TXCIEn bit).
Dachte die Abfrage könnte ich so machen...
Der Basti schrieb:> Dachte die Abfrage könnte ich so machen...
Das ist halt die Krux, wenn man die Grundlagen überspringt.
Nochmal:
Wie frägt man ein Bit in einem Register ab, von dem man den Bitnamen
kennt?
(Du hast das doch schon gemacht: Du hast abgefragt ob Bit PB0 (das war
der Bitname) im Register PINB (das ist das Register) gesetzt ist oder
nicht)
Du hast das ein wenig umständlich gemacht
i=PINB;
i= i & 0x01;
if (i !=0)
{
aber prinizpiell war es richtig.
Die kürzere Schreibweise wäre gewesen
if( PINB & ( 1 << PB0 ) )
und das wendest du jetzt auf das Bit namens TXC0 im Register UCSR0A an!
(und dann überlegst du dir, wie du das Bit wieder auf 0 zurück kriegst.
Aufpassen: derartige Bits werden durch das Schreiben einer 1 gelöscht!
Okay das werde ich dann mal tun. Mein Laptopacku ist dann auch fast alle
und das Ladegerät ist zuhause, kann dann erst heute Abend bzw. morgen
von Erfolgserlebnissen berichten...;-)
Danke für eure Mühe!
Gruß der Basti
Der Basti schrieb:> Mahlzeit Zusammen,>> anbei der Code wie es dann funktioniert!
Glaub ich nicht
UCSR0B |= (1<<TXEN0)|(1<<RXEN0)|(1<<TXCIE0)
Du hast immer noch den Interrupt enabled ohne eine ISR dafür zu haben.
-> ständige Prozessor-resets.
Man gibt keinen Interrupt frei, für den man keinen Handler hat!