Hallo, ich habe folgenden Code auf einem Atmega8 (Ausschnitt):
1
unsignedintempfi;
2
3
empfi=uart_getc();
4
if(empfi&UART_NO_DATA)
5
{
6
// keine Daten erhalten
7
}
8
else
9
{
10
uart_putc((unsignedchar)empfi);
an meinem PC wird jetzt eine Zahl zwischen 0-255 ausgegeben.
jetzt möchte ich mit dem Wert "empfi" auf meinem Atmega8 Berechnungen
durchführen (z.B.: empfi=empfi-10).
Wie/oder Was muss ich mit "empfi" machen damit ich solche Berechnungen
durchführen kann?
Danke.
Wenn uart_getc aber 16 bit zurück gibt, wobei die oberen 8 bit als
Statusbits verwendet werden, dann reichen 8 bit nicht. UART_NO_DATA ist
so ein Statusbit, das man verwendet, um zu erkennen ob überhaupt Daten
empfangen wurden!
Chris L. schrieb:> Wenn uart_getc aber 16 bit zurück gibt, wobei die oberen 8 bit als> Statusbits verwendet werden, dann reichen 8 bit nicht.16 Bit oder mehr schrieb:> Dann sollte man mit Wert nicht einfach rechnen.Henri Großmann schrieb:> Hallo, das mit einfach rechnen wie z.b. empfi = empfi-10 funktioniert> nicht.> Kommt immer mist raus.
Statusbits loeschen...
1
uint16_tempfi;
2
3
empfi=uart_getc();
4
5
// statusbits loeschen
6
empfi=empfi&0x00FF;// wenn die statusbits im oberen Byte stehen, sonst
Henri Großmann schrieb:> Hallo, das mit einfach rechnen wie z.b. empfi = empfi-10> funktioniert nicht.> Kommt immer mist raus.
Pack den cast mit rein
empfi = (unsigned char)empfi - 10;
'Kaj' schrieb:> empfi = empfi & 0x00FF; // wenn die statusbits im oberen Byte stehen,> sonst
sie stehen im oberen Byte und man braucht sie nicht löschen, da sie 0
sind, solange UART_NO_DATA nicht gesetzt ist. Abgesehen davon strippt
uart_putc sowieso das High-Byte raus.
'16 Bit oder mehr' schrieb
> Pack den cast mit rein
Man braucht auch nichts casten. Du bellst den völlig falschen Baum an.
@Henri
> Kommt immer mist raus.
Definiere 'Mist'.
Was sendest du dem µC und was erwartest du?
Dir ist hoffentlich klar, dass du hier eine Binärübertragung hast. D.h.
du sendest Bytes.
Wenn du vor einem Terminal sitzt und dort auf der Tastatur 173 tippst,
dann wird nicht 1 Byte mit dem Wert 173 übertragen, sondern es werden 3
Bytes übertragen: eines mit dem ASCII Code für '1', eines mit dem ASCII
Code für '7' und eines mit dem ASCII Code für '3'. Und ein 4.tes Byte
wirst du dann auch noch brauchen, denn der µC kann ja nicht riechen,
dass du nach den Tasten 1 und 7 noch die 3 drücken wirst. Das 4.te Byte
brauchst du also um anzuzeigen: jetzt ist alles übertragen.
Auf dem µC musst du die Bytes wieder zusammensetzen, daraus eine Zahl
machen, davon 10 abziehen und dann aus der neuen Zahl wieder einen Text
machen, den du dann zurück schickst, damit im Terminal die 'Zahl' (die
eigentlich auch nur ein Text ist) aufleuchtet und dein Gehirn 163 liest.
Wenn das nicht das ist, was du machen willst, dann definiere 'Mist'; wie
du feststellst, das Mist rauskommt und ob du eigentlich deine UART
insofern schon getestet hast, dass die Übertragung (Taktfrequenz,
Baudrate) überhaupt korrekt funktioniert.
@Karl Heinz
Hallo, erst einmal Danke für deinen langen Text...
Hier nochmal eine etwas genauere Angabe von mir.
Ich sende von einem Visual Basic Programm auf meine PC einen Wert an den
µC,
und zwar so...
1
DimdataAsInteger
2
data=128
3
SerialPort1.Write(data)
im µC Empfange ich die Daten (über USB -> UART) und gebe die Daten
danach zurück...
1
while(1)
2
{
3
empfi=uart_getc();// Daten empfangen
4
if(empfi&UART_NO_DATA)
5
{
6
// keine Daten erhalten
7
}
8
else
9
{
10
uart_putc((unsignedchar)empfi);// Daten zurück senden
11
}
jetzt empfange ich die Daten wieder mit meinem Visual Basic Programm auf
dem PC...
1
PufferString=SerialPort1.ReadExisting()
2
RichTextBox1.AppendText(PufferString)
Jetzt wird auf meinem PC GENAU die Zahl angezeigt welche ich vom PC zu
µC gesendet habe.
Das sagt mir die Übertragung von PC zu µC und zurück Funktioniert.
Jetzt möchte ich jedoch auf dem µC mit dieser Zahl (z.B.: 128)
verschieden Port's schalten...
1
if(empfi>127)
2
{
3
PORTB|=(1<<PB5);// Port B5 ein
4
empfi=empfi-128;// rest von empfi
5
}
6
else
7
{
8
PORTB&=~(1<<PB5);// Port B5 aus
9
}
So wo ist nun mein Denkfehler, lass mich gerne belehren beschäftige mich
ja
auch erst ca. 2 Wochen mit µC.
Danke an alle die mir weiterhelfen können, und dies auch machen...
> RichTextBox1.AppendText(PufferString)
Text?
Sobald Text im Spiel ist, funktioniert alles ein wenig anders.
Du musst dir erst mal klar machen, dass es einen UNterschied zwischen
binärer Übertragung und textueller Übertragung gibt.
Klar. Texte werden ebenfalls übertragen, in dem Bytes auf die Reise
gehen. Der UNterschied ist dann eben der, dass bei einer rein binären
Übertragung ein Byte-WErt von zb 32 für die Zahl 32 steht, während er
bei einer Text-Übertragung nach ASCII für ein Leerzeichen steht (weil
der ASCII COde für ein Leerzeichen nun mal 0x20 oder eben dezimal 32
ist).
Sobald Texte im Spiel sind, gibt es keinen prinzipiellen UNterschied
zwischen dem Text "168" und "Hugo". Beides sind auf der
Übertragungsebene einfach nur Texte, die Buchstabe für Buchstabe
übertragen werden.
Dass das Programm, welches am jeweils anderen Ende der Leitung mit
diesem Text etwas spezielles macht, ist eine andere Sache - betrifft
aber die reine Textübertragung nicht.
> Jetzt wird auf meinem PC GENAU die Zahl angezeigt welche ich vom PC zu µC
gesendet habe.
Nein. Es wird nicht die Zahl angezeigt. Es wird der Text (bestehend aus
mehreren 'Buchstaben') angezeigt. Das das mal eine Zahl war, das
entsteht erst in deinem Gehirn, welches dem Text "168" eine besondere
Bedeutung (nämlich den einer Zahl) zuweist. Aus Sicht der UART
unterscheidet sich der Text "168" vom Text
"Supercalifragilisticexpialidocious" nur in der Anzahl der Buchstaben
und der Auswahl der verwendeten Buchstaben. Aber Text ist Text und der
hat als solcher keine Bedeutung. Vor allen Dingen nicht den, eine Zahl
zu sein, mit der man rechnen könnte. Man kann natürlich auf µC Seite aus
dem Text "168" wieder eine Zahl machen und dann mit der rechnen. Kann
man, aber erst mal ist das einfach nur Text und sonst nichts.
Danke, aber hättest du eventuell noch einen kleinen Tipp wie ich
das am besten mache mit dem Text zu Zahl?
Habe schon viel mit atoi probiert will aber irgendwie nicht so wie
ich...
Und wäre dann so eine Abfrage möglich/richtig?
Henri Großmann schrieb:> Danke, aber hättest du eventuell noch einen kleinen Tipp wie ich> das am besten mache mit dem Text zu Zahl?
zuallererst brauchst du eine Kennung, mit der du feststellen kannst:
hier ist der Text zu Ende.
D.h. der PC kann nicht einfach nur den Text "12" senden. Denn niemand
kann (auch der µC nicht) wissen, ob nach den Zeichen '1' und '2' noch
etwas kommt, oder ob das schon der ganze Text war. Kann ja sein, dass
der PC den Text "12" wegschicken wollte. Kann aber auch sein, dass da
noch eine 4 kommt, und der ganze Text in WIrklichkeit "124" darstellen
soll.
Auf der anderen Seite des Kabels kann man nun mal nicht mehr
unterscheiden, ob diesseits
1
SerialPort1.Write( "123" );
stattgefunden hat, oder
1
SerialPort1.Write( "1" );
2
SerialPort1.Write( "2" );
3
SerialPort1.Write( "3" );
In beiden Fällen wird dasselbe übertragen. Nämlich nacheinander die
Zeichen '1', '2' und '3'.
Fazit: Ohne Zusatzinformation geht das nicht.
Dein VB Programm muss also nachdem es den
1
SerialPort1.Write(data)
noch etwas nachschieben. Ein Zeichen, welches in den Daten selbst nicht
vorkommt, woran aber der µC erkennen kann 'Huch: jetzt ist der Text zu
Ende, da kommt nichts mehr'
zb könnte dein VB Programm irgendein Sonderzeichen nachschieben. Ich
nehm man einen ';'
1
SerialPort1.Write(data)
2
SerialPort1.Write(";")
so. Damit ist klar, dass (in deinem Fall), die Zeichen '1', '2', '8' und
dann eben noch ein ';' über die Leitung geschoben werden.
Und die musst du eben wieder zusammensetzen.
Das kann man jetzt natürlich machen, in dem man die Zeichen in einem
char-Array sammelt. Kann man, muss man aber in deinem speziellen Fall
nicht. Denn in deinem Fall wissen wir, das (abgesehen vom ';') das ganze
eine Zahl darstellen soll. Und bei Zahlen geht das ganz einfach.
Ausgehend von zb 8, wie hängst du da die nächste Ziffer (sagen wir mal
eine '3' ran), so dass aus den 8 die 83 entstehen? Na, ganz einfach:
wenn du das nächste Zeichen hast, dann nimmst du die 8 einfach mal 10
und addierst noch den Zahlenwert für 3. So werden aus den 8 durch 8 * 10
+ 3 die 83. Und aus den 83 werden mit der nächsten Ziffern 4 die 834,
indem du die 83 mal 10 nimmst und noch 4 addierst.
D.h. deine Strategie lautet:
Hole das nächste Zeichen von der UART, falls eines vorhanden ist
Ist dieses nächste Zeichen ein ';', dann bedeutet das, das die 'Zahl'
(in Textform) komplett übertragen wurde. D.h. man kann die Zahl
bearbeiten und damit irgendwas machen (zb 10 subtrahieren und zurück
schicken)
Ist das nächste Zeichen kein ';' dann geht die Zahl weiter und dieses
Zeichen muss in die Zahl eingerechnet werden.
1
intmain()
2
{
3
charbuffer[10];
4
5
.....
6
7
zahl=0;
8
9
while(1)
10
{
11
empfi=uart_getc();
12
13
if(!(empfi&UART_NO_DATA))// gibt es ein Zeichen?
14
{
15
charc=empfi;// High Byte loswerden und nur den char übrig lassen
16
if(c==';')
17
{
18
// mach was mit der Zahl
19
zahl=zahl-10
20
itoa(zahl,buffer,10);
21
uart_puts(buffer);
22
uart_puts(';');
23
zahl=0;
24
}
25
else
26
{
27
// sicherheitshalber, auch wenn es nie vorkommen sollte
28
if(isdigit(c))
29
zahl=zahl*10+(c-'0');
30
}
31
}
32
}
und teste das Ganze erst mal mit einem gewöhnlichen Termninalprogramm
anstelle einem VB Programm. Du beginnst gerade einen 2-Fronten Krieg, in
dem du nicht weißt ob deine Programmfehler auf µC-Seite oder auf
VB-Seite zu suchen sind. Soweit bist du noch nicht, dass du das in einem
Aufwasch handhaben könntest. In derartigen 2-Fronten Kriege sind schon
ganz andere Kapazunder als von deinem Kaliber gnadenlos untergegangen.
Also. Entwickle erst mal so, dass du auf PC Seite ein Terminal-Programm
hast und du deine Eingaben mit der Hand machst. Dann weißt du auch, was
tatsächlich über die Schnittstelle rausgeht bzw. zurück kommt und musst
nicht raten, ob dein VB Programm das alles tatsächlich so erzeugt, wie
es das sollte, bzw. was tatsächlich über die Schnittstelle rausgeht
(dafür wäre auch zb die Installation eines Serial Port Monitors eine
ausgesprochen gute Idee)
Hallo, soweit versteh ich das jetzt ein wenig.
Der Code von dir funktioniert auch soweit, aber wie zum Teufel bekomme
ich jetzt den Wert (Zahl) welche sich im char c befindet zu einem
Integer (genau wie Zahl in deinem Beispiel).
Danke.
NEIN, NEIN, NEIN bin ich blöd....
Alles klar ich hab jetzt den Durchblick, alles funktioniert wie es soll.
Ich bedanke mich sehr bei
Karl Heinz
sowie
Rufus Τ. Firefly (für den letzten Tipp zum verstehen)
Danke, mein Problem ist gelöst.
P.S.: warum steht da "zahl * 10", versteh ich nicht
Henri Großmann schrieb:> warum steht da "zahl * 10", versteh ich nicht
Damit du alle Ziffern deiner Zahl mit einrechnest.
Dezimalzahl hat was mit 10 zu tun.
Probier es doch mal aus mit 123
Du bekomst erst die Ziffer '1' und zahl = 0
zahl = 0 * 10 + ('1' - '0') = 0 + 1 = 1
zahl = 1 * 10 + ('2' - '0') = 10 + 2 = 12
zahl = 12 * 10 + ('3' - '0') = 120 + 3 = 123
fertig