Forum: Mikrocontroller und Digitale Elektronik FT232RL schluckt erstes Byte der Übertragung


von N. N. (drnicolas)


Lesenswert?

Ich übertrage von einem ATmega über den FT232 binäre Daten in Paketen zu 
14 Bytes.
Ich beobachte jetzt, daß das erste Byte jeweils verschluckt wird, es 
kommen also nur 13 Bytes (2-14) an. Das ganze egal bei welcher Baudrate. 
Die ankommenden byts sind übrigens fehlerfrei.


Besonders ulkig: Wenn ich 20 Pakete am Stück senden lasse, kommen 279 
Bytes an (20*14-1!).
Flicke ich ziwschen die Pakete delays von 100ms, dann kamen nur 260 
Bytes an - jeweils das erste Byte fehlte.

Ich vermute Probleme des Treibers - irgendwo habe ich gelesen, das USB 
oder der FT232 Probleme mit dem Übertragen kleiner Datenmengen hat, was 
isch wohl mit Treiebr-Tuning lösen liesse.

Kann jemand helfen ?

von Michael L. (michaelx)


Lesenswert?

N. N. schrieb:
> Ich übertrage von einem ATmega über den FT232 binäre Daten in Paketen zu
> 14 Bytes.
> Ich beobachte jetzt, daß das erste Byte jeweils verschluckt wird, es
> kommen also nur 13 Bytes (2-14) an. Das ganze egal bei welcher Baudrate.
> Die ankommenden byts sind übrigens fehlerfrei.
>
>
> Besonders ulkig: Wenn ich 20 Pakete am Stück senden lasse, kommen 279
> Bytes an (20*14-1!).
> Flicke ich ziwschen die Pakete delays von 100ms, dann kamen nur 260
> Bytes an - jeweils das erste Byte fehlte.
>
> Ich vermute Probleme des Treibers

Klar, es liegt natürlich immer an den Anderen!
FTDI schmeist nur so einen Schrott auf den Markt - oder was?

> - irgendwo habe ich gelesen, das USB
> oder der FT232 Probleme mit dem Übertragen kleiner Datenmengen hat, was
> isch wohl mit Treiebr-Tuning lösen liesse.

Quelle/Link? Und warum hast du es nicht probiert?

> Kann jemand helfen ?

Leider nicht. Du hältst dich ja für fehlerfrei, darum ist es auch nicht 
nötig, dass du deinen Quellcode postest!

von Reinhold_B (Gast)


Lesenswert?

Hallo drnicolas,
um das systematisch einzugrenzen würde ich mit Testcode nur 1 Byte 
senden, unbedingt ein Druckbares (ASCII 'A' z.B.) alle 100ms oder noch 
seltener (1/sec).
Als Empfangssw KEINE eigene sondern ein Terminalprogramm (notfalls 
Hyperterminal).
Baudrateneinstellung prüfen ob korrekt und dann los.
Vielleicht werden ja nur bestimmte Zeichen verschluckt (Schnittstelle im 
Binarymode öffnen!), mit anderen Zeichen probieren ( einfach 0x00 bis 
0xFF durchgehen lassen). Sollte bei öffnen im Binarymode NICHT 
passieren.
Mit dem Oszi/Logicanalysator (sofern vorhanden) Das Byte prüfen ob es 
korrekt aufgebaut ist (Startbit,Daten,Stoppbit), damit klar ist dass 
nicht deine HW/SW die Ursache ist.
Erst kürzlich hat einer meiner jüngeren Kollegen aus NichtWissen und 
nichtFragen eine RS232 falsch rum gepolt betrieben und sich gewundert 
das nicht alles ankam.
Generell gilt nämlich für alle mir bekannten Controller: Das Signal am 
Controller-Pin ist negiert gg. dem Signalpegel auf der RS232-Leitung 
(weil die alten 75188/75189 RS232-Treiber negierend waren, MAX232&co 
haben das beibehalten).
Für das alles braucht man deinen Code erstmal nicht :-)

