Hallo,
Ich verwende den Mikrocontroller Atmega644p und er hat zwei USARTs
(USART0 und USART1). Ich habe eine Routine mit Interruptsfunktionen für
den Atmega 644p geschrieben, so dass der Atmega 644p Byte über USART0
empfängt und dann die empfangenen Byte wieder über USART1 sendet. Leider
funktioniert meine Interruptsroutine nicht gut. Ich bitte sie um Hilfe.
Ich weiße nicht, was schief läuft. Ich bin auf Korrekturen offen.
PS: Das Programm für das Senden der Byte (Charakter 0, 1, 2, ...)von PC
zum Atmega644p liegt im Anhang und wurde in c++ geschrieben. Das
Programm c++ habe ich getestet und er läuft einwandfrei.
Danke im Voraus.
Monkeydluffy.
Luffy Monkey schrieb:> Hi Stefan Ernst,>> was schlägst du mich vor ?
Schrittweise vorgehen.
Erstmal alles ohne Interrupt.
Dann den Empfangsinterrupt in Betrieb nehmen und das Senden an die
andere USART weiterhin konventionell erledigen.
Und erst dann den 2.ten Interrupt zum Senden dazu nehmen.
Ein hinreichend komplexes Programm in einem Zug ohne Zwischenstufen zu
schreiben, ist ein ziemlich sichere Garantie dafür, dass es nicht
funktionieren wird. Und das Problem ist dann, dass man mit haufenweise
Code dasitzt und nicht weiß, wo man mit der Fehlersuche anfangen soll,
weil der/die Fehler überall stecken kann.
Luffy Monkey schrieb:> was schlägst du mich vor ?
Ich schlage dir vor, dass du uns erklärst, was deine Absicht war, als du
diese ISR geschrieben hast. Nur dann können wir wissen, ob sie
umgeschrieben werden muss, oder einfach entfernt werden kann.
Und wenn du schon beim Erklären bist, dann erkläre auch gleich, was die
Hauptschleife eigentlich machen soll. Die ist in ihrer jetzigen Form
auch schlicht Unsinn.
Hallo nochmal.
Okay, ich habe für das Empfangen und Übertragung von Byte drei ISR
verwendet.
Der ISR(USART0_RX_vect) dient zum empfangen von Byte mit dem Puffer UDRO
über USART0.
Der ISR(USART1_UDRE_vect) dient zum Transfer der Daten von UDRO in UDR1.
Der ISR(USART1_TX_vect) dient zum komplet Transfer von Daten über
USART1.
Die Funktion usart_Transfer sendet die Daten Byteweise zu zwei
Motorsteuerungen
Die Routine der While-Schleife des Main-Programms dient zur Übertragung
von Byte zu zwei Motorsteuerungen.
Die Beide Motorsteuerung verstehen ein bestimmtes Protokoll und können
nur Daten in Form von ASCii-Zeichen übernehmen.
Beispiel ---> "#2A\r"
Bedeutung: # ----> Anfang der Anweisung
2 ----> Nummer des Motors
A ----> Befehl zu erledigen(Motor anfahren)
\r ----> Ende der Anweisung
Ich hoffe meine Informationen sind genug für euch. Ich warte auf ihre
Rückmeldung.
Danke im Voraus.
Eine Frage noch:
Hat der µC neben der UART-Splittung noch etwas anderes zu tun?
Wenn 'nein' ist mir nämlich nicht wirklich klar, was du dir von einer
Interrupt-Steuerung versprichst. Das verkompliziert insbesondere das
Senden enorm.
Irgendwie ist mir da in deinem Programm einiges nicht klar.
Da hast 3 UART Partner. Den PC und die beiden Motorsteuerungen.
Von der USART 0 benutzt du nur den Empfänger
Von der USART 1 benutzt du nur den Sender
das sind 2 Anschlüsse. Wo hängt der 3.te Gesprächspartner drann?
Hallo,
>>Irgendwie ist mir da in deinem Programm einiges nicht klar.>>Da hast 3 UART Partner. Den PC und die beiden Motorsteuerungen.>>Von der USART 0 benutzt du nur den Empfänger>>Von der USART 1 benutzt du nur den Sender>>das sind 2 Anschlüsse. Wo hängt der 3.te Gesprächspartner drann?
Es gibt kein dritter Anschluss.
Erster Anschluss: Der Mikrocontroller ist mit der seriellen Port RS232
des PCs über USART0 verbunden.
Zweiter Anschluss: Der Mikrocontroller ist mit den seriellen Port RS485
von zwei identischen Motorsteuerungen verbunden. Jede Motorsteuerung
besitzt ein Anschluss RS485.
Für die Kommunikation zwischen dem Mikrocontroller und den beiden
Motorsteuerungen habe ich ein Kabel angefertigt, so dass ein Ende des
kabels ein Anschluss RS485 besitzt und das andere Ende des Kabels hat
zwei Anschlüsse RS485. Das Ende des Kabels mit einem Anschluss RS485
wird mit dem USART1 des Mikrocontrollers verbunden. Das andere Ende des
Kabels, das zwei Anschlüsse RS485 besitzt, wird mit den beiden
Motorsteuerungen verbunden.
USART0 (RS232): Kommunikation zwischen Mikrocontroller und PC
USART1(RS485): Kommunikation zwischen Mikrocontroller und beiden
Motorsteuerungen.
Moin,
Karl Heinz Buchegger schrieb:
> Schrittweise vorgehen.> Erstmal alles ohne Interrupt.> Dann den Empfangsinterrupt in Betrieb nehmen und das Senden an die> andere USART weiterhin konventionell erledigen.> Und erst dann den 2.ten Interrupt zum Senden dazu nehmen.
Ich versuche Momentan schrittweise vorzugehen. Ich habe erstmal meine
Routine ohne Interrupte geschrieben. Aber ich komme nicht klar, wenn ich
in die while-Schleife des Main-Programms die Daten von USART0 zum USART1
übertrage.
Das main Programm lautet :
1
intmain(void)
2
{
3
4
USART_Init(UBRR_VAL);// Initializierung USART0 und USART1
5
charc;
6
while(1)
7
{
8
c=USART0_Receive();
9
USART1_Receive()=c;
10
usart_Transfer("#3sc\r");// Sendung der Fahrstrecke
11
usart_Transfer("#3A\r");// Motor anfahren
12
13
}
14
}
Ich kriege folende Fehlermeldung :
../test_ohne_interrupt.c:104: error: lvalue required as left operand of
assignment
Wie kann ich besser die Daten von USART0 zum USART1 ohne Interrupt
senden.
Danke im Voraus.
Luffy Monkey schrieb:> Das main Programm lautet :> [c]> int main (void)> {>> USART_Init(UBRR_VAL) ; // Initializierung USART0 und USART1> char c ;> while(1)> {> c = USART0_Receive();> USART1_Receive() = c ;
Schlimmer als ich dachte.
Du musst erst mal C lernen.
USART1_Transmit( c );
Hi,
> Schlimmer als ich dachte.> Du musst erst mal C lernen.> USART1_Receive() = c ;> Was soll diese Zeile machen?> Du braucht ein C-bUch. Dringend.
Sorry für meine blöde Frage. Man lernt durch Fehler. Ich habe sogar
schon die Sprache c für Anfänger gelesen und mir ist nicht aufgeffallen,
dass ich eine dumme Frage gestellt habe.
Danke für die schnelle Antwort.
Luffy Monkey schrieb:> Hi,>>>> Schlimmer als ich dachte.>> Du musst erst mal C lernen.>>>> USART1_Receive() = c ;>>> Was soll diese Zeile machen?>>> Du braucht ein C-bUch. Dringend.>>> Sorry für meine blöde Frage. Man lernt durch Fehler.
Im Prinzip: ja
In diesem konkreten Fall: nein
Der Fehler zeigt, dass dir grundlegende Kentnisse fehlen, wie
Programmiersprachen (zumindest C) grundsätzlich funktionieren.
> Ich habe sogar> schon die Sprache c für Anfänger gelesen und mir ist nicht aufgeffallen,> dass ich eine dumme Frage gestellt habe.
Das ist das eigentlich bedenkliche!
Durchlesen reicht nicht. Du musst das Buch durcharbeiten! Die Übungen
machen. Es hat keinen Sinn, den Eifelturm bauen zu wollen, wenn die
einfachsten physikalischen Prinzipien, wie die Newtonschen Gesetze,
nicht klar sind. Alles weitere, was auch noch notwendig ist um den Turm
bauen zu können, baut auf diesen Fundamenten auf. Die MÜSSEN sitzen. Im
Schlaf!
Und daher: Ja, man lernt durch seine Fehler.
Aber es gibt Fehler, die dürfen eigentlich nicht passieren. Deiner ist
von dieser Kategorie. So etwas DARF für einen Lernenden, der noch dazu
ein Lehrbuch gelesen hat, kein Problem sein. Wenn doch, dann ist da
etwas grundlegend schief gegangen und man fragt sich: was von den
absoluten Grundlagen (die mit den minimalsten Anforderungen an Können)
beherrscht er ausserdem noch nicht?
No.
Du hast an dieser Stelle keine Garantie dafür, dass du das Zeichen
welches du aus UDR0 geholt hast auch in die UDR1 reinstopfen darfst.
Bei dir funktioniert das momentan, weil die beiden UART mehr oder
weniger synchron laufen. Aber spätestens dann, wenn die beiden
unterschiedliche Baudraten haben und der µC ein paar Zeichen
zwischenspeichern muss, gibt das Probleme.
Keine Annahmen treffen, die nicht unbedingt notwendig sind!
Die Annahme hier lautet: Die UART1 ist zur Übertragung bereit.
Und diese Annahme ist durch nichts gerechtfertigt. Die Annahme muss man
auch nicht treffen:
Der Empfangsinterrupt schreibt sein Zeichen in eine FIFO und in der
Hauptschleife werden die Zeichen in der FIFO sukzessive über die UART1
ausgegeben, SOFERN die UART1 zur Ausgabe bereit ist.
Das Programm hat in der Hauptschleife sowieso nichts zu tun. Da kann es
genausogut in der FIFO nachsehen, ob vielleicht ein oder mehrere Zeichen
zur Ausgabe bereit sind, ob die UART1 zur Ausgabe bereit ist und wenn
beides der Fall ist, wird dann 1 Zeichen über die UART1 ausgebeben. Und
im nächsten Durchlauf durch die Hauptschleife das nächste usw. usw. bis
die FIFO abgearbeitet wurde und wieder leer ist.
Luffy Monkey schrieb:> Hallo Karl Heinz Buchegger,>> ich habe vesucht, deine Anweisung zu befolgen
Du hast es aber nicht gemacht.
1
ISR(USART0_RX_vect)
2
{
3
chardata;
4
data=UDR0;// Byte lesen
5
6
if(counter<usart_buffer_size)
7
{
8
usart0_rx_buffer[counter]=data;
9
10
11
// USART1 zur Ausgabe in Bereitschaft
12
while(!(UCSR1A&(1<<UDRE1)));
13
USART1_Transmit(usart0_rx_buffer[counter]);
14
counter++;
15
}
16
}
genau das willst du nämlich nicht machen!
Du willst nicht in der ISR für Empfang darauf warten, dass die andere
UART zum Senden frei wird! Genau darum geht es. Die beiden sollen
unabhängig voneinander sein.
Ich skizziere mal
1
ISR(USART0_RX_vect)
2
{
3
chardata;
4
data=UDR0;// Byte lesen
5
6
dataindenPufferstellen
7
}
8
9
10
....
11
12
13
intmain()
14
{
15
....
16
17
18
while(1)
19
{
20
21
if(ZeichensindimPuffer&&
22
UCSR1A&(1<<UDRE1))// die UART1 kann ein Zeichen ausgeben
23
{
24
USART1_Transmit(dasZeichenausdemPuffer);
25
}
26
}
27
}
Das Senden erfolgt NICHT mittels Interrupt (zumindest jetzt noch nicht).
Nur so ist sichergestellt, dass von der UART0 Zeichen kommen können (bis
der Puffer voll ist) selbst dann, wenn die UART1 nicht bereit ist. Die
ISR stellt sie einfach in den Puffer. Mehr nicht.
Und in der Hauptschleife wird der Puffer sukzessive abgearbeitet.
Zeichen für Zeichen. Solange bis er wieder leer ist.
> ISR(USART0_RX_vect)> {> char data;> data = UDR0; // Byte lesen> UDR1 = data; // Byte schreiben> }
Das sendet ja schon wieder das Zeichen sofort ohne Rücksicht auf
Verluste.
Ich gebs auf.
Programmieren durch "vorhandenen fremden Code solange zusammenwürfeln,
bis da irgendwas rauskommt" funktioniert nun mal nicht.
Moin Karl Heinz Buchegger,
> Ich gebs auf.
Bitte, gebe nicht auf. Ich habe der Wille, um zu verstehen, was ich
falsch mache. Glaubt mir, ich bemühe mich, um deine Anweisungen zu
befolgen. Aber ich enttäusche dich jedesmal mit schlechter Antwort.
Sorry.
> ISR(USART0_RX_vect)> {> char data;> data = UDR0; // Byte lesen> UDR1 = data; // Byte schreiben> }> Das sendet ja schon wieder das Zeichen sofort ohne Rücksicht auf> Verluste.
Du meinst hier bestimmt der Datenverlust !!!
Wie kann ich die Verluste vermeiden ? ich bin verwirrt und möchte ganz
herzlich vorankommen.
Was du möchtest, nennt sich Ring-Puffer oder abstrakter: Queue oder
Warteschlange.
Das heisst es gibt eine Stelle an der sich neue Zeichen anreihen um aufs
gesendet werden warten, und eine stelle an der Zeichen abgeholt werden
um gesendet zu werden.
pseudocode:
1
#define BUF_LEN 64
2
shortreadpos=0;
3
shortwritepos=0;
4
5
charbuffer[BUF_LEN];
6
7
onRead(){
8
charc=UDR0;
9
10
if(readytowrite){
11
UDR1=c;
12
}else{
13
buffer[writepos]=c;
14
writepos++;
15
if(writepos==BUF_LEN)
16
writepos=0;
17
}
18
}
19
20
onWriteReady(){
21
if(readpos!=writepos){//es gibt etwas zu schreiben
22
UDR1=buffer[readpos];
23
readpos++;
24
if(readpos==BUF_LEN)
25
readpos=0;
26
}
27
}
Ich behandle hier nicht den Fall wenn der Ringpuffer überläuft, also
wenn die writepos die readpos überholt.
Karl Heinz Buchegger schrieb:> Nur so ist sichergestellt, dass von der UART0 Zeichen kommen können (bis> der Puffer voll ist) selbst dann, wenn die UART1 nicht bereit ist. Die> ISR stellt sie einfach in den Puffer. Mehr nicht.> Und in der Hauptschleife wird der Puffer sukzessive abgearbeitet.> Zeichen für Zeichen. Solange bis er wieder leer ist.
Muss man gar nicht in der Hauptschleife machen, sondern:
ISR(USART0_RX_vect)
schreibt das von UART0 empfangene Zeichen in einen Ringbuffer
ISR(USART1_TXCIE_vect)
liest das Zeichen aus dem Ringbuffer und schreibt es in den UART1,
denn hier ist garantiert, dass der UART1 zum Senden frei ist.
Damit tauschen sich beide ISRs über einen gemeinsamen Ringbuffer aus.
Die Hauptschleife kann sich derweil um andere Dinge kümmern, z.B. ein
paar LEDs effektvoll blinken lassen oder was weiß ich ;-)
Hallo nochmal,
Danke Frank und Florian für eure Rückmeldungen.
Ziel: Übertragung der empfangenen Daten von USART0 zum USART1 mit
Verwendung von Empfangsinterrupt ISR(USART0_RX_vect).
Monkeydluffy schrieb:
> ISR(USART0_RX_vect)> {> char data;> data = UDR0; // Byte lesen> UDR1 = data; // Byte schreiben> }
Karl meinte:
> Das sendet ja schon wieder das Zeichen sofort ohne Rücksicht auf> Verluste.
Was wäre dann, wenn ich meine Routine folgendermaße umstelle:
1
ISR(USART0_RX_vect)
2
{
3
chardata;
4
data=UDR0;
5
6
if(!(UCSR1A&(1<<UDRE1)))// ready to write
7
{
8
UDR1=data;
9
}
10
}
11
12
intmain(void)
13
{
14
USART_Init(UBRR_VAL);// Initializierung USART0 und USART1
15
sei();
16
charc;
17
while(1)
18
{
19
c=USART1_Receive();
20
if((UCSR1A&(1<<RXC1))&&
21
(UCSR1A&(1<<UDRE1)))// die UART1 kann ein Zeichen ausgeben
nein, schau dir nochmal den beispielcode an den ich geschrieben hab und
versuche ihn zu verstehen.
in der ISR:
was passiert mit data wenn nicht ready to write ist? es wird einfach
verworfen -> datenverlust.
in main:
das gleiche, wenn nicht ready to write ist, wird das zeichen
verlorengehen.
Frank M. schrieb:> Muss man gar nicht in der Hauptschleife machen, sondern:
...
> ISR(USART1_TXCIE_vect)> liest das Zeichen aus dem Ringbuffer und schreibt es in den UART1,> denn hier ist garantiert, dass der UART1 zum Senden frei ist.>> Damit tauschen sich beide ISRs über einen gemeinsamen Ringbuffer aus.
Die Interrupt Steuerung, die er dafür braucht, ist noch viel zu
kompliziert für ihn. Daher hätte ich ihn die Ausgabe in der
Hauptschleife machen lassen. Das kostet auch in der Hauptschleife nicht
viel und ist für ihn noch handhabbar.
(Mit dem TXCIE Vektor wirds unangenehm, weil der ja nicht immer kommt,
bzw. weil da erste Zeichen ja konventionell auf den Weg gebracht werden
muss. Sagt ja keine, dass bei einem Transmit Complete schon das nächste
Zeichen zum Senden bereit steht.)
> > Ich gebs auf.> Bitte, gebe nicht auf.
Doch tu ich. Die einzige Möglichkeit dir noch weiter zu helfen ist es,
dir den Code zu schreiben. Und das will ich nicht.
Moin ,
>>Karl Heinz Buchegger schrieb:>Doch tu ich. Die einzige Möglichkeit dir noch weiter zu helfen ist es,>dir den Code zu schreiben. Und das will ich nicht.
Ich weiße nicht mehr, was ich dir sagen kann, um dich meine Bemühungen
zu beweisen. Aber ich gebe nicht auf und bin bereit meine Schwäche zu
beseitigen.
Ich habe was gemacht, aber es läuft nicht. Irgendwie habe ich wieder
etwas nicht berücksichtgt. Kann jemand mir darüber was sagen.
Ich bitte um eure Hilfe.
Danke im Voraus.
Der code lautet:
1
charbuffer[buffer_size];
2
uint8_twritepos=0;
3
uint8_treadpos=0;
4
5
ISR(USART0_RX_vect)
6
{
7
chardata;
8
data=UDR0;// read Byte
9
10
if(!(UCSR1A&(1<<UDRE1)))// ready to write
11
{
12
UDR1=data;// write data
13
}
14
else// if not ready to write
15
{
16
if(writepos<buffer_size)
17
buffer[writepos]=data;// write into circular buffer
18
writepos++;
19
if(writepos==buffer_size)
20
writepos=0;
21
}
22
}
23
24
intmain(void)
25
26
{
27
28
29
USART_Init(UBRR_VAL);// Initializierung USART0 und USART1
30
sei();
31
32
33
34
while(1)
35
36
{
37
charc;
38
c=USART1_Receive();
39
40
if((UCSR1A&(1<<RXC1))&&
41
(UCSR1A&(1<<UDRE1)))// die UART1 kann ein Zeichen ausgeben
Hier sendest Du aus der ISR raus (wo Dir Karl Heinz schon seit
Ewigkeiten vorbetet, dass Du bei auch nur bei knapp unterschiedlichen
Empfangs- und Sende-Geschwindigkeiten sofort ein (Überlauf-)Problem
bekommst)....
Und hier sendest Du nochmal aus der main-Funktion raus:
>
1
>intmain(void)
2
>{
3
>...
4
>USART1_Transmit(c);
5
>
Diesen Faux-Pas hast Du Dir jetzt schon 3 mal geleistet durch mehrfaches
Zeigen Deines Codes - seitdem Dir Karl Heinz gesagt hast, Du sollst das
Senden aus der ISR tunlichst unterlassen.
Was soll man also mit Dir machen? Karl Heinz hat Dir mehrfach
Alternativen vorgestellt. Statt sie zu nutzen, hältst Du an dem Senden
aus der ISR fest.
>> Hier sendest Du aus der ISR raus (wo Dir Karl Heinz schon seit> Ewigkeiten vorbetet, dass Du bei auch nur bei knapp unterschiedlichen> Empfangs- und Sende-Geschwindigkeiten sofort ein (Überlauf-)Problem> bekommst)....
Ich glaub er versteht gar nicht, dass die reine Zuweisung an das UDR
Register das Senden auslöst.
Das andere Problem besteht darin, dass er keine vernünftigen FIFO
Routinen hat.
Karl Heinz Buchegger schrieb:> Ich glaub er versteht gar nicht, dass die reine Zuweisung an das UDR> Register das Senden auslöst.
Ja, er versteht das wohl als Umsetzung Deiner "Skizze" (s.o):
1
ISR(USART0_RX_vect)
2
{
3
chardata;
4
data=UDR0;// Byte lesen
5
6
dataindenPufferstellen
7
}
"Puffer" ist für Ihn wohl UDR1 ;-)
> Das andere Problem besteht darin, dass er keine vernünftigen FIFO> Routinen hat.
Doch, er hat ein FIFO mit der Länge 1 ;-)))
"Vernünftig" ist da jedoch was anderes...
Hallo,
>> Frank M. schrieb:>Was soll man also mit Dir machen? Karl Heinz hat Dir mehrfach>Alternativen vorgestellt. Statt sie zu nutzen, hältst Du an dem Senden>aus der ISR fest.
Danke schön für deine Mitteilung. Ich glaube, ich habe endlich
verstanden, was ich falsch mache.
>> Karl Heinz Buchegger schrieb:>Ich glaub er versteht gar nicht, dass die reine Zuweisung an das UDR>Register das Senden auslöst.
Ganz genau, ich wusste das nicht und ich habe trotz eurer Erklärungen
dieser Fehler nicht korrigiert. Ich verstehe jetzt, warum Karl Heinz
Buchegger aufgegeben hat. Sorry nochmal.
>> Frank M. schrieb:>Ja, er versteht das wohl als Umsetzung Deiner "Skizze" (s.o):>ISR(USART0_RX_vect)>{> char data;> data = UDR0; // Byte lesen> data in den Puffer stellen>}>"Puffer" ist für Ihn wohl UDR1 ;-)
Genau ... In meinem Kopf war UDR1 = puffer. Jetzt weiße ich, dass Karl
Heinz ein anderer puffer als Zwischenspeicher meinte.
Ich habe der Code geändernt und er sieht folgendermaße:
Luffy Monkey schrieb:> Genau ... In meinem Kopf war UDR1 = puffer. Jetzt weiße ich, dass Karl> Heinz ein anderer puffer als Zwischenspeicher meinte.
Genau.
Eine FIFO, und zwar eine richtige FIFO! Zb Ausgeführt als Ringbuffer-
Das was du da hast ist nämlich keine. Bei dir ist es nicht möglich,
wahlfrei Zeichen in die Datenstruktur reinzustellen bzw. rauszuholen.
Und zwar nicht nur streng abwechseln lesend und schreibend sondern
beliebig zwischen reinstellen und rauslesen wechselnd.
while(1)
{
UDR1 = buffer[counter1]; // write into Buffer UDR1
Du kannst doch nicht einfach so tun, als ob da irgendwelche Zeichen im
buffer sind! Da können welche sein oder auch nicht. Je nachdem, ob im
der ISR(USART0_RX_vect) welche reingestellt wurden oder nicht.
c = USART1_Receive() ;
Tu dir selbst einen Gefallen und lass den 'Rückkanal' von USART 1 erst
mal aussen vor. Du hast auch ohne dieses Detail noch massive Probleme!
> Hat zumindest jetzt mein aktueller Code ein Sinn?
Nein.
Ich weiß nicht, warum du das machen musst. Aber eigentlich müsste man
sagen: Gib die Aufgabe an jemanden ab, der wenigstens die einfachsten
Grundzüge der Programmierung beherrscht. Bei dir fehlt es an allen Ecken
und Enden (und zwar schon beginnend bei den Grundlagen). Man muss es
einfach so sehen: Programmieren ist nicht dein Ding. Das liegt dir
nicht. Ist kein Problem und ist auch keine Schande. Aber für dich ist es
eine Qual und jemand anderer hat das in 15 Minuten geschrieben.
Okay, jetzt hast Du einen Buffer, in dem Du das empfangene Zeichen in
der ISR ablegst. Schon besser.
Aber das was da in der main-Funktion steht, ist immer noch Unsinn.
UDR1 = buffer[counter1]; // write into Buffer UDR1
Hier sendest Du das gespeicherte Zeichen bereits raus! Die Zuweisung
sorgt dafür! Hast Du denn geprüft, ob der UART zum Senden schon wieder
frei ist? NEIN!
c = USART1_Receive() ;
Warum liest Du das was vom UART1??? Ich dachte Du wolltest von UART0
lesen und auf UART1 schreiben. Was ist hier c? Ich dachte, das Zeichen
steht in Deinem Buffer, den Du in der ISR gefüllt hast?
USART1_Transmit(c);
Ach, hier sendest Du. Komischerweise nicht das, was Du im Deinem Buffer
hast, sondern das, was Du vom UART1(!) plötzlich liest.
counter1++;
Dein counter wird größer und größer....
So funktioniert kein FIFO. Ein FIFO heisst "First IN, First OUT". Zudem
brauchst Du noch einen speziellen FIFO, da Dein Speicher endlich ist,
nämlich einen Ringbuffer, wo sich die Katze in den Schwanz beissen kann.
Dafür brauchst Du 2 Zählervariablen, die den Anfang und das Ende Deines
Ringbuffers speichern.
Du rotzt hier einfach auf "Gut Glück" irgendeinen Code hin, der so
überhaupt nicht funktionieren kann. Lies Dich erstmal in die Materie ein
(im Speziellen Ringbuffer), dann nimm ein Stück Papier und einen
Bleistift und versuche, das Szenario auf dem Blatt Papier
durchzuspielen. Überlege, wie Dein Buffer organisiert ist und wie/wann
Du Anfang- und Endemarkierung änderst und wann (trotzdem immer noch) ein
Buffer-Overflow auftreten kann.
So einfach ist das nicht. Du bist Lichtjahre von einer Lösung entfernt.
>> Karl Heinz Buchegger schrieb;>Man muss es einfach so sehen: Programmieren ist nicht dein Ding.Das liegt>dir nicht. Ist kein Problem und ist auch keine Schande. Aber für dich ist>es eine Qual und jemand anderer hat das in 15 Minuten geschrieben.
Ich weiße, dass meine Kenntnisse in Programmierung und Mikrocontroller
sehr schwach sind. Aber ich möchte mich unbedingt verbessern und werde
trotzdem nicht aufgeben. Trotzdem danke für deine ausfürliche
Erklärungen.
>> Frank M. schrieb:> So einfach ist das nicht. Du bist Lichtjahre von einer Lösung entfernt.
Das stimmt, ich war und bin wahrscheinlich noch Lichtjahre von einer
Lösung entfernt. Aber ich habe die Wille, um meine Aufgabe zu verstehen
und letztendlich zu lösen. Ich danke dir auch für deine Ratschläge,
Erklärungen und verlasse mich auf dich für weitere Hilfe.
Ich habe das Prinzip des Ringpuffers gelesen und habe die in meiner
Routine eingesetzt.
Die Routine lautet:
Du hast wieder einmal Code irgendwo im Internet gefunden und einfach so
kopiert.
Anders kann ich mir die beiden Zeilen ...
return fail; // Ringbuffer is empty, we read nothing from ringbuffer
...
return sucess;
... in der main-Funktion nicht erklären.
Wenn Du mittels return die main-Funktion verlässt, ist
ENDE DES PROGRAMMS!
Danach dreht sich der µC nur noch im Kreis und tut nichts mehr.
Es hat keinen Zweck. Lern erstmal C mit einem guten Buch an einem PC,
danach arbeite hier das AVR-GCC-Tutorial durch.
Komm dann in einem Jahr wieder. Nicht früher.
Luffy Monkey schrieb:> Bin ich noch entfernt von der Lösung ? Wenn ja, bitte sagen sie mir> bescheid, was ich unbedingt in meiner Routine ändern muss.
Schreib dir einige kleine Funktionen, welche
- einen Ringpuffer anlegen,
- Elemente hinzufügen,
- Elemente abholen,
- rückgeben, wie viele Plätze im Ringpuffer noch frei bzw. schon belegt
sind.
Beginn doch mal mit statischen String-Puffern und statischen Indizes.
Wenn das mal hinhaut, verwende eine struct dafür. Dann verwende diese
Library in deinem Programm.