Ich habe ein Programm das empfängt über ein Terminal Zeichen vom PC. Das
wird in einen char Buffer[7] geschrieben.
Soweit so gut.
Wenn jetzt nur 3 Zeichen übertragen werden, dann bleiben 4 Plätze übrig.
Ich mach mal ein Beispiel:
1
Anzeige Terminal
2
3
1|2|3||||| Terminal sendet 123
4
1|2|3|4|5|6|| Terminal sendet 456
5
8||||||| Terminal sendet 78
Ich hab jetzt schon vieles Versucht, aber nix fruchtet. In Java würde
ich array[] = new Array() schreiben und das wäre gelöst. Wie löse ich
sowas in C?
einfach ein
> Buffer[0]= '\0';
und schon ist der String 0 byte lang. Aber damit wird der Speicher nicht
freigebenen, es wird noch die der String abgeschlossen.
mcnanuk schrieb:> Ich hab jetzt schon vieles Versucht, aber nix fruchtet. In Java würde> ich array[] = new Array() schreiben und das wäre gelöst. Wie löse ich> sowas in C?
Indem du das Array überhaupt nicht löscht, und dich daran erinnerst, das
in C ein String dort aufhört, wo das '\0' Zeichen ist.
http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F
hast du also in C ein Array
char Buffer[200];
und willst du ausdrücken, dass dort drinnen ein String mit 0 Zeichen
Länge beheimatet ist, dann platzierst du das \0 Zeichen so, dass sich
ein String mit 0 Zeichen Länge ergibt
Buffer[0] = '\0';
Das funktioniert nicht.
Wenn ich diese zeile in die IfElse Abfrage oder danach setze, dann wird
nix im LCD geschrieben und die Abfrage landet immer bei "Kleiner 100"
mcnanuk schrieb:> Das funktioniert nicht.
Doch, das funktioniert.
Siehe deinen Originalthread.
Dein Problem ist, dass du ein massives Verständnisproblem bei ganz
anderen Dingen hast.
mcnanuk schrieb:> Wenn ich diese zeile in die IfElse Abfrage oder danach setze, dann wird> nix im LCD geschrieben und die Abfrage landet immer bei "Kleiner 100"
Du hast den Quellcode vergessen. ;-)
Wo kommt eigentlich lcd_puts() her?
Reagieren deine LCD-Funktionen wirklich auf \n?
Karl heinz Buchegger schrieb:> Siehe deinen Originalthread.
Wie? Habe ich mal wieder was verpasst?
Karl heinz Buchegger schrieb:> Doch, das funktioniert.> Siehe deinen Originalthread.>> Dein Problem ist, dass du ein massives Verständnisproblem bei ganz> anderen Dingen hast.
Das will ich nicht bestreiten, wobei ich meine es so in etwa zu
verstehen. Nur wie soll man lernen, wenn man nicht anhand von Beispielen
sich voranhangelt.
ich verstehe auch was bei Buffer[0] = '\0'; passiert.
Die verständnisfragen werden immer weniger, wenn auch noch genug übrig
sind. Wobei ich mir eigentlich recht sicher bin, bei dem was ich da
fabriziert habe.
Nur hier an der Stelle sehe ich absolut keine Lösung. Direkt nach dem
Einschalten des Boards klappt ja auch alles einwadnfrei. Eben aber nur
beim ersten Mal, danach fehlt besagter reset.
Karl heinz Buchegger schrieb:> Link zu schrieb:>>> Siehe deinen Originalthread.>> Wie? Habe ich mal wieder was verpasst?> Beitrag "Atmega644 UART - Komische Ausgabe"
Ach so.
Reagiert die Fleury-Lib wirklich auf '\n' wie man so erwarten würde?
In der Online-Doku finde ich nichts dazu...
Link zu schrieb:> Reagiert die Fleury-Lib wirklich auf '\n' wie man so erwarten würde?> In der Online-Doku finde ich nichts dazu...
Sein Problem ist erst mal nicht das LCD an sich, sondern das
Verständnis, dass über die UART erst mal nur einzelne Zeichen
eintrudeln, die er zu einem String zusammensetzen muss, ehe er dann
irgendetwas sinnvolles damit anstellen kann.
Es wäre schon viel gewonnen, wenn er sich endlich einmal mit sich selbst
einigen könnte, wie er nun die UART bedienen will.
Mit eigenem Code oder mit der Fleury Library.
mcnanuk schrieb:> Nur hier an der Stelle sehe ich absolut keine Lösung. Direkt nach dem> Einschalten des Boards klappt ja auch alles einwadnfrei. Eben aber nur> beim ersten Mal, danach fehlt besagter reset.
Dann frag dich doch mal, woher deine Add Funktion, genauer gesagt die
Variable LastCharInBuffer, wissen soll, dass es jetzt wieder von vorne
im Buffer losgeht.
Im übrigen:
Von deinem Code schwirren mitlerweile mindestens 3 grundverschiedene
Versionen durchs Forum. Kein Mensch weiß mitlerweile mehr, wie dein Code
zur Zeit in seiner vollen Pracht aussieht, ob du die Fleury Lib noch
benutzt, etc.
Es ist schwierig, auf Fehler im Code hinzuweisen, bzw. auf
Verständnisprobleme einzugehen, wenn der zugrundeliegende Code nicht
bekannt ist.
Das sollte dir einen kleinen Denkanstoss geben.
Ich danke Euch.... ich habe extra einen neuen post aufgemacht, da der
alte Thread doch schon sehr gewachsen war.
Ich glaube geschrieben zu haben, dass ich verstanden habe wie Uart Daten
sendet. Zuerst hat es mich irritiert, aber als ich wusste, das es Ascii
ist, war es mir klar.
Ich verwende im Moment die Libary von Fleury, da mein eigener Ansatz
zwar an sich funktioniert, aber eben dort ein Fehler steckt, den ich
nicht finde.
Aber lassen wir das mal weg.
Dein Einwand mit der Add Funktion ist natürlich absolut berechtigt, und
ist mir absolut nicht aufgefallen. Wie eigentlich immer wenn man
Stundenlang davor sitzt.
Ich entschuldige mich mal für die Verwirrung die ich gestiftet habe,
obwohl ich mich eigentlich bemüht habe immer übersichtlich zu posten.
Das heisst auch das wegzulassen was weiter oben schon stand. Aber war
wohl der falsche Weg :)
Der Hund liegt tatsächlich in der Add Methode begraben. Werde mir das
jetzt mal anscheun und versuchen das Problem zu lösen.
mcnanuk schrieb:> Ich verwende im Moment die Libary von Fleury, da mein eigener Ansatz> zwar an sich funktioniert, aber eben dort ein Fehler steckt, den ich> nicht finde.> Aber lassen wir das mal weg.
Nein.
Das können wir nicht weg lassen.
Falls du es immer noch nicht begriffen hast. Hier nochmal. Diesmal in
aller Deutlichkeit:
P O S T E D E I N E N A K T U E L L E N C O D E !
U N D Z W A R K O M P L E T T !
Jetzt verstanden?
> Der Hund liegt tatsächlich in der Add Methode begraben.
Der Hund ist auch dort begraben, dass dir Stringverabreitung an sich
noch nicht klar ist. Im anderen Thread hast du einen Code gepostet, der
von der Fleury Lib weggegangen ist. Die Teile die du geklaut hast, sind
alle korrekt. Aber in den Teilen, die du dazugeschrieben hast, wimmelt
es nur so von String-Verständnisfehlern. Daher die Aufforderung: Poste
kompletten Code!
Deine Probleme lassen sich nicht an einer Stelle dingfest machen. Deine
Probleme ziehen sich über deinen ganzen Code hin.
> Nur wie soll man lernen, wenn man nicht anhand von Beispielen> sich voranhangelt.
Nein. Beispiele sind gut, um zu Lernendes zu illustrieren, aber nicht,
um sich daran entlang zu hangeln. Entlang hangeln solltest Du Dich an
den Grundlagen und die Beispiele zu deren Verdeutlichung nehmen. Sonst
landest Du bloß bei der Herumprobiererei, die wir gerade sehen.
Dann wüsstest Du, dass ein C-String an \0 endet und alles, was danach
kommt, völlig egal ist - auch wenn es vom Speicherplatz her noch zum
String-Array gehört. Wenn der erste Platz im String-Array, also
string[0], '\0' enthält, ist der String also 0 Zeichen lang.
OK.
Als erstes bauen wir da gleich mal eine Funktion, die einen String von
der UART empfängt. Als Konvention soll gelten: Die Übertragung, und
damit der String, soll dann beendet sein, wenn von der Gegenstelle ein
'\n' daherkommt.
Irgend so eine Konvention muss es geben, weil dein Programm ja nicht
wissen kann, ob die Übertragung '1' '8' schon alles war (und du 18
getippt hast) oder ob da noch was kommt (und du zb 183 getippt hast).
Die UART Library ist so aufgebaut, dass uart_getc nicht darauf wartet,
dass ein Zeichen reinkommt. Das erleichtert den Einsatz, wenn asynchron
noch andere Dinge passieren sollen. Fürs erste will ich aber genau die
Umkehrung haben: Eine Funktion, die auf ein Zeichen wartet, falls keines
vorhanden ist (die Lib speichert zwischenzeitlich eingehende Zeichen
selbst zwischen).
Fehlerbehandlung wie Frame Fehler u. dgl. lass ich erst mal weg.
1
charuart_getc_wait()
2
{
3
unsignedintc;
4
5
do{
6
c=uart_getc();
7
}while(c&UART_NO_DATA);
8
9
uart_putc((c&0x00ff));
10
11
returnc;
12
}
13
14
15
voiduart_gets(char*Buffer)
16
{
17
charc;
18
intnextCharPos=0;
19
20
c=uart_getc_wait();
21
while(c!='\n'){
22
Buffer[nextCharPos++]=c;
23
c=uart_getc_wait();
24
}
25
26
Buffer[nextCharPos]='\0';
27
}
Die Funktion uart_gets bekommt einen Buffer (ein char Array) übergeben,
in dem sie die einzelnen Zeichen ablegen soll. Auch hier wieder eine
Vereinfachung: Der Buffer muss vom Aufrufer gross genug zur Verfügung
gestellt werden! Der Code sollte hier noch geändert werden, in dem man
der Funktion die Größe des Buffers mitgibt und die Funktion in die Lage
versetzt, sich davor zu schützen ausserhalb des zulässigen Speichers zu
schreiben. Das verkompliziert allerdings den Code und lenkt von den
wesentlichen Dingen ab. Daher hab ich es erst mal weg gelassen.
Mit der Funktion uart_gets() ist es nun möglich ein Hauptprogramm zu
schreieben, welches auf einen kompletten String wartet, diesen String in
einen int umwandelt und abhängig vom Zahlenwert etwas auf dem LCD zu
machen
Ich muss allerdings sagen.
Ich habs hier im Editor direkt getippt und noch nicht durch einen
Compiler gejagt. Da mag noch der eine oder andere kleine Fehler drinnen
sein. Das Grundprinzip ist aber ok.
Was schonmal funktioniert: Das Programm reagiert auf die Eingabe im
terminal... musste da LF(\n) als Endsymbol einstellen.
Aber der buffer ist leer, und damit die Zahl 0.
Auch wird nix ans Terminal zurückgegeben.
> Aber der buffer ist leer, und damit die Zahl 0.> Auch wird nix ans Terminal zurückgegeben.
Du hattest mal ein Programm vorgezeigt, in dem sowohl eine ISR für den
UART drin war als auch eine direkte Abholung außerhalb. Da das wohl
Dein allerkleinstes Problem zu dieser Zeit war, habe ich auf einen
Kommentar verzichtet. Nun hast Du uns zwar das angeblich komplette
Programm gezeigt -- aber uart_init() war nicht dabei.
Daher: ist darin immer noch diejenige uart_init(), die RXCIE setzt und
bei der eventuell sogar noch die ISR für den Empfangsinterrupt dabei
ist?
/* enable UART receiver and transmmitter and receive complete interrupt */
19
UART0_CONTROL=_BV(RXCIE)|_BV(RXEN)|_BV(TXEN);
20
21
#elif defined (ATMEGA_USART)
22
/* Set baud rate */
23
if(baudrate&0x8000)
24
{
25
UART0_STATUS=(1<<U2X);//Enable 2x speed
26
baudrate&=~0x8000;
27
}
28
UBRRH=(unsignedchar)(baudrate>>8);
29
UBRRL=(unsignedchar)baudrate;
30
31
/* Enable USART receiver and transmitter and receive complete interrupt */
32
UART0_CONTROL=_BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
33
34
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
35
#ifdef URSEL
36
UCSRC=(1<<URSEL)|(3<<UCSZ0);
37
#else
38
UCSRC=(3<<UCSZ0);
39
#endif
40
41
#elif defined (ATMEGA_USART0 )
42
/* Set baud rate */
43
if(baudrate&0x8000)
44
{
45
UART0_STATUS=(1<<U2X0);//Enable 2x speed
46
baudrate&=~0x8000;
47
}
48
UBRR0H=(unsignedchar)(baudrate>>8);
49
UBRR0L=(unsignedchar)baudrate;
50
51
/* Enable USART receiver and transmitter and receive complete interrupt */
52
UART0_CONTROL=_BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
53
54
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
55
#ifdef URSEL0
56
UCSR0C=(1<<URSEL0)|(3<<UCSZ00);
57
#else
58
UCSR0C=(3<<UCSZ00);
59
#endif
60
61
#elif defined ( ATMEGA_UART )
62
/* set baud rate */
63
if(baudrate&0x8000)
64
{
65
UART0_STATUS=(1<<U2X);//Enable 2x speed
66
baudrate&=~0x8000;
67
}
68
UBRRHI=(unsignedchar)(baudrate>>8);
69
UBRR=(unsignedchar)baudrate;
70
71
/* Enable UART receiver and transmitter and receive complete interrupt */
72
UART0_CONTROL=_BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
73
74
#endif
75
76
}/* uart_init */
Hier meine init Methode... direkt aus der Fleury Libary...
Ich will jetzt nicht in meinem eigenen versuch kruschteln, um keine
Verwirrung, speziell bei mir hervorzurufen :)
Ja, das ist genau das, was ich meinte. Das kommt davon, wenn man sich
aus verschiedenen Quellen Beispiele zusammenstoppelt, ohne die
Grundlagen zu haben, sie zu verstehen.
Mach aus
Wiso verschiedene Quellen.... kommt doch alles aus der Hand von Herrn
Fleury...
Wie gesagt das was mein erster Anstz.... später hab ichs dann selbst
versucht. Hier in diesem thread oben der Code basiert komplett auf der
Libary. Die kommunikation klappt auch, nur mit der Verarbeitung der
empfangenen Daten habe ich Schwierigkeiten.
Aber da ich dort nicht weiterkomme, und ich seit Tagen versuche eine
Lösung zu erstellen, versuche ich es nochmals mit dem Ansatz von Karl
heinz Buchegger.
Es war aber sehr lehrreich, da ich in den letzen 2 Tagen mehr über C
gelernt habe, als in den 2 Monaten zuvor.
Nein. Karl Heinz hat Dir eine Empfangsroutine vorgeschlagen, die mit
einer Interrupt-erlaubenden Initialisierung nicht zusammenarbeitet. Da
Du aber trotz Aufforderung, den KOMPLETTEN Code zu posten, diese
Initialisierung nicht gezeigt hast, konnte er davon nichts wissen.
Es war Zufall, dass mir das ein paar Stunden vorher schon aufgefallen
war. Und es wäre Deine Verantwortung als Zusammensteller gewesen,
Konflikte mit Teilen, die Du zufügst, zu erkennen.
> Die kommunikation klappt auch
Oooch komm. Du setzt RXCIE, holst aber die Rx-Daten nicht
interruptgesteuert ab, und willst mir erzählen, dass die Kommunikation
klappt? Gut möglich, dass es trotz Wegnehmen von RXCIE immer noch nicht
klappt. Das liegt aber dann nicht daran, dass RXCIE gar kein Fehler
gewesen wäre, sondern daran, dass Du noch andere solche Würmer drin hast
(was mich gar nicht wundern würde).
Wenn man anfängt zu programmieren ist es ohnehin nicht ratsam, auf eine
Unmenge an Libraries zurückzugreifen. Zuerst ist es mal wichtig, sein
eigenes Geschreibsel richtig zu verstehen.
Du hast in deinem Code Libs für LCD und Uart eingefügt. Während LCD
sicher etwas fortgeschrittener ist, ist der UART sehr einfach zu
initialisieren und konfigurieren. Wenn du dies selber machst, lernst du
auch den Umgang mit den diesbezüglichen Registern und kannst so
obgenannte Fehler ausschließen.
Auch wenn du nun zig Libraries zusammenwürfelst und das Programm am Ende
sogar noch funktioniert, hast du trotzdem keine wirkliche Ahnung was da
eingelicht abläuft.
"Learning by doing" ist absolut ok. Aber "Learning by looking other
people doing" eben nicht
Hc Zimmerer schrieb:> war. Und es wäre Deine Verantwortung als Zusammensteller gewesen,> Konflikte mit Teilen, die Du zufügst, zu erkennen.
Moment.
Ich geh davon aus, dass die Fleury Lib unverändert benutzt wird.
Und soweit ich mich erinnern kann, klappt die auch problemlos
interruptgesteuert.
> Oooch komm. Du setzt RXCIE, holst aber die Rx-Daten nicht> interruptgesteuert ab
Wovon sprichst du?
DIe Fleury Funktionen enthalten die ISR. Von der ISR werden die Daten in
einen Ringbuffer gestellt, von wo sie wiederrum uart_getc abholt.
Wenn ich den gesamten Code gepostet hätte, dann hätte ich hier mehr als
2000 Zeilen Code gepostet.
Nunja es liegt mir sehr fern mich hier zu streiten, auch kann ich nicht
für alles geradestehen, was in meinem Code stand. Ich bin nunmal noch
kein Spezialist im µC Bereich und in der C Welt.
Ich habe einige Jahre Java, Phython, Scheme, ... Erfahrung. In die
Embedded Welt stürzte ich mich erst seit kurzem. Ich finde das alles
sehr Spannend, und bin denjenigen sehr Dankbar, die sich die Zeit
nehmen, mich auf meine Fehler hinzuweisen und mir Tipps geben.
C-Bücher habe ich hier liegen, aber bringen mich nur bedingt weiter.
Heute und gestern bin ich an meine Grenzen gestoßen, was die logik
hinter C angeht. Aber aus Fehlern lernt man.
Jedenfalls back on Topic:
Ich hab den Fehler gefunden im Code von Karl Heinz:
Aber wie ich sehe, hat er es schon reineditiert... :)
Naja wenigstens weiss ich worauf zu achten ist :)
mcnanuk schrieb:> Was schonmal funktioniert: Das Programm reagiert auf die Eingabe im> terminal... musste da LF(\n) als Endsymbol einstellen.>> Aber der buffer ist leer, und damit die Zahl 0.
OK.
> Auch wird nix ans Terminal zurückgegeben.
Den sntsprechenden putc hab ich nachträglich noch ergänzt.
1
charuart_getc_wait()
2
{
3
unsignedintc;
4
5
do{
6
c=uart_getc();
7
}while(c&UART_NO_DATA);
8
9
uart_putc((c&0x00ff));
10
11
returnc;
12
}
Zum ersten Problem:
Ich hatte tatsächlich nach dem Absenden des Codes noch einen
'Problemfall', ein vergessenens ++
Hast du das so
Null Ahnung von Nichts schrieb:> "Learning by doing" ist absolut ok. Aber "Learning by looking other> people doing" eben nicht
Nunja kommt ja ganz auf die Person an, und wie sie damit umgeht.
Als ich angefangen habe UART zu nutzen, wusste ich nicht was es war. Da
kam mir die libary vom Fleury gelegen, da ich gute Erfahrungen mit der
LCD Libary gemacht hatte.
Die Uart Schnittstelle ist leider eine last Minute Anforderung, die ich
noch einbauen musste.
Aber generell arbeite ich auf, was ich so hernehme. Und das Datenblatt
liegt sowieso immer neben mir aufm Tisch.
[Karl Heinz]
> Wovon sprichst du?
Karl Heinz, da muss ich Dir Abbitte tun. Ich habe beim Drübergucken
Dein uart_getc_wait() für eine direkte Abholroutine gehalten, die
außerhalb des Interrupts arbeitet. Erst jetzt habe ich gesehen, dass Du
Fleurys Buffer-Abholroutine darin verwendest. Sorry.
Hc Zimmerer schrieb:> [Karl Heinz]>> Wovon sprichst du?>> Karl Heinz, da muss ich Dir Abbitte tun.
Kein Problem.
Solange wir das Misverständnis ausräumen können.
jep ... Danke Dir...
Die Feinheiten werde ich noch einbauen, wobei Die Schnittstelle sehr
einfach gehalten werden soll... Irgendwann muss ich sie Ausbauen, aber
momentan tut sie genau das was ich brauche.
1
#include<stdlib.h>
2
#include<avr/io.h>
3
#include<avr/interrupt.h>
4
#include<avr/signal.h>
5
#include<avr/pgmspace.h>
6
#include<util/delay.h>
7
#include<string.h>
8
#include"lcd.h"
9
#include"uart.h"
10
11
12
/* define CPU frequency in Mhz here if not defined in Makefile */
mcnanuk schrieb:> Als ich angefangen habe UART zu nutzen, wusste ich nicht was es war. Da> kam mir die libary vom Fleury gelegen, da ich gute Erfahrungen mit der> LCD Libary gemacht hatte.
Ich habe zwar die UART LIb von ihm auch noch nie irgendwo eingesetzt.
Ich schätze sie aber trotzdem, weil sie grundsätzlich delay-freies
arbeiten erlaubt. Man muss nicht zwangsweise auf ein Zeichen warten,
kann das aber leicht 'umrüsten'. Anders rum ist das nicht so einfach
möglich.
mcnanuk schrieb:> void uart_gets( char * Buffer )> {> char c;> int nextCharPos = 0;>> c = uart_getc_wait();> uart_putc(c);> while( c != '\n' ) {> Buffer[ nextCharPos++ ] = c;> c = uart_getc_wait();> uart_putc(c);>> }>> Buffer[ nextCharPos ] = '\0';> }
Normalerweise mach ich solche Sachen ungern mit Index-Variablen. Lieber
direkt mit Pointermanipulation. Dann muss man keineen Datentyp für die
Indexvariable festlegen. Reichen 8 Bit, oder sollen es doch 16 Bit sein.
Mit Pointern stellt sich die Frage nicht.
Da die Funktion allerdings sowieso noch ausgebaut werden müsste
1
voiduart_gets(char*Buffer,intBufferSize)
um der Funktion die Möglichkeit der Verhinderung eines Bufferüberlaufs
zu geben, kommt dieser Index dann sehr gelegen.
> jep ... Danke Dir...> Die Feinheiten werde ich noch einbauen, wobei Die Schnittstelle sehr> einfach gehalten werden soll...
Wer sitzt am anderen Ende?
Ein Mensch oder ein anderes Programm?
Für einen Menschen solltest du noch zumindest eine rudimentäre
Editiermöglichkeit über 'Backspace' (die große Pfeil Links Taste über
Return) einbauen. Das geht ziemlich trivial: du kriegst ein '\b' Zeichen
über die Schnittstelle und wenn du selber eines wegschickst, dann
schiebt das Terminal den Cursor ein Zeichen nach links.
Karl heinz Buchegger schrieb:> Wer sitzt am anderen Ende?> Ein Mensch oder ein anderes Programm?
Hehe die Frage ist einfach: Ich ! :)
Es soll auch nur eine Zahl eingegeben werden. 0-40 000. Das \n übernimmt
Hterm für mich :)
Aber ich werde in der Zukunft das ganze Ausbauen, und wie du sagtest es
Userproof machen.
>> Wer sitzt am anderen Ende?>> Ein Mensch oder ein anderes Programm?>> Hehe die Frage ist einfach: Ich ! :)
Nun, das ist unter Umständen keine erschöpfende Auskunft ;)