Ich kann mich noch gut erinnern, in den 90ern musste ich einen DOS 
Gerätetreiber bauen. Gab Probleme, letztlich war die Ursache wirklich 
das MS-DOS 5.0 selbst. Es hatte vom Programm übergebene Bytes !manchmal! 
nicht an den Gerätetreiber weitergegeben. Letztlich haben wir damals 
einen Workaround gemacht, weil die eigentliche Ursache nicht korrigiert 
werden konnte.

Zurück zu deinem Problem: Erst wenn das übertragen einzelner Bytes ohne 
Fehler klappt, dann erst auf die gewünschte Blocklänge gehen, und 
schauen was ankommt. Hier erst kommen dann Interrupt und ggf. 
Timingprobleme dazu wenn es dann nicht klappt.
Wenn du auf dem PC eigene SW hast, bau dir einen Debugmode ein der die 
empfangenen Bytes direkt anzeigt oder in eine Logdatei schreibt, bevor 
irgendeine Weiterverarbeitung passiert. RS232 kann man übrigens 
problemlos anzapfen (also die Datenleitung an einen zweiten EIngang 
legen wo eine Terminal-SW mithorcht), Treiberleistung, Eingangsimpedanz 
sind hier noch unkritisch.

Viel Erfolg mit dem Projekt!

von Michael L. (michaelx)


Lesenswert?

Hannes schrieb im Beitrag #2975409:
> @Michael L.
>
> Nun komm mal wieder runter...wenn Du nicht helfen willst, spar Dir solch
> blöde Kommentare.

OK, das hat dem TO jetzt aber ganz bestimmt geholfen. ;-)

> Warum bist Du so aggressiv?

Muss man jetzt schon Sarkasmus erklären?

BTW: Wenn man fragt, bekommt man nicht immer die Antworten, welche man 
erwartet. Das wiederum liegt so gut wie immer an der Fragestellung.

http://www.tty1.net/smart-questions_de.html

Wer etwas zusammenfrickelt, sollte nicht vorschnell die Fehler auf 
Andere schieben. Schon gar nicht auf Basis von Vermutungen, oder weil 
man glaubt, mal irgendwo irgendwas gelesen zu haben. Und mehr als eine 
vage verbale Beschreibung hat der TO nicht geliefert.

> Hat Dich Frauchen nicht gut behandelt?

Ich werde von ihr immer gut behandelt. Nur den Ausdruck "Frauchen" kann 
sie nicht ausstehen, schließlich ist sie erwachsen. Da hättest du dir im 
RL wohl mindestens einen blöden Spruch eingefangen. :-D

@drnicolas
Bitte mehr Informationen und systematisches Vorgehen, wenn du Hilfe 
suchst.

von kukuk (Gast)


Lesenswert?

...wenn man ohne Interrupt arbeitet passiert so etwas oefters

von el gasto (Gast)


Lesenswert?

Michael L. schrieb:

>
> Ich werde von ihr immer gut behandelt. Nur den Ausdruck "Frauchen" kann
> sie nicht ausstehen, schließlich ist sie erwachsen. Da hättest du dir im
> RL wohl mindestens einen blöden Spruch eingefangen. :-D

Also die paar RL, die ich hier im hohen Norden kenne, sind alle 
unsympathisch, da hilft wohl auch kein Umzug.

von N. N. (drnicolas)


Lesenswert?

Das Rätsel ist gelöst.

Es lag daran, daß ich zuerst UDRIE enabled habe und DANACH in UDR die 
Daten schreibe.
Jetz funktioniert es.

trotzdem lohnt es sich mit den Timeouts des Treiebrs zu experimentieren. 
Wenn man von 0 auf z.B 200ms umstellt, dann kommen die Daten zwar 
vollständig aber etwas abgehackt.

