Servus Leute,
ich hab ein paar kleinere Problem mit C auf meinem Atmega16...
Und zwar will ich vom Uart rechnerseitig einen Befehl reinschicken und
damit meinen Datenstring abhohlen (digitale Zustände und Analogwerte),
doch irgendwie hauts nicht so hin wie ich will.
Wenn ichs so wie im Code unten mache, krieg ich Probleme bei dem Wert
für den AD Wandler. Es kommt zwar der Zahlenwert an, aber danach noch
teilweise 2 3 oder mehr Mistzeichen.
Deshalb wollte ich die Daten in ein char Array schmeissen und das dann
komplett ausgeben. Warum? Weil ich denke das zwischendrin irgendwelche
undefinierten Sachen in den Uartpuffers des Rechners kommen bevor der MC
die nächsten Daten schickt und zwar in der for Schleife welche den
string der itoa Funktion auswertet.
Ausserdem wenn ich die Daten in das Char Array schreiben will egal ob
Hexwert oder als Buchstabe kommt diese Fehlermeldung und am Uart kommt
nur ein Zeichen welches zufällig auszusehen scheint.
../Main.c:76: warning: array subscript has type 'char'
Bau ich irgendwo mist? Wahrscheinlich sonst würds ja gehen :-)
Hier mal der Code:
*--------------------------------------------
void Datenuebertragung()
{
//--Char Array für Übertragungsdaten definieren
//char DatenArray[20];
//int DatenArray_Index = 0;
//--Variablen für den AD Wandler
uint16_t adcval; //--Variable für den Wert am AD Wandler
char string[7]; //--Hilfsvariable für die Übertragung
char i; //--Hilfsvariable für die Übertragung
//--Auslesen des AD Wandlers
adcval=ReadChannel(2);
//--Umwandeln des Intwertes in String Variable für Übertragung
itoa(adcval,string,10);
//--Beginn des Datenprofils der Messwerte in Datenarray schreiben
//DatenArray[DatenArray_Index]="<";
//DatenArray_Index++;
//DatenArray[DatenArray_Index]=0x3B;
//DatenArray_Index++;
usart_putc(0x3C); //-- < Senden
usart_putc(0x3B); //-- ; Senden
//--Übertragung Analogwert 1
for(i=0;i<7;i++)
{
if(string[i]==0x60) //--Abruch falls Stringende des Intwertes
erreicht ist
{
break;
}
//DatenArray[DatenArray_Index]=string[i];
//DatenArray_Index++;
usart_putc(string[i]); //-- Senden des AD Wertes
}
//DatenArray[DatenArray_Index]=0x3B;
//DatenArray_Index++;
usart_putc(0x3B); //-- ; Senden
//--Todo zweiter AD Wandler
//--Bis dahin Standardwert 0 schicken
//DatenArray[DatenArray_Index]=0x30;
//DatenArray_Index++;
//DatenArray[DatenArray_Index]=0x3B;
//DatenArray_Index++;
usart_putc(0x30); //-- 0 Senden
usart_putc(0x3B); //-- ; Senden
//--Digitale Zustände erkennen und Senden
//--Zustand 1
if (bit_is_set(PINB,0))
{
//DatenArray[DatenArray_Index]=0x31;
//DatenArray_Index++;
usart_putc(0x31);
}
else
{
//DatenArray[DatenArray_Index]=0x30;
//DatenArray_Index++;
usart_putc(0x30);
}
//DatenArray[DatenArray_Index]=0x3B;
//DatenArray_Index++;
usart_putc(0x3B); //-- ; Senden
//--Zustand 2
if (bit_is_set(PINB,1))
{
//DatenArray[DatenArray_Index]=0x31;
//DatenArray_Index++;
usart_putc(0x31);
}
else
{
//DatenArray[DatenArray_Index]=0x30;
//DatenArray_Index++;
usart_putc(0x30);
}
//DatenArray[DatenArray_Index]=0x3B;
//DatenArray_Index++;
usart_putc(0x3B); //-- ; Senden //--Zustand 3
if (bit_is_set(PINB,2))
{
//DatenArray[DatenArray_Index]=0x31;
//DatenArray_Index++;
usart_putc(0x31);
}
else
{
//DatenArray[DatenArray_Index]=0x30;
//DatenArray_Index++;
usart_putc(0x30);
}
//DatenArray[DatenArray_Index]=0x3B;
//DatenArray_Index++;
usart_putc(0x3B); //-- ; Senden
//--Datensatz abschluss senden
//DatenArray[DatenArray_Index]=0x3E;
//DatenArray_Index++;
usart_putc(0x3E); //-- < Senden
//--Senden des Datenstrings
// for (i=0;i<DatenArray_Index;i++);
// {
// usart_putc(DatenArray[i]);
// }
}
Die Warnmeldung soll Dich möglicherweise darauf aufmerksam machen, dass
es zu Nebenwirkungen kommen kann, wenn man vorzeichenbehaftete Variablen
als Array-Index verwendet...
Abgesehen bietet dieses Forum die Möglichkeit, C-Code vernünftig zu
formatieren, um ihn lesbarer zu machen. Diese Möglichkeit solltest Du
nutzen...
if(string[i]==0x60)//--Abruch falls Stringende des Intwertes
5
erreichtist
6
{
7
break;
8
}
9
//DatenArray[DatenArray_Index]=string[i];
10
//DatenArray_Index++;
11
usart_putc(string[i]);//-- Senden des AD Wertes
12
}
ist doch Müll. Warum fragst du ausgerechnet auf 0x60 ab?
(BTW: 0x60 ist ein Zeichen wie jedes andere. Weder für
atoi noch für irgendeine andere String-Funktion hat dieses
Zeichen irgendeine spezielle Bedeutung)
Jeder gültige String in C ist mit einem '\0' Character
abgeschlossen. Das kannst du auch ausnutzen, indem du die
komplette Schleife darauf aufbaust.
1
i=0;
2
while(string[i]!='\0')
3
usart_putc(string[i++]);
Dieses Prinzip ist so universell, dass es sich lohnt für
die Ausgabe von Strings, gleich mal eine eigene Funktion
zu schreiben:
1
voidusart_puts(constchar*Text)
2
{
3
unsignedinti=0;
4
5
while(Text[i]!='\0')
6
usart_putc(Text[i++]);
7
}
und in weiterer Folge mit dieser Funktion zu arbeiten
1
usart_putc(0x3C);//-- < Senden
2
usart_putc(0x3B);//-- ; Senden
3
4
//--Übertragung Analogwert 1
5
usart_puts(string);
6
7
usart_putc(0x3B);//-- ; Senden
Weiters. Gewöhn dir das herumschmeissen mit ASCII Codes
gleich wieder ab.
Es gibt absolut keinen Grund
usart_putc(0x30);
zu schreiben, wenn du
usart_putc( '0' );
meinst. Der Unterschied zwischen den beiden Schreibweisen dürfte
offensichtlich sein. Gibst du den ASCII Code 0x3B aus, so wird
wohl so ziemlich jeder in einer ASCII Tabell nachsehen müssen,
welches Zeichen denn den Code 0x3B hat. Schreibst du aber
usart_putc( ';' );
dann braucht niemand irgendeine Tabelle, um zu erkennen, dass
du einen ; ausgeben willst. Dann brauchst du auch keinen
Kommentar mehr, ala.
usart_putc(0x3E); //-- < Senden
schreib was du meinst:
usart_putc( '<' );
Servus,
warum Ascii...weil mir immer eingehämmert wurde ein Programmierer hat
diese im Kopf zu haben und zu Nutzen. Angeblich schneller...obs stimmt
weis ich net.
<Jeder gültige String in C ist mit einem '\0' Character
<abgeschlossen. Das kannst du auch ausnutzen, indem du die
<komplette Schleife darauf aufbaust.
Also brauch ich auch für jeden String 2 Zeichen mehr. Für einen String
mit 19 Zeichen brauch ich dann 21 damit das \0 noch mit reinpasst.
Das schöne ist so kommt am Uart dann alles korrekt an soweit, aber mein
C# läuft 2 mal in die Abfrageschleife rein...aber vorher mit Bascom lief
sie einmal rein, deshalb wollte ich halt die Variablen in nen String
schmeissen und auf einmal ausgeben. Gibts aber nur ein !-Zeichen aufn
Hyperterminal.
Theoretisch könnte ich ja auf die 2 mal in C# warten, aber was ist wenn
die Verbindung zwischendrin abreisst, dann wartet der Rechner ewig.
So sieht die Zuweisung aus.
Matthias wrote:
> Servus,>> warum Ascii...weil mir immer eingehämmert wurde ein Programmierer hat> diese im Kopf zu haben und zu Nutzen. Angeblich schneller...
Das ist Unsinn.
uart_putc( 32 );
uart_putc( 0x20 );
uart_putc( ' ' );
ist exakt dasselbe. Es sind nur 3 verschiedene Schreibweisen
für immer dasselbe: Die Funktion uart_putc wird aufgerufen
und ihr wird der ASCII Code für ' ' übergeben. Nur in den
ersten beiden Fällen musst du selbst den ASCII Code wissen
und im letzten Fall setzt der Compiler für dich ein.
Es gibt noch ein anderes Argument, welches zugegebenermassen
auf den hier benutzten Systemen nicht wirklich wichtig ist:
Die letzte Version ist portabel!
Wenn du je auf einem IBM Mainframe programmieren musstest (oder
irgendwann musst) wirst du lernen, dass ASCII nicht die einzige
Codierung ist, die es gibt. IBM Mainframes benutz(ten) EBCDIC.
Und dort hat ' ' einen ganz anderen Code als 0x20.
Der Compiler dort weiss das und ersetzt ' ' mit dem richtigen
Code wenn du ' ' benutzt. Nicht jedoch, wenn du 0x20 schreibst.
>> <Jeder gültige String in C ist mit einem '\0' Character> <abgeschlossen. Das kannst du auch ausnutzen, indem du die> <komplette Schleife darauf aufbaust.> Also brauch ich auch für jeden String 2 Zeichen mehr.
1 mehr.
> Für einen String> mit 19 Zeichen brauch ich dann 21 damit das \0 noch mit reinpasst.
Du brauchst 20.
In ein Array der Länge 10
char Text[10];
passt ein String mit 9 druckbaren Zeichen. Zb. "abcdefghi"
+---+---+---+---+---+---+---+---+---+---+
| a | b | c | d | e | f | g | h | i | \0|
+---+---+---+---+---+---+---+---+---+---+
>> Das schöne ist so kommt am Uart dann alles korrekt an soweit, aber mein> C# läuft 2 mal in die Abfrageschleife rein...aber vorher mit Bascom lief> sie einmal rein, deshalb wollte ich halt die Variablen in nen String> schmeissen und auf einmal ausgeben.
Den (auskommentierten) Teil hab ich mir nicht weiter angesehen.
> Gibts aber nur ein !-Zeichen aufn> Hyperterminal.>> Theoretisch könnte ich ja auf die 2 mal in C# warten, aber was ist wenn> die Verbindung zwischendrin abreisst, dann wartet der Rechner ewig.> So sieht die Zuweisung aus.>>
1
>DatenArray[DatenArray_Index]='<';
2
>DatenArray_Index++;
3
>DatenArray[DatenArray_Index]=';';
4
>DatenArray_Index++;
5
>
> Senden wollte ichs so>
1
>for(i=0;i<DatenArray_Index;i++);
2
>{
3
>usart_putc(DatenArray[i]);
4
>}
5
>
>
selbiges auch hier:
Mach den "String" mal zu einem richtigen C-String.
Verpass ihm ganz zum Schluss ein \0 Zeichen und
benutze die String Funktionen.
Ich denke aber nicht, dass das dein Problem lösen wird.
Ob du die Ausgabe in kleinen Happen schickst oder in einem
Schwall macht ja keinen Unterschied.
Dein Fehler wird wohl auf C# Seite liegen.
Matthias wrote:
> <Jeder gültige String in C ist mit einem '\0' Character> <abgeschlossen. Das kannst du auch ausnutzen, indem du die> <komplette Schleife darauf aufbaust.> Also brauch ich auch für jeden String 2 Zeichen mehr.
Hinweis: das Zeichen "backslash null", '\0' ist ein einzelnes Zeichen,
nicht zwei bestehend aus "backslash" '\' und "null" '0'.
Es handelt sich um den sogenannten Null-Terminator mit ASCII-Wert 0x00.
Die Schreibweise mit dem vorangestellten Backslash ist nur so gewählt,
um das Ding nicht mit dem Zeichen "Null" '0' zu verwechseln.
Gruss, Martin
Servus,
etz bin ich wenigstens Zwecks Ascii schlauer. Aber für den Lehrer gabs
nur die Welt von Intel und MS, der Rest hat ihn net interessiert. Man
merkt schon wie MS um jeden Kunden kämpft, wir kriegen die meisten MS
Produkte kostenlos. Seis Windows, Compiler oder Office. Wie sagte schon
Bill Gates...er sieht lieber 1000 Rechner mit illegalem Windows drauf
als einen mit Linux oder der gleichen drauf.
Naja ist ja etz egal jetzt weis ichs ja besser.
Danke soweit.
Fehler bei C#...wäre nicht der erste, der mir auf die Nerven geht.
Ich Tipp fast drauf das die kurze Pause zwischen dem Ausgeben des
AD-Wandlerwertes C# schon veranlasst die ersten Zeichen zu hohlen die im
Uartpuffer rechnerseitig drin sind. Wobei die Pause wohl im µs Bereich
liegen dürfte.
Wegen dem String...also ich glaub dir was du sagst.
Jedoch warum sind \0 als ein Zeichen gesehen?
Für mich ist beides jeweils ein Zeichen...
Naja das Buch welches ich hab schweigt sich da leider auch sehr aus.
Ich merk schon die 4 Jahre wo ich mal für ein halbes Jahr C hatte und
kaum mehr als ein "Hallo World" Programm erstellt habe reichen hier wohl
lange nicht...aber es wird dank euer Hilfe immer besser.
Jetzt wenn ich die Kamera noch so zum laufen krieg wie sie sollte und
das Display anzeigt was es soll dann wäre ja alles gut.
Also dank euch derweilen...
MfG
Matthias
Matthias wrote:
> Wegen dem String...also ich glaub dir was du sagst.> Jedoch warum sind \0 als ein Zeichen gesehen?> Für mich ist beides jeweils ein Zeichen...http://www.gidf.de/ ;-)
Zitat aus http://en.wikipedia.org/wiki/Null_character :
"The character has special significance in C and its derivatives, where
it serves as a reserved character used to signify the end of strings.
The null character is often represented as '\0' in source code (in
reality an octal escape sequence). Strings ending in a null character
are said to be null-terminated."
Edit: Das ist wie der "new line" character beim printf Befehl, dieser
ist "backslash 'n'" , '\n' und repräsentiert auch nur ein Zeichen,
nämlich "new line"
Matthias wrote:
> Wegen dem String...also ich glaub dir was du sagst.> Jedoch warum sind \0 als ein Zeichen gesehen?
Weil es sonst keine (schöne) Möglichkeit gäbe diverse
Sonderzeichen zu bilden.
Du schreibst ja auch \n für einen Zeilenvorschub und
das ist dann nur ein einziges Zeichen. Oder \t für
einen Tabulator und das ist auch nur ein einzelnes
Zeichen. Und so hat halt \0 auch eine spezielle Bedeutung
und ist trotzdem nur ein einzelnes Zeichen.
Es gibt noch mehr dieser sog. Escape-Zeichen. Will man
tatsächlich einen einzelnen Back-Slash haben, so lautet
das 'Zeichen' dafür dann \\
> Für mich ist beides jeweils ein Zeichen...
Für dich vielleicht. Nicht jedoch für den Compiler.
Und der Compiler hat das Sagen.
> Naja das Buch welches ich hab schweigt sich da leider auch sehr aus.
Ehrlich?
Schmeiss es weg und kauf dir ein Vernünftiges.
>> Ich merk schon die 4 Jahre wo ich mal für ein halbes Jahr C hatte und> kaum mehr als ein "Hallo World" Programm erstellt habe reichen hier wohl> lange nicht...aber es wird dank euer Hilfe immer besser.
(Ist nicht böse gemeint:)
Das ist allerdings richtig. Ich geh mal davon aus, dass du mit
'halbes Jahr' ein Schulsemester meinst. Das entspricht, wenn man
die Stunden rechnet, gerade mal 1 bis 2 Wochen Programmierung.
Damit bist du bestenfalls gerade mal im mittleren Anfängerstadium.
Da wartet noch vieles auf seine Entdeckung durch dich.
Aus dem Anfängerstadium bist du in ein paar (realen) Wochen
raus. In 5 bis 6 Monaten bist du Fortgeschrittener. Profi
wird man nach ein paar Jahren. Und Experte wird man eigentlich
nie. Es gibt immer wieder was zu lernen. Selbst nach 20 Jahren
hält C noch so manche Überraschung für mich bereit.
Servus,
also halbes Jahr C und dann gings mit den anderen Sprachen los.
Zuerst mal VB, SQL und dann zum Schluss etz halt C#.Net.
C# mach ich jetzt schon 2 Jahre da kommt ich relativ gut hin.
C hat mir vorallem wegen dem Zeigersachen nicht sonderlich gefallen
(Lehrer war ein Freak davon). Ein Zeiger auf Zeiger von einem 4dim.
Array auf Zeigern...*würg*.
Habs damals sogar geschafft meinen Rechner Betriebssystemmässig zu
killen mit dem Zeigerzeug in den Übungen. In den praktischen Stunden
ging bei mir dort reihenweise der Dr.Watson Virenscanner an. :-)
MfG
Matthias