Problem mit serieller Schnittstelle!

Puchti

Grünschnabel
Also,
ich bin sozusagen nur ein Gelegenheitsprogrammierer und auch nicht wirklich gut.
Daher habe ich so meine Probleme, aber mit dem Folgenden komme ich wirklich nicht mehr weiter (Ich muss ein wenig ausholen, um die Sache verständlich zu machen):

Es geht um ein DMatrix-Display der Firma Mitex, welches über den RS232C Port bedient werden kann. Das geht wie folgt:

Code:
Beispiel
Anfrage an das Display: 0xA000011A; //Funktionscode A0, Payload 0001, Checksum 1A
Antwort vom Display: 0xA00A; //Funktionscode A0, Checksum 0A

Anfrage an das Display: 0xB40A0211223F; //Funktionscode A0, Payload 0A021122, Checksum 3F
Antwort vom Display: 0xB44B; //Funktionscode B4, Checksum 4B

Antwort des Display bei Fehler (oder fehlerhafte Checksum): 0x400004;

Wie die Befehle hier zustande kommen hat erstmal nix mit dem Problem zutun.
Die Checksum ist die Summe aller Bytes, nibble weise gedreht.

Das Display als solches ist über einen USB zu Seriell Wandler (PL2303) an eine Fritz Box angeschlossen. Auf dieser läuft ein Linux; Prozessorarchitektur ist Mips32.

Mein Programm zur Ansteuerung der Anzeige ist in C geschrieben und mit einem Cross-Compiler für diese Architektur übersetzt. Dieser Cross-Compiler läuft auf Linux in einer VM (VMware) unter Windows als Hostsystem.

Statt das Programm mit dem Cross-Compiler zu übersetzen, nutze ich zum testen auch mal gcc, um das Programm für das Linux in der VM zu übersetzen.
Dann schließe ich das Display mitsamt USB zu Seriell Wandler an den Windowsrechner an.
Ich starte mein Programm in der VM und voilà- es funktioniert tadellos. D.h. es wird angezeigt, was ich wollte und die Antworten des Displays sind auch richtig.

DAS PROBLEM:

Nun fix das Programm für Mips32 übersezt und auf die FritzBox gespielt- Display anschließen und...

Ja der 1. Befehl, den ich sende wird öfter nicht ausgeführt- dabei IMMER keine Antwort vom Display.
Die nächsten Befehle, die ich sende werden fast immer ausgeführt, nur die Antworten des Displays sind murx:

Code:
1. Anfrage an das Display: 0xA0...; //Funktionscode A0...
erwartete Antwort vom Display: 0xA00A; //Funktionscode A0, Checksum 0A
echte Antwort vom Display: KEINE;
Ausgeführt: MANCHMAL;

2. Anfrage an das Display: 0xB1...; //Funktionscode B1...
erwartete Antwort vom Display: 0xB11B; //Funktionscode B1, Checksum 1B
echte Antwort vom Display: 200A;
Ausgeführt: JA;

3. Anfrage an das Display: 0xA4...; //Funktionscode A4...
erwartete Antwort vom Display: 0xA44A; //Funktionscode A4, Checksum 4A
echte Antwort vom Display: 311B;
Ausgeführt: JA;

4. Anfrage an das Display: 0xA4...; //Funktionscode A4...
erwartete Antwort vom Display: 0xA44A; //Funktionscode A4, Checksum 4A
echte Antwort vom Display: 244A;
Ausgeführt: JA;

Die letzte Antwort wiederholt sich, wenn ich immer wieder Funktionscode A4 aufrufe.

Es schein also so zu sein, als ob immer die Antwort des vorhergehenden Befehles ankommt. Dabei ist er aber auch so verstümmelt, das die ersten 2 bits des höherwertigen Nibble auf 00 gesetzt sind.

Beispiel siehe Anfrage 3:
Antwort war 0x311B, also 11000100011011;
Antwort auf vorhergehenden Befehl hätte sein müssen: B11B, also 1011000100011011;
-> Es fehlen also die ersten zwei bit und die Antworten kommen zum falschen Zeitpunkt.

WORAN ES NICHT LIEGT:

1. Meine Befehle sind korrekt!
2. Die Fritz Box.
Habe das Programm auch für i386 Linux übersetzt und auf einem Debian System ausgeführt. keine VM. Dennoch gleicher Fehler wie auf der FritzBox.
3. Der USB zu Seriell Wandler.
Das Programm lief in der Linux-VM tadellos auch mit USB Wandler.
Habe es auch am "echten" seriellen port mit Cross-Kabel versucht. Kein Unterschied.
Der Adapter verhält sich wirklich transparent.

ANFORDERUNGEN DES DISPLAY AN DIE VERBINDUNG LAUT HANDBUCH

1. Nur RxD, TxD und GND sind überhaupt beschalten.
2. 9600 Baud
3. 1 Start-, 8 Daten-, 1 Stoppbit
4. even parity

MEIN CODE UM DIESE EINSTELLUNGEN VORZUNEHMEN

Code:
void open_port(void)
	{
	struct termios options;
	
	
	fd = open(PORT, O_RDWR | O_NOCTTY | O_NDELAY);
	if (fd == -1) perror("open_port(): Unable to open Port\n");
	else fcntl(fd, F_SETFL, 0);
	
	tcgetattr(fd, &options); /* Get the current options for the port... */

	cfsetispeed(&options, B9600);				/* Input speed */
	cfsetospeed(&options, B9600);				/* Output speed */
	options.c_cflag |= (CLOCAL | CREAD);			/* local mode and receiver enable */
	options.c_cflag |= PARENB;				/* set parity */
	options.c_cflag &= ~PARODD;				/* parity even */
	options.c_cflag &= ~CSTOPB;				/* 1 Stopbit */
	options.c_cflag &= ~CSIZE;				/* Mask the character size bits */
	options.c_cflag |= CS8;					/* 8 data bits */
	options.c_cflag &= ~CRTSCTS;   	 			/* Disable hardware flow control*/
	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);	/* Raw input mode */
	options.c_iflag |=  (INPCK |ISTRIP);			/* Input parity checking and stripping */
	options.c_iflag &= ~(IXON | IXOFF | IXANY);		/* Disable software flow control */
	options.c_oflag &= ~OPOST;				/* Raw output mode */
	options.c_cc[VMIN]  = 0;				/* Number of char to wait for */
	options.c_cc[VTIME] = 0;				/* Timeout 1st char in tenths of seconds */

	tcflush(fd, TCIFLUSH);	/*should flush the buffer */
	tcsetattr(fd, TCSANOW, &options); /* Set the current options for the port... */
	}

MEIN CODE UM DATEN ZU SENDEN UND ZU EMPFANGEN

Code:
unsigned int hmuch, i;
unsigned char answer[255];
...
write(fd, command, lengh);
...
hmuch=read(fd, &answer, sizeof(answer));
if (hmuch <= 0) printf("send_command(): No answer from display\n");
else {
	printf("Answer: ");
	for(i=0;i<hmuch;i++)
		{
		printf("%.2X",answer[i]);
		}
	printf("\n");
	}
...

So das war viel Text. Aber ich hoffe jemand hat hier eine Idee?
Danke schon mal im voraus
 

Neue Beiträge

Zurück