von Falk B. (falk)


Lesenswert?

@  N. N. (drnicolas)

>Es lag daran, daß ich zuerst UDRIE enabled habe und DANACH in UDR die
>Daten schreibe.
>Jetz funktioniert es.

Wirklich? Poste Code als Anhang. Wahrscheinlich ist der Bug nur 
kaschiert.

>trotzdem lohnt es sich mit den Timeouts des Treiebrs zu experimentieren.

Aber nur, wenn man weiß was man tut.

>Wenn man von 0 auf z.B 200ms umstellt, dann kommen die Daten zwar
>vollständig aber etwas abgehackt.

Was mal nicht im Sinn des Erfinders ist. Der FT232 läuft ziemlich gut, 
auch mit Standardeinstellungen.

von N. N. (drnicolas)


Lesenswert?

Mit abgehackt meine ich, daß die Pakete nicht mit Abstand kommen, 
sondern u.U. 3 oder 4 Pakete auf einmal, dafür mit grösserem Abstand.

Sieht im besten Falle unschön aus, wenn vom µC die Angaben eines 
Drehencoders nicht gleichmässig kommen.

Aber trotzdem: in einem englischsprachigen Forum wurde ich schon schief 
angemacht ob meiner Übertragunsgmethode. Vielleicht bin ich ja 
tatsächlich komplett auf dem Holzweg.

Hier kommt mal ein Code-Auschnitt:
1
void UARTRingbuffer_TX_CheckStart(void)
2
{
3
  if((UART_TX_Control.QueueRunning==0) && (RTS_LINE_FT232R==USART_READY) && 
4
    (UART_TX_Control.BufferBytesRemaining!=UART_TX_QUEUESIZE*sizeof(struct UART_Message)))
5
  { //Übetragung anstossen ....
6
      UART_TX_Control.QueueRunning=-1; //die Übetragung läuft jetzt formal
7
    #ifdef __AVR_AT90CAN128__
8
      //UCSR1A |= (1<<UDRE1);  //Flag UDRE löschen
9
      volatile uint8_t tmp_char=*UART_TX_Control.READ_Pointer;
10
      UDR1=tmp_char;  //Datenbyte in das Register UDR1 schreiben 
11
      UCSR1B = UCSR1B | (1<<UDRIE1);    // Interrupt freigeben
12
                  //...danach werden die restlichen Bytes werden durch Interupt 
13
                  //gesendet.
14
                  // Der Pointer wird erst NACH erfolgreichem Senden erhöht
15
  
16
      
17
    #elif __AVR_ATmega32__
18
        UDR=*UART_TX_Control.READ_Pointer;  //Daten in temp. register laden
19
        UCSRB = UCSRB |  (1<<UDRIE1);
20
    #endif
21
  } //if
22
} //end UARTRingBuffer_TX_CheckStart

Und jetzt noch die IRQ-Routine ...
1
/* Die nachfolgende Interruptroutine wird immer dann aufgerufen, wenn UDRE eintritt, d.h.
2
  UDR ist leer, resp. das nächste Byte kann gesendet werden */
