PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Kommunikation über UART und FIFO benötigt delay



sast
27.02.2009, 10:37
Ich verwende schon seit längerem die UART Funktionen aus dem Wiki und hatte bisher auch noch nie Probleme, da ich nie mehr als 8 Zeichen gesendet habe um zwischen den Kontrollern zu kommunizieren. Nun hab ich mal bei einem Versuchsaufbau ( will mich an die SPI Schnittstelle wagen) ein Hallo Welt an den Kontroller vom PC aus geschickt.
War auch ok da ich wie im unten stehenden Code für den Empfang ein delay(100) drin hab. Welches nur ein Rudiment aus irgend einem Test war.

Gesendet habe ich :owHallo Welt!



int main( void )
{
char c;
char text[32];
char tag[3];
int i;

initio();
initspi();

ser_init();
sei();
tag[0]=CONTROLLER_TAG;//':'
tag[1]=CONTROLLER_ID;//'o'
tag[2]=0;

while (1)
{
if (ser_chars_present())
{
i=0;
do
{
c = ser_getc_nowait();
text[i++]=c;
} while(ser_chars_present());
text[i]='\0';
delay_ms(100);
if(((i<31) && (strlen(text)<3)) && (ser_chars_present()))
{
do
{
c = ser_getc_nowait();
text[i++]=c;
} while(ser_chars_present());
text[i]='\0';
}
if((strlen(text)>2) && (!strncmp(text, tag, 2)))
{
if(!execution_of_the_order(text[2], text))
{
ser_puts(CONTROLLER_FAIL);
}
}
else
{
//geht uns nichts an
}
}
}
}

Dadurch entsteht aber eine ziemlich große Pause bis die Antwort vom Kontroller kommt.


char execution_of_the_order(char order, char* message)
{
char s[32];
int a;

a=0;
while(a<3)
{
message++;
a++;
}
strncpy(s, message, 32);

if(order=='a')
{
ser_puts(CONTROLLER_RESPONSE);
return 1;
}
if(order=='b')
{
ser_puts(CONTROLLER_NAME);
return 1;
}
if(order=='w')
{
SpiSendString(s);
ser_puts(s);
return 1;
}
if(order=='r')
{
ser_puts(CONTROLLER_RESET);
bootloader();
return 1;
}
return 0;
}

Habe also mal das delay auf 10 runtergesetzt, unter der Annahme, dass man das gar nicht benötigt und siehe, da kommt das raus, was ich mal als Bild versuche anzuhängen.

Kann mir das einer erklären? Es ist auch reproduzierbar immer Hallo W was da als Antwort kommt.

sast

EDIT: Habs wieder mal zu schnell hier eingestellt.
Die Abarbeitung ist natürlich viel schneller als die Daten, welche mit 9600Baud eintrudeln. Werde einfach nach jedem empfangenen Byte eine von Baudrate und Sysclk abhängige Wartezeit einbauen. Das ist dann immer noch kürzer als einfach mal so 100ms zu warten.
Oder hat jemand eine effizientere Idee?

sternst
27.02.2009, 13:16
Sowas geht natürlich auch ganz ohne irgendwelchen Delays.
Pseudocode:

do {

if (Zeichen_da)
Zeichen_eintragen;

} while (noch_nicht_alle_Zeichen_da);

sast
27.02.2009, 13:27
Woher weiß der Kontroller denn wann alle Zeichen da sind? Es gibt keine Endekennung. Und es soll flexibel einsetzbar sein.

sast

sternst
27.02.2009, 13:37
Ohne ein Framing geht es nun mal nicht (auch nicht mit irgendeiner Delay-Lösung).

sast
27.02.2009, 13:48
Es ist in einer Master Slave Lösung eingebunden.
Dadurch wird immer nur ein Kontroller (Slave) angesprochen.
Wenn er keine Zeichen mehr bekommt, kann er davon ausgehen, dass die Übertragung beendet ist. Deshalb würde es theoretisch reichen, wenn er noch ein bis zwei Zeichenlängen wartet ob noch was kommt und dann die Abarbeitung startet. Der Master bekommt dann auch immer eine Bestätigung nach getaner Arbeit des Slaves oder läuft in ein timeout.
Bisher hat das so immer ganz gut funktioniert.

sast

sternst
27.02.2009, 14:06
Es gibt keine Endekennung.

Wenn er keine Zeichen mehr bekommt, kann er davon ausgehen, dass die Übertragung beendet ist.
Also gibt es doch eine Endekennung, nämlich in Form einer Sendepause. ;-)
Dann würde ich in die Schleife einen Timeout auf der Basis eines Timer-Interrupts mit rein nehmen.

sast
27.02.2009, 14:34
klingt annehmbar. Zur Zeit sind pro empfangenen Zeichen 2ms delay drin. Das verlängert die Zeit vom letzten empfangenen Zeichen bis zum Beginn der Abarbeitung auf nicht ganz das Doppelte. Ist aber immer noch viel weniger als die 100ms.
Im Normalfall hatte ich auch nie mehr als 8 Zeichen und da wäre nach ca 16ms schon die Abarbeitung dran.
Aber das mit dem Timer timeout machts universeller.

Danke fürs Mitdenken!

<offtopic>
Mal was ganz anderes, wozu ist denn der blaue Button bei jedem Beitrag?
</offtopic>

sast

PicNick
27.02.2009, 16:30
Der Butten sendet dem zuständigen Moderator eine Nachricht, das der angeklickte Post vermutlich irgendeine böse Schweinerei enthält. :mrgreen:
In diesem Fall bin das ich. Was steht zu Diensten ?

sast
27.02.2009, 16:57
Wollte das nur mal wissen, weil ich bei nem anderen Posting mal auf diesen Knopf gedrückt hatte und das war danach auch weg
Da hatte ich mal versucht einen Tip in Bascom zu geben und war mir dann aber nicht mehr sicher ob ich nicht Blödsinn erzähle und da wollte ich es wieder weg haben. Es hat sich rausgestellt, das es sogar richtig gewesen wäre

sast