Guten Tag,
ich möchte Messwerte (Integer) vom PC an der uC über USB (FT232 im
Einsatz) senden. Zur Zeit benutze ich den USART. Ich zerlege auf dem PC
mein Integer in die unterschiedlichen Ziffern und sende im festen
Datenformat:
z.B. Integer 123 -> Char "0" "1" "2" "3"
Auf dem uC interpretiere ich die "Zahl" als:
atoi(0)* 1000 + atoi(1) * 100 + atoi(2) * 10 + 1* atoi(3) = 123
Nun kann ich sie weiterverarbeiten. Ziemlich umständlich. Hat wer einen
einfachen Alternativansatz ?Setze es in C auf dem ATMega16 um.
Vielen Dank
du kannst es dcoh einfach binär senden.
Integer 123 wird dann als "0x00 0x7b" also 2 zeichen gesendet. Du musst
nur ein Protokoll definieren damit du den anfang und das ende der zahlen
erkennst.
Peter II schrieb:> du kannst es dcoh einfach binär senden.
Jaja. Das ist die einfachste und zugleich dümmste Methode, denn sie
enthält keinerlei Mittel, um die zwei beteiligten Rechner zu
synchronisieren. Stell dir vor, jemand will Zahlen >255 senden. Was
dann? Hoffen, daß nie was dazwischenkommt? Nee, irgendeine Art Protokoll
ist schon nötig.
Aber was soll das?
"atoi(0)* 1000 + atoi(1) * 100 + atoi(2) * 10 + 1* atoi(3) = 123"
Ich verstehe nicht den tieferen Sinn dieses langen Schriebses.
Wahrscheinlich würde ich das sinngemäß etwa so machen und die Zahlen
mit nem Komma voneinander separieren:
var
L : longint;
C : Char;
L:= 0; C:= #0;
repeat
if CharAvailable(MyComport)
then begin
C:= GetTheChar(MyComport);
if C in ['0'..'9'] then L:= L*10+(C-'0');
until (C=',') or (MyState=HaveNoLustMehr);
DoSomething(L);
GoToBed;
end.
W.S.
W.S. schrieb:>> du kannst es dcoh einfach binär senden.> Jaja. Das ist die einfachste und zugleich dümmste Methode, denn sie> enthält keinerlei Mittel, um die zwei beteiligten Rechner zu> synchronisieren.
klar doch - aus dem Grund verwendet PPP oder Ehternet auch Klartext.
Text ist das dümmste was man machen kann, dann dann muss man auf beiden
seiten wandeln denn für ein computer ist das so nicht verständlich.
Warum sollen sich 2 Computer in der Sprache der Menschen unterhalten?
Du kannst es auch per Hand umrechnen indem du von der Zahl eine 59 glaub
ich abziehst, müsst mal gucken welchen hex Wert eine 0 hat. Da sparste
dir zumindest das atoi.
Ingo
ATMega16_Einsteiger schrieb:> z.B. Integer 123 -> Char "0" "1" "2" "3">> Auf dem uC interpretiere ich die "Zahl" als:>> atoi(0)* 1000 + atoi(1) * 100 + atoi(2) * 10 + 1* atoi(3) = 123
Und warum bastelst Du nicht aus den vier Zeichen einen String, den Du
dann atoi vorwirfst?
atoi("0123") = 123 ...
ATMega16_Einsteiger schrieb:> Auf dem uC interpretiere ich die "Zahl" als:>> atoi(0)* 1000 + atoi(1) * 100 + atoi(2) * 10 + 1* atoi(3) = 123>> Nun kann ich sie weiterverarbeiten. Ziemlich umständlich.
Du kannst auch einfach atoi("0123") machen, dann kannst du dir das
Zusammenbasteln von Hand sparen.
Peter II schrieb:> klar doch - aus dem Grund verwendet PPP oder Ehternet auch Klartext.
Die meisten Protokolle verwenden in der Tat Klartext.
Peter II schrieb:> Text ist das dümmste was man machen kann, dann dann muss man auf beiden> seiten wandeln denn für ein computer ist das so nicht verständlich.
ASCII-Text ist in der Tat eine der schlausten Arten, Daten zu
übertragen, oft sogar zu speichern. "Der" Computer "weiß" keineswegs, ob
ihm Zahlen in 8/16/32/... Bit Breite, mit oder ohne Vorzeichen, als
binäre Ganzzahl oder als Fließkomma, in Little oder Big Endian vorgelegt
werden.
> Warum sollen sich 2 Computer in der Sprache der Menschen unterhalten?
Man kann natürlich auch ASN.1 nehmen. In den meisten Fällen ist das aber
schlicht Overkill.
Dauergast schrieb:> Die meisten Protokolle verwenden in der Tat Klartext.
nur keine bei denen aus auf geschwindigkeit und effizienz ankommt.
Auch würde ich mich mit "meisten" sehr zurück halten, ich kenn kaum
Protokolle außerhalb von http (inc. mail) wo etwas im klartext gemacht
wird. ( PPP, XMODEM, ETHERNET, IP, TCP, X25, ISDN, TDS (sql-server) usw.
)
> ASCII-Text ist in der Tat eine der schlausten Arten, Daten zu> übertragen, oft sogar zu speichern. "Der" Computer "weiß" keineswegs, ob> ihm Zahlen in 8/16/32/... Bit Breite, mit oder ohne Vorzeichen, als> binäre Ganzzahl oder als Fließkomma, in Little oder Big Endian vorgelegt> werden.
warum sollte eine ineffizienzte (mehr Platz und mehr CPU-Resourcen)
lösung sinnvoll sein?
Weil ebend der computer nicht weiss was für daten kommen definiert man
ja ein Protokoll in diesem ist festgelgt welche Daten wie übertragen
werden.
> Man kann natürlich auch ASN.1 nehmen. In den meisten Fällen ist das aber> schlicht Overkill.
ASN.1 ist wirklich etwas übertrieben, ich würde es aber einem XML parser
vorziehen wenn es schnell und resourcen schonden werden soll.
Peter II schrieb:> warum sollte eine ineffizienzte (mehr Platz und mehr CPU-Resourcen)> lösung sinnvoll sein?
Wesentlich ineffizienter ist es nur, wenn Du auf beiden Seiten zufällig
dieselbe Wortbreite, Endianität und dasselbe Alignment hast. Aber das
ist eher selten, und noch seltener für die Zukunft vorhersehbar.
Dauergast schrieb:> Wesentlich ineffizienter ist es nur, wenn Du auf beiden Seiten zufällig> dieselbe Wortbreite, Endianität und dasselbe Alignment hast. Aber das> ist eher selten, und noch seltener für die Zukunft vorhersehbar.
gut dann ist es nur noch 5mal so effizent und nicht mehr 10mal effizent.
ATMega16_Einsteiger schrieb:> z.B. Integer 123 -> Char "0" "1" "2" "3">> Auf dem uC interpretiere ich die "Zahl" als:>> atoi(0)* 1000 + atoi(1) * 100 + atoi(2) * 10 + 1* atoi(3) = 123
"1" ist ein String. Das Zeichen wäre '1'.
Eine String ist ein Nullterminiertes char-Array.
atoi erwartet als Argument ein Nullterminiertes char-Array und kein
einzelnes Teichen. Das klappt also nicht so, wie du es probierst.
Ansonsten kannst du von den empfangenen Zeichen einfach '0' abziehen.
Peter II schrieb:> Dauergast schrieb:>> Die meisten Protokolle verwenden in der Tat Klartext.>> nur keine bei denen aus auf geschwindigkeit und effizienz ankommt.
Auf Applikationsebene sind im Internet so gut wie alle gängigen
Standard-Protokolle textbasiert. Manche neueren Protokolle wie Jabber
benutzen sogar XML.
>> ASCII-Text ist in der Tat eine der schlausten Arten, Daten zu>> übertragen, oft sogar zu speichern. "Der" Computer "weiß" keineswegs, ob>> ihm Zahlen in 8/16/32/... Bit Breite, mit oder ohne Vorzeichen, als>> binäre Ganzzahl oder als Fließkomma, in Little oder Big Endian vorgelegt>> werden.>> warum sollte eine ineffizienzte (mehr Platz und mehr CPU-Resourcen)> lösung sinnvoll sein?
Es ist programmiertechnisch die einfachste. Außerdem läßt es sich viel
einfacher debuggen. Wenn der Overhead nicht besonders stört, ist es
sinnvoller, diese Vorteile zu nutzen.
Uc: Sprintf(string,"%d",Zahl); send-uart-s(string);
Pc: get_String(String); atoi(String);
Is zwar Ucseitig nicht Ressourcensparend aba am einfachsten!
Bessere Variante wäre mit Bitshift den integer in 2 chars umwandeln und
pcseitg wieder zusammensetzen : char = integer <<8; usw.. ( pseudocode->
siehe tutorial Bitoperationen)
Rolf Magnus schrieb:> Auf Applikationsebene sind im Internet so gut wie alle gängigen> Standard-Protokolle textbasiert. Manche neueren Protokolle wie Jabber> benutzen sogar XML.
richtig aber hier geht es um ein übertragungsrpotokoll auf der Seriellen
Leitung und übertragungsprotkolle sind auf den unteren schichten sind
meist keine Text Protokolle.
> Uc: Sprintf(string,"%d",Zahl); send-uart-s(string);> Pc: get_String(String); atoi(String);
schon die verwendung von Sprintf macht es noch schlimmer, es gibt auch
itoa!
Hast du mal auf einen µC die anzahl der Take für diese beiden zeilen dir
angeschaut? Wir reden hier mindestens vom ein paar 100.
uint16_t zahl;
uc: send( Zahl, sizeof(Zahl) );
pc: Read( Zahl, sizeof(Zahl) );
bei bedarf kann man noch ein LittleEdian/Bigendian swap einbauen.
> Es ist programmiertechnisch die einfachste. Außerdem läßt es sich viel> einfacher debuggen. Wenn der Overhead nicht besonders stört, ist es> sinnvoller, diese Vorteile zu nutzen.
ist schon erstaunlich das das ganze Wissen um die Verarbeitung von
Binären daten in den letzen Jahren verloren gegangen ist. Vor 10Jahren
hatte die Programmieren damit keine Probleme. Aber heute muss ja alles
auf XML gemacht werden, sonst wüssten die CPUs gar nicht mehr was sie
machen sollen.
Peter II schrieb:> ist schon erstaunlich das das ganze Wissen um die Verarbeitung von> Binären daten in den letzen Jahren verloren gegangen ist.
Da gab es auch noch Methoden wie z.B. das "sixeln" um unabhängig von
7,e,1 oder 8,n,1 auf der seriellen übertragen zu können.
Gruß Anja
Peter II schrieb:> richtig aber hier geht es um ein übertragungsrpotokoll auf der Seriellen> Leitung und übertragungsprotkolle sind auf den unteren schichten sind> meist keine Text Protokolle.
Auf RS232 hat man meistens keine unteren Schichten. Wozu auch?
>> Uc: Sprintf(string,"%d",Zahl); send-uart-s(string);>> Pc: get_String(String); atoi(String);> schon die verwendung von Sprintf macht es noch schlimmer, es gibt auch> itoa!
Was macht es schlimmer? Es braucht natürlich mehr Ressourcen, aber wenn
man die zur Verfügung hat, wird dadurch gar nichts schlimmer. Wie es
immer so schön heißt: Man bekommt von Atmel kein Geld für nicht
benutzten Speicher zurück. Und mit sprintf hab ich den Vorteil, daß ich
auch gleich eine komplette Zeile auf einmal erzeugen kann, statt die aus
lauter Einzelwerten mühevoll zusammenzubasteln.
Wenn die Ressourcen nicht verfügbar sind, braucht man natürlich eine
andere Lösung. Aber programmiertechnisch ist sprintf die einfachste
Möglichkeit.
> Hast du mal auf einen µC die anzahl der Take für diese beiden zeilen dir> angeschaut? Wir reden hier mindestens vom ein paar 100.
Und? Unmittelbar danach werden wahrscheinlich Tausende von Taktzyklen in
einer Schleife verbraten, die nix andres tut, als darauf zu warten, daß
der nächste Programmzyklus losgeht.
> uint16_t zahl;>> uc: send( Zahl, sizeof(Zahl) );> pc: Read( Zahl, sizeof(Zahl) );>>> bei bedarf kann man noch ein LittleEdian/Bigendian swap einbauen.
Um sowas braucht man sich bei Text nicht kümmern. Auch nicht um ein
Protokoll, das es schafft, nach Unterbrechungen wieder den Anfang des
nächsten Datenpakets zu finden. Das ergibt sich bei zeilenweiser
Textübertragung quasi von selbst.
>> Es ist programmiertechnisch die einfachste. Außerdem läßt es sich viel>> einfacher debuggen. Wenn der Overhead nicht besonders stört, ist es>> sinnvoller, diese Vorteile zu nutzen.> ist schon erstaunlich das das ganze Wissen um die Verarbeitung von> Binären daten in den letzen Jahren verloren gegangen ist. Vor 10Jahren> hatte die Programmieren damit keine Probleme.
Ich schrieb nicht, daß es ein Problem ist, sondern nur, daß es
umständlicher ist.
> Aber heute muss ja alles auf XML gemacht werden, sonst wüssten die CPUs> gar nicht mehr was sie machen sollen.
XML finde ich dann auch etwas übertrieben. Wenn man sich Sachen wie
xmlrpc anschaut, hat man das Gefühl, daß es die Erfinder darauf angelegt
haben, den Overhead so groß wie nur irgend möglich zu machen.
Hallo,
Danke für die Antworten. Habe mein Programm angehängt. Ich übergebe vom
PC aus:
0100001234 => Pin 0 Status 1 (High) Verzögerung 1234 us etc.
Also:
01000012341100001234210000123431000012344100001234
für einen Vorgang. (Ich habe am Controller 5 Kanäle nach Außen geführt.
Mein Problem:
Die Pins werden richtig geschaltet. Die Verzögerung in us stimmt nicht
(mit Oszilloskop überprüft). Trage ich in die Delayfunktion einen festen
Wert selber ein ..also nicht über die Variable Time[n], dann stimmen die
Zeiten.
Hat wer Anregungen wo ich mit der Fehlersuche beginnen kann. Ich suche
schon etwas länger. Habe mir alles Ausgeben lassen, die Zeichen werden
scheinbar richtig übertragen.
Danke
ATMega16_Einsteiger schrieb:> z.B. Integer 123 -> Char "0" "1" "2" "3">> Auf dem uC interpretiere ich die "Zahl" als:>> atoi(0)* 1000 + atoi(1) * 100 + atoi(2) * 10 + 1* atoi(3) = 123>> Nun kann ich sie weiterverarbeiten. Ziemlich umständlich. Hat wer einen> einfachen Alternativansatz ?Setze es in C auf dem ATMega16 um.
Marcus hat ja schon darauf hingewiesen, dass du bei _delay_us keine
Variable verwenden kannst.
Das heißt: Du kannst schon. Nur stimmen die Zeiten nicht.
Zu deiner ursprünglichen Frage.
Wenn du das hier
hast du an dieser Stelle bereits alles beisammen:
Die Umrechnung von Zeichen in einen echten Integer (das was bei dir die
Funktion char_to_int gemacht hat) UND die Aufsummierung zur
vollständigen Zahl (das was deine Multiplikationen mit den
Hilfsvariablen gemacht haben).
OK, nicht ganz. Deine Hilfsfunktion char_to_int hat noch Fehlerprüfung
gemacht. So gesehen wäre der 100% Ersatz
1
intchar_to_int(charc)
2
{
3
if(c>='0'&&c<='9')
4
returnc-'0';
5
6
return0;
7
}
8
...
9
...
10
11
Time_us_[i]=0;
12
13
for(j=0;j<8;j++)// das k braucht kein Mensch da drinnen
Einsteiger_ATMega16 schrieb:> Mein Problem:> Die Pins werden richtig geschaltet. Die Verzögerung in us stimmt nicht> (mit Oszilloskop überprüft). Trage ich in die Delayfunktion einen festen> Wert selber ein ..also nicht über die Variable Time[n], dann stimmen die> Zeiten.
Du hast also weder die Doku der avr-libc, noch die Warnung des Compilers
gelesen. Solltest du mal tun.
Ich habe keine Warnung erhalten. Die avr-libc habe ich echt nicht
gelesen. Jedenfalls bin ich bei der Delay Funktion nicht drüber
gestolpert. Sorry.
Ich habe die Funktion:
void pause(int zeit)
{
int i;
for (i = 0;i<zeit;i++)
{ _delay_us(1);}
};
nun genommen, bekomme aber immernoch falsche Zeiten. Hat wer eine Idee?
Danke
Einsteiger_ATMega16 schrieb:> Ich habe die Funktion:>> void pause(int zeit)> {> int i;> for (i = 0;i<zeit;i++)> { _delay_us(1);}> };>> nun genommen, bekomme aber immernoch falsche Zeiten. Hat wer eine Idee?
jetzt läufst du in ein anderes Problem rein.
In einem Programm ist es ja nicht so, dass nur ein _delay_us Zeit
verbraucht, sondern auch der Rest des Programmes. Solange die _delay_us
Zeiten groß gegenüber dem Rest sind, spielt das keine allzugroße Rolle.
Hier aber landest du mit 1us schon in Zeitbereichen, in denen die
komplette Schleifensteuerung zeitlich gesehen in einer ähnlichen
Größenordnung liegt, bzw. je nach Taktfrequenz sogar darüber.
d.h dein _delay_us(1) verbraucht schon 1 µs. Aber die for-Schleife
drumherum verbraucht nochmal oder gar noch mehr Zeit als diese 1us.
Und deshalb stimmen dann die Zeiten nicht.
Ist wie beim Fliegen. Der Flug München-Berlin dauert 50 Minuten. Kann
man deswegen sagen, du kannst in 50 Minuten in Berlin sein? Nein, kann
man nicht. Denn du musst erst mal zu Flughafen fahren, musst dort eine
gewisse Zeit vorher dort sein. Musst das Checkin-Procedere über dich
ergehen lassen, etc. etc. Summa summarum brauchst du daher für einen 50
Minuten Flug reale 4 Stunden.
Vielliecht verstehst du jetzt schön langsam, warum hier bei Wartezeiten
ala _delay_ms bzw _delay_us alle die Hände über dem Kopf
zusammenschlagen. Wenn die Zeiten exakt sein sollen, bzw. länger sein
sollen, ist das alles nicht zu gebrauchen. _delay_xx sieht zwar auf den
ersten Blick super einfach aus, ist es aber nicht. Wenn die tatsächliche
Wartezeit auch etwas länger sein darf UND vor allen Dingen, wenn es
nicht zu lange ist (Millisekunden Bereich), kann man es benutzen. Aber
für alles andere ist das nicht brauchbar. Da führt kein Weg an der
Benutzung eines Timers vorbei.
Peter der Großartige schrieb:> Text ist das dümmste was man machen kann, dann dann muss man auf beiden> seiten wandeln
Du schriebest Unsinn. Versuch doch bitte mal, zuerst zu denken und dann
zu schreiben.
Und unser Einsteiger_ATMega16 schrieb:> Ich übergebe vom PC aus:>> 0100001234 => Pin 0 Status 1 (High) Verzögerung 1234 us etc.>> Also:> 01000012341100001234210000123431000012344100001234>> für einen Vorgang.
Oh du Einsteiger, mach es lieber anders. Das was du da gepostet hast,
ist schlecht, weil es einfach extrem unflexibel ist. Du bist auf der
"Denkschiene" der festen Blöcke, wo alle Positionen festgelegt und starr
sind und alle Kommandos nicht atomar, sondern zusammengesetzt sind.
Jaja, man kann zwar so leben, aber besser ist es, nur atomare Kommandos
zu benutzen. Das sind welche, die nur 1 Information transportieren.
Ich geb dir mal ein Beispiel. Nehmen wir an, du brauchst im Moment 3
verschiedene Kommandos:
- Pin High setzen
- Pin Low setzen
- Verzögerungszeit vereinbaren
Dann wäre es ne günstige Sache, zuerst nen numerischen Wert (also ne
Zahl) zu schicken und dann das atomare Kommando, also eines, das
wirklich nur 1 Sache bewerkstelligt.
Beispiel:
(V setzt die Verzögerungszeit, L setzt auf Low, H setzt auf High)
1234V1H2H34H99V4L
Bedeutung:
1234V setzt die Verzögerungszeit auf 1234 us
1H setzt Pin 1 auf High
2H setzt Pin 2 auf High
34H setzt Pin 34 auf High
99V setzt die Verzögerungszeit auf 99 us
4L setzt Pin 4 auf Low
Auf diese Weise kannst du formatfrei ohne führende Nullen senden, mit
jedem Buchstaben synchronisiert sich der Kommandostrom selbst und du
kannst jederzeit noch andere Kommandos erfinden, ohne daß es die bereits
bestehenden Kommandos stört.
Mit deinem o.g. Block
01000012341100001234210000123431000012344100001234
bist du längst nicht so flexibel.
W.S.
W.S. schrieb:> Auf diese Weise kannst du formatfrei ohne führende Nullen senden, mit> jedem Buchstaben synchronisiert sich der Kommandostrom selbst und du> kannst jederzeit noch andere Kommandos erfinden, ohne daß es die bereits> bestehenden Kommandos stört.
Und ... auch nicht ganz unwichtig:
Du brauchst nur das Senden, was sich auch tatsächlich verändert.
Womit dann auch dem 'Nicht Text' Argument mehr oder weniger der Boden
unter den Füssen weggezogen wird.