3
#ifdef __AVR_AT90CAN128__
4
ISR(USART1_UDRE_vect)
5
#endif
6
7
#ifdef __AVR_ATmega32__
8
ISR(USART_UDRE_vect)
9
#endif
10
{ 
11
#ifdef UART_DEBUG
12
  UARTRingTracker.TX_ByteCount++;  //nur für Überwachungszwecke !!
13
#endif
14
  
15
  UART_TX_Control.BufferBytesRemaining++; //Zeichen erfolgreich gesendet
16
  UART_TX_Control.READ_Pointer++;  //Pointer um eins erhöhen ...
17
  
18
  //... den Pointer ggf. auf Anfang setzen
19
  if(UART_TX_Control.READ_Pointer>= ((unsigned char *) &UART_TX+UART_TX_QUEUESIZE*sizeof(struct UART_Message))) 
20
  {
21
    UART_TX_Control.READ_Pointer=(unsigned char *) &UART_TX;
22
  }  
23
  
24
  if(UART_TX_Control.BufferBytesRemaining<UART_TX_QUEUESIZE*sizeof(struct UART_Message))
25
  {  // Es sind noch Zeichen übrig in der Queue
26
    if((RTS_LINE_FT232R==USART_READY))
27
    {  //Gegenseite empfangsbereit
28
      // es !dürfen! weitere Zeichen gesendet werden ...
29
    #ifdef __AVR_AT90CAN128__      
30
      UDR1=*UART_TX_Control.READ_Pointer;  //Datenbyte in das Register UDR1 schreiben
31
    #elif defined __AVR_ATmega32__
32
      UDR=*UART_TX_Control.READ_Pointer;      
33
    #endif
34
    }
35
    else
36
    {  //Gegenseite *NICHT* empfangsbereit !
37
      //vorerst die Übetragung beenden. Der Marker für 
38
    #ifdef __AVR_AT90CAN128__
39
      CLEARBIT(UCSR1B,UDRIE1);  //Interrupt löschen
40
    #elif defined __AVR_ATmega32__      
41
      CLEARBIT(UCSRB,UDRIE);      
42
    #endif  
43
      UART_TX_Control.QueueRunning=0;  // Übetragung ist offiziell beendet (?)
44
    
45
    }
46
    return;  //Interrupt bleibt aktiviert ... weitere Zeichen folgen
47
  }
48
  else
49
  {  //andernfalls -> aktuelles Paket ist komplett gesendet !
50
#ifdef __AVR_AT90CAN128__
51
    CLEARBIT(UCSR1B,UDRIE1);  //Interrupt löschen
52
#elif defined __AVR_ATmega32__      
53
    CLEARBIT(UCSRB,UDRIE);      
54
#endif
55
    UART_TX_Control.QueueRunning=0;  // Übetragung ist offiziell beendet
56
    
57
  #ifdef UART_DEBUG
58
    UARTRingTracker.TX_PacketCounter++;  //Zähler für vollständig gesendete Pakete erhöhen
59
  #endif
60
  }
61
} // Ende SIGNAL(...)

von g457 (Gast)


Lesenswert?

> in einem englischsprachigen Forum wurde ich schon schief angemacht ob
> meiner Übertragunsgmethode. Vielleicht bin ich ja tatsächlich komplett
> auf dem Holzweg.

Schief anmachen würde ich das [0] nicht nennen. Und komplett auf dem 
Holzweg bist Du auch nicht, aber es ist unnötig kompliziert. Das macht 
zukünftige Wartung nicht unbedingt einfacher.

[0]
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=1023088

von Michael L. (michaelx)


Lesenswert?

N. N. schrieb:
> ... Vielleicht bin ich ja
> tatsächlich komplett auf dem Holzweg.

Ich habe jetzt nicht den ganzen Code durchdrungen, aber ich glaube dass 
du in der ISR Zeichen verlierst, wenn die Gegenseite gerade nicht 
empfangsbereit ist. Oder verwirfst du etwa den Puffer im Ganzen? Das 
wiederum wäre ja nicht unbedingt nötig, weil RTS/CTS ja "nur" das 
Hardware-Handshake ist. Es scheint aber, als würdest du es im Sinne von 
DTR/DSR (Anzeige der Betriebsbereitschaft, d.h. überhaupt erst mal eine 
Gegenstelle "da") behandeln. Eine "Umdeutung" der Signale ist in 
gewissen Grenzen sicherlich möglich, und auch Wurscht, solange du 
zwischen zwei selbst gebauten Geräten überträgst. Aber wenn du eine 
Gegenstelle nach Standard hast, kann das auch zu scheinbar 
unerklärlichem Verhalten.

Grüße.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.