Page 1 of 1

Serielle Schnittstelle - Burst einlesen

Posted: 21. Nov 2007 13:12
by TS-Tec
Hallo!

Ich ein Microcontroller der mir auf einen Befehl über die serielle Schnittstelle sofort eine Antwort zurück sendet.
Dies möchte ich in ein C-Programm einbinden. Das senden der Zeichen klappt auch gut, nur die Antwort wird nicht korrekt dargestellt. Wenn ich das ganze über ein Terminal-Programm simuiliere, also die Antwort Zeichen für Zeichen eingebe und mir \r abschließe, klappt alles wunderbar.
Die Sache ist aber scheinbar die, das der Controller einen Burst schickt. Obwohl am Ende auch ein \r [ASCII 13] kommt erkennt mein Programm das nicht. Auch die Ausgabe ist sehr seltsam. Es scheint eine Überlagerung der aktuellen mit vorherigen Antworten zu sein. Manchmal kommt die Antwort nur bruchstückhaft, manchmal mehrfach.
Wie muss ich den Port konfigurieren, um einen Burst korrekt einlesen zu können?

Hier mein Code:

Code: Select all

	/* Öffnet den übergebenen Port und liefert den zugehörigen File-Descriptor zurück. -1 = Fehler*/
    int open_port(char Port[])
    { 		
    	int fd;
    	fd = open(Port, O_RDWR);
    	fcntl(fd, F_SETFL, 0);
    	
    	/*TODO Unterschied TCU/NFC-Portsettintgs proggen*/
    	tcgetattr(fd,&oldtio); /* save current port settings */
    	
    	return (fd);
    }
    
    
    /* Stellt die Portparameter für einen übergenen File-Descriptor ein. -1 = Fehler */
    int setPortParam(int fd)
    {
    	
    	struct termios term_attr;
    	
    	if (tcgetattr(fd, &term_attr) != 0)
    	{
    	    perror("terminal: tcgetattr() failed");
    	    return(-1);
    	}
    	
    	
    	
    	
    	bzero(&term_attr, sizeof(term_attr));
    	term_attr.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
    	term_attr.c_iflag = IGNPAR | ICRNL;
    	term_attr.c_oflag = 0;//OPOST; //| ONLCR | OCRNL;
    	term_attr.c_lflag = 0;
    	term_attr.c_cc[VTIME]    = 0;   /* inter-character timer unused */
    	//printf("setting flags");
    	term_attr.c_cc[VMIN]     = 0;   /* blocking read until 8 chars received */
    	
        tcflush(fd, TCIFLUSH);
       	if (tcsetattr(fd, TCSANOW, &term_attr) != 0)
    	{
    		perror("terminal: tcsetattr() failed");
    		return -1;
    	}
    	
    	return 1;
    }
    
    void closePort(int fd){
    	printf("Closing Port");
    	tcsetattr(fd,TCSANOW,&oldtio);
    	close(fd);
    	
    }
    
    /*TODO Funktion WriteToPort programmieren!*/
    void WriteToPort(int fd){
   
    char buffer[255] = "";    
    
    int n = write(fd, "0av\r", 3);
    if &#40;n < 0&#41;
    fputs&#40;"write&#40;&#41; of 4 bytes failed!\n", stderr&#41;;
    while &#40;STOP==FALSE&#41; &#123;       /* loop for input */
             read&#40;fd,buffer,64&#41;;   /* returns after 5 chars have been input */
             printf&#40;"%s", buffer&#41;;
             if &#40;buffer&#91;0&#93;==10&#41; STOP=TRUE;
    		 &#125;

    closePort&#40;fd&#41;;
    &#125;

Posted: 22. Nov 2007 22:26
by Janka
Vermutlich sendet dein Controller immer, auch wenn der PC gar nichts verarbeiten kann -- der hat nämlich nur 16 Byte Puffer, und dann muss die Interruptroutine des Porttreibers eingegangene Zeichen erstmal wegarbeiten.

Du brauchst Flusskontrolle. Entweder dein Controller kann XON/XOFF, dann musst du mit tcsetattr() zusätzlich das Flag IXOFF setzen, oder dein Controller kann RTS/CTS, dann musst du eine mindestens 4-adrige Leitung verwenden (RTS am PC mit CTS am Controller verbinden) und der serielle Port wird dem Controller automatisch "Stop" signalisieren, sobald der Puffer kurz vor voll ist.

Janka

Posted: 04. Dec 2007 14:16
by TS-Tec
Mhh ich habe beides ausprobiert... ohne Erfolg!
Es hat sicher irgendetwas mit dem Puffer zu tun.
Wenn eine sehr lange Antwort kommt (ca. 1000 Zeichen) dann kommt beim Aufruf von read() nur ein Teil an. Der Rest kommt beim nächten Afruf von read() und vermischt sich mit der neuen Antwort (da ja inzwischen ein weiterer Befehl mit write()N gesendet wurde).
Was kann ich gegen dieses Phänomen tun? Den Eingangspuffer vergrößern???

Posted: 05. Dec 2007 15:41
by Janka
Der 16-Byte-Eingangspuffer ist Hardware. Wenn der Controller nicht auf Handshake-Signale reagiert, ist dessen Firmware *Mist* und gehört korrigiert.

Janka