hallo alle zusammen!
1.: avr studio 4.14, ATmega128, in C
bräucht ma wieder rat und beistand wegen folgendem problem:
ich sitz an ner empfangsroutine für ein rs485 bus, welche auf anfrage
vom master den messwert von nem sensor berechnet und an den master
sendet:
1 | ISR (SIG_UART1_RECV)
| 2 | {
| 3 | cli();
| 4 | temp_str1 = USART_Receive1();
| 5 | if (temp_str1 == 0x03) {
| 6 | temp_str2 = USART_Receive1();
| 7 | temp_str3 = USART_Receive1();
| 8 |
| 9 | messen();
| 10 |
| 11 | if (erg2>9.99){
| 12 | dtostrf(erg2,1,1,puffer);}
| 13 | //printf(puffer,"err");}
| 14 | else if (erg2<=9.99) {dtostrf(erg2,1,2,puffer);}
| 15 |
| 16 | len = strlen(puffer);
| 17 |
| 18 | switch(temp_str3)
| 19 | {
| 20 | case 0x05 : USART_Transmit1(len);USART_Puts1(puffer);break;
| 21 | case 0x04 : PORTB = 0b11100111;break;
| 22 | }
| 23 | }
| 24 | sei();
| 25 | }
|
Dieser Interrupt wird ausgelöst, 3 bytes empfangen
(adresse,status,status), bei korrekter adresse die funktion messen();
aufgerufen, umgewandelt und zurückgesendet.
wenn ich den code wie oben nicht verändere funktioniert er eig bis auf
wenige messwerte, aber er funkioniert...
der fehler tritt dann auf (was ich wieder total nicht verstehen kann),
wenn ich
dtostrf(erg2,1,1,puffer);
durch
printf(puffer,"err");
oder
die isr einfach nur umschreiben möchte. und zwar bekomm ich dann nur
noch ein "er" statt "err" und als messwert eine kommastelle zu wenig
aber dafür ein "y","ö" oder "ü" also nicht mehr "5,67" sondern "5,6y"
oder auch gerne nur "5,6 "!
da ich mir sicher bin, das die rs232 verbindung fehlerfrei läuft und
allein der befehl printf die übertragung stört, bin ich völlig ratlos
woran es hängen könnte!jegliche kleine änderung verursacht fehler bei
der übertragung... :-(
wär froh, wenn mir einer sagen könnte, wie der hase zu laufen hat^^
mfg keniff
Ich rate mal.
puffer ist als
char puffer[3];
definiert?
Noch ein Hinweis: die erste Zahl bei dtostrf ist die Gesamtzahl an zu
benutzenden Stellen (die Feldbreite). Dies beinhaltet ein eventuelles
Vorzeichen und auch den Kommapunkt.
Eine Angabe von 1, 1 ist daher sinnlos. Du willst eine Kommazahl in
einem Feld der Breite 1 (inkl Vorzeichen und Kommapunkt) unterbringen
UND das Ganze dann auch noch mit 1 Nachkommastelle.
Für eine Ausgabe von 5.2 benötigst du eine Feldbreite von 3 (1
Vorkommastelle, 1 Dezimalpunkt, 1 Nachkommastelle = 1 + 1 + 1 = 3). Das
empfangende char-Array muss aber dann mindestens eine Länge von 4 haben
(wegen des obligaten '\0' Zeichens am String-Ende)
Aber vorsicht: dtostrf kann deine erste Angabe (die Feldbreite)
ignorieren, wenn es ansonsten die Zahl nicht unterbringen kann. Dadurch
ist es unklug, den Ausgabepuffer ganz knapp zu dimensionieren. Array
Overflows sind die Folge mit den typischen Folgen wie du sie
beschreibst.
Edit:
printf(puffer,"err");
macht auch keinen Sinn. Wenn schon, dann sprintf. Und um den Text "err"
dort unterbringen zu können, muss puffer mindestens eine Länge von 4
haben.
hey karl-heinz,
du schon wieder! ;-) freut mich!
ehm nein^^, puffer is [10]
der befehl dtostrf is mir noch bissel neu, da werd ich nochma schaun,
aber an dem liegts ja nicht unbedingt...
habs auch schon mit sprintf, strcpy oder sonstigem probiert...
selbst wenn ich ein def. string verschicken möchte aber die
sprintf-zeile benutze, hab ich den selben fehler...
eig kann ich nicht den kompl code posten, aber denk auf rate spielchen
hat hier keiner lust! aber bitte nicht köpfen, wenn nicht alles 1A
C-Syntax is ;-)
mfg keniff
Hmm.
Was mir mal überhaupt nicht gefällt ist, dass du die Empfangerei in eine
ISR gelegt hast. ISR mit Warten auf Ereignisse ist meistens keine gute
Idee. Zumindest solltest du den cli() und sei() da rauswerfen. Sowas hat
in einer ISR nichts verloren.
Welche UART Funktionen benutzt du, was machen die?
Edit:
Meist ist es eine gute Idee, explizit zu sein. Manchmal ist es das aber
nicht. Das hier 1 | if (erg2>9.99){
| 2 | dtostrf(erg2,1,1,puffer);}
| 3 | //printf(puffer,"err");}
| 4 | else if (erg2<=9.99) {dtostrf(erg2,1,2,puffer);}
| 5 | //sprintf(puffer,"%f",a);
|
scheint mir ein Fall für "es ist keine gute Idee" zu sein.
Wenn eine Zahl nicht kleiner als 9.99 ist, dann muss sie größer oder
gleich 9.99 sein. Es gibt keine andere Möglichkeit
1 | if( erg2 > 9.99 )
| 2 | dtostrf( erg2, 4, 1, puffer);
| 3 | else
| 4 | dtostrf( erg2, 4, 2, puffer );
|
PS: Der Code ist durch die vielen Auskommentierungen sehr schlecht zu
lesen. Der Fehler an den ich ursprünglich dachte, liegt allerdings nicht
vor. Die Ausgabepuffer sind gross genug dimensioniert.
ich weiss, ich sollte die ISR so kurz wie möglich halten, aber auch das
auslagern des codes in eine extra-funktion bringt kein unterschied...
benutz usart-routinen, welche aber denk standard sind?! (anhang)
steh echt vorm berg...
hoff du siehst vllt, was da schief läuft!
Martin S. wrote:
> ich weiss, ich sollte die ISR so kurz wie möglich halten, aber auch das
> auslagern des codes in eine extra-funktion bringt kein unterschied...
Darum gehts nicht. Mit 'so kurz wie möglich' meint man nicht Codegröße
sondern wie lange die Interrupts gesperrt sind. In deiner ISR sind die
Interrupts sehr, sehr lange gesperrt. Nämlich solange wie es dauert 3
Bytes zu empfangen, zu messen und das Ergebnis auf den Weg zu bringen.
Auf der anderen Seite macht deine Hauptschleife gar nichts. Da wäre
vieles gut aufgehoben.
denkst du, da liegt der hund begraben? also, dass durch falschen aufbau
vom main/isr usw, das programm irgendwann aussetzt?
hmm, wenn das was bringt mach ichs gern ^^
was mich aber bischen wundert, da der µC als slave eig eh nichts andres
zu tun hat, als die isr abzuarbeiten.
bei dem >9,99 fehlt eig auch noch die abfrage <0,00 , aber das waren
alles mehr spielereien, und auch nicht wirklich überlegt...
das problem ist halt eher das oben genannte. hab dich ja vorgewarnt,
dass es manchma recht verwurstelt is.
kann es sein, dass µC-programmierung manchma was von zauberei hat??? ;-)
verstehs grad echt net
Martin S. wrote:
> denkst du, da liegt der hund begraben? also, dass durch falschen aufbau
> vom main/isr usw, das programm irgendwann aussetzt?
Ich weiß es nicht.
Ich seh im Moment eigentlich kein offensichtliches Problem mehr.
Ich würds auf jeden Fall mal machen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|