LED-Cube // Problem mit COM-Port
-
Hi,
ich bin neu hier in diesem Forum und hätte gleich mal ein Problem. Erst mal vorneweg: Ich hab leider (noch) nicht wirklich viel Ahnung von C, und ich hoffe, ihr könnt mir weiterhelfen.
Mein derzeitiges Bastelprojekt ist ein 8x8x8-LED-Cube, den ich nach einer Anleitung nachgebaut habe. Er wird über einen Atmega32 angesteuert, was auch so funktioniert wie es soll. Rechenaufwändigere Animationen sollen am Computer berechnet und per RS232 an den Cube gesendet werden. Und hier liegt das Problem.
Das Programm dafür vom Ersteller der Anleitung wurde ursprünglich auf einem Linux-System geschrieben. Sollte ja generell kein Problem sein, das dann auf einem Windows-System zum laufen zu bringen, aber es lief nicht auf Anhieb. Im Programm war ein Header (termios.h) eingebunden, den man unter Windows wohl nicht kompilieren kann. Also hab ich das mal meinem Cousin geschickt, der selbst Informatiker ist. Er hat den Code dann etwas abgeändert, wodurch ich den jetzt auch unter Windows kompilieren kann. Leider hat mein Cousin selbst nicht die Hardware (zB einen COM-Port) um die Funktion des Programms zu testen.
Ich hab an meinem Notebook (Windows 7 Professional 64-Bit) eigentlich auch keinen seriellen Anschluss, aber hab mir einen USB-Adapter von Digitus gekauft (die genaue Bezeichnung hab ich grade nicht da, aber der Adapter läuft mit einem FDTI-Chip). Treiber installiert, der Adapter läuft - soweit ich das beurteilen kann - einwandfrei und ist als COM1 installiert.
Wenn ich nun meine .exe ausführe, kommen erst die Fehlermeldungen "unable to open comport" und "Can not open comport", danach läuft das Programm ganz normal weiter. Natürlich gibt's auch den Code dazu:cube.c
#include "cube.h" #include "time.h" void cube_push (unsigned char data[8][8]) { int x,y,i; i= 0; unsigned char buffer[200]; char* buf_ptr; buffer[i++] = 0xff; // escape buffer[i++] = 0x00; // reset to 0,0 for (x=0;x<8;x++) { for (y=0;y<8;y++) { buffer[i++] = data[x][y]; if (data[x][y] == 0xff) { buffer[i++] = data[x][y]; } } } buf_ptr = (char*)&buffer; if(SendBuf(cport_nr, buf_ptr, i) < 0) printf("send data failed...\n"); } int cube_init (void) { int i, n, cport_nr=1, /* /dev/ttyS0 (COM1 on windows) */ //auf 1 geändert bdrate=38400; /* 9600 baud */ // auf 38400 geändert if(OpenComport(cport_nr, bdrate)) { printf("Can not open comport\n"); return(0); } //fcntl(tty, F_SETFL, 0); return 1; }
rs232.c
#include "rs232.h" #ifdef __linux__ /* Linux */ int Cport[22], error; struct termios new_port_settings, old_port_settings[22]; char comports[22][13]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2","/dev/ttyS3","/dev/ttyS4","/dev/ttyS5", "/dev/ttyS6","/dev/ttyS7","/dev/ttyS8","/dev/ttyS9","/dev/ttyS10","/dev/ttyS11", "/dev/ttyS12","/dev/ttyS13","/dev/ttyS14","/dev/ttyS15","/dev/ttyUSB0", "/dev/ttyUSB1","/dev/ttyUSB2","/dev/ttyUSB3","/dev/ttyUSB4","/dev/ttyUSB5"}; int OpenComport(int comport_number, int baudrate) { int baudr; if((comport_number>21)||(comport_number<0)) { printf("illegal comport number\n"); return(1); } switch(baudrate) { case 50 : baudr = B50; break; case 75 : baudr = B75; break; case 110 : baudr = B110; break; case 134 : baudr = B134; break; case 150 : baudr = B150; break; case 200 : baudr = B200; break; case 300 : baudr = B300; break; case 600 : baudr = B600; break; case 1200 : baudr = B1200; break; case 1800 : baudr = B1800; break; case 2400 : baudr = B2400; break; case 4800 : baudr = B4800; break; case 9600 : baudr = B9600; break; case 19200 : baudr = B19200; break; case 38400 : baudr = B38400; break; case 57600 : baudr = B57600; break; case 115200 : baudr = B115200; break; case 230400 : baudr = B230400; break; case 460800 : baudr = B460800; break; case 500000 : baudr = B500000; break; case 576000 : baudr = B576000; break; case 921600 : baudr = B921600; break; case 1000000 : baudr = B1000000; break; default : printf("invalid baudrate\n"); return(1); break; } Cport[comport_number] = open(comports[comport_number], O_RDWR | O_NOCTTY | O_NDELAY); if(Cport[comport_number]==-1) { perror("unable to open comport "); return(1); } error = tcgetattr(Cport[comport_number], old_port_settings + comport_number); if(error==-1) { close(Cport[comport_number]); perror("unable to read portsettings "); return(1); } memset(&new_port_settings, 0, sizeof(new_port_settings)); /* clear the new struct */ new_port_settings.c_cflag = baudr | CS8 | CLOCAL | CREAD; new_port_settings.c_iflag = IGNPAR; new_port_settings.c_oflag = 0; new_port_settings.c_lflag = 0; new_port_settings.c_cc[VMIN] = 0; /* block untill n bytes are received */ new_port_settings.c_cc[VTIME] = 0; /* block untill a timer expires (n * 100 mSec.) */ error = tcsetattr(Cport[comport_number], TCSANOW, &new_port_settings); if(error==-1) { close(Cport[comport_number]); perror("unable to adjust portsettings "); return(1); } return(0); } int PollComport(int comport_number, unsigned char *buf, int size) { int n; #ifndef __STRICT_ANSI__ /* __STRICT_ANSI__ is defined when the -ansi option is used for gcc */ if(size>SSIZE_MAX) size = (int)SSIZE_MAX; /* SSIZE_MAX is defined in limits.h */ #else if(size>4096) size = 4096; #endif n = read(Cport[comport_number], buf, size); return(n); } int SendByte(int comport_number, unsigned char byte) { int n; n = write(Cport[comport_number], &byte, 1); if(n<0) return(1); return(0); } int SendBuf(int comport_number, unsigned char *buf, int size) { return(write(Cport[comport_number], buf, size)); } void CloseComport(int comport_number) { close(Cport[comport_number]); tcsetattr(Cport[comport_number], TCSANOW, old_port_settings + comport_number); } /* Constant Description TIOCM_LE DSR (data set ready/line enable) TIOCM_DTR DTR (data terminal ready) TIOCM_RTS RTS (request to send) TIOCM_ST Secondary TXD (transmit) TIOCM_SR Secondary RXD (receive) TIOCM_CTS CTS (clear to send) TIOCM_CAR DCD (data carrier detect) TIOCM_CD Synonym for TIOCM_CAR TIOCM_RNG RNG (ring) TIOCM_RI Synonym for TIOCM_RNG TIOCM_DSR DSR (data set ready) */ int IsCTSEnabled(int comport_number) { int status; status = ioctl(Cport[comport_number], TIOCMGET, &status); if(status&TIOCM_CTS) return(1); else return(0); } #else /* windows */ HANDLE Cport[16]; char comports[16][10]={"\\\\.\\COM1:", "\\\\.\\COM2", "\\\\.\\COM3", "\\\\.\\COM4", "\\\\.\\COM5", "\\\\.\\COM6:", "\\\\.\\COM7", "\\\\.\\COM8", "\\\\.\\COM9", "\\\\.\\COM10", "\\\\.\\COM11", "\\\\.\\COM12", "\\\\.\\COM13", "\\\\.\\COM14", "\\\\.\\COM15", "\\\\.\\COM16"}; char baudr[64]; int OpenComport(int comport_number, int baudrate) { if((comport_number>15)||(comport_number<0)) { printf("illegal comport number\n"); return(1); } switch(baudrate) { case 110 : strcpy(baudr, "baud=110 data=8 parity=N stop=1"); break; case 300 : strcpy(baudr, "baud=300 data=8 parity=N stop=1"); break; case 600 : strcpy(baudr, "baud=600 data=8 parity=N stop=1"); break; case 1200 : strcpy(baudr, "baud=1200 data=8 parity=N stop=1"); break; case 2400 : strcpy(baudr, "baud=2400 data=8 parity=N stop=1"); break; case 4800 : strcpy(baudr, "baud=4800 data=8 parity=N stop=1"); break; case 9600 : strcpy(baudr, "baud=9600 data=8 parity=N stop=1"); break; case 19200 : strcpy(baudr, "baud=19200 data=8 parity=N stop=1"); break; case 38400 : strcpy(baudr, "baud=38400 data=8 parity=N stop=1"); break; case 57600 : strcpy(baudr, "baud=57600 data=8 parity=N stop=1"); break; case 115200 : strcpy(baudr, "baud=115200 data=8 parity=N stop=1"); break; case 128000 : strcpy(baudr, "baud=128000 data=8 parity=N stop=1"); break; case 256000 : strcpy(baudr, "baud=256000 data=8 parity=N stop=1"); break; default : printf("invalid baudrate\n"); return(1); break; } Cport[comport_number] = CreateFileA(comports[comport_number], GENERIC_READ|GENERIC_WRITE, 0, /* no share */ NULL, /* no security */ OPEN_EXISTING, 0, /* no threads */ NULL); /* no templates */ if(Cport[comport_number]==INVALID_HANDLE_VALUE) { printf("unable to open comport\n"); return(1); } DCB port_settings; memset(&port_settings, 0, sizeof(port_settings)); /* clear the new struct */ port_settings.DCBlength = sizeof(port_settings); if(!BuildCommDCBA(baudr, &port_settings)) { printf("unable to set comport dcb settings\n"); CloseHandle(Cport[comport_number]); return(1); } if(!SetCommState(Cport[comport_number], &port_settings)) { printf("unable to set comport cfg settings\n"); CloseHandle(Cport[comport_number]); return(1); } COMMTIMEOUTS Cptimeouts; Cptimeouts.ReadIntervalTimeout = MAXDWORD; Cptimeouts.ReadTotalTimeoutMultiplier = 0; Cptimeouts.ReadTotalTimeoutConstant = 0; Cptimeouts.WriteTotalTimeoutMultiplier = 0; Cptimeouts.WriteTotalTimeoutConstant = 0; if(!SetCommTimeouts(Cport[comport_number], &Cptimeouts)) { printf("unable to set comport time-out settings\n"); CloseHandle(Cport[comport_number]); return(1); } return(0); } int PollComport(int comport_number, unsigned char *buf, int size) { int n; if(size>4096) size = 4096; /* added the void pointer cast, otherwise gcc will complain about */ /* "warning: dereferencing type-punned pointer will break strict aliasing rules" */ ReadFile(Cport[comport_number], buf, size, (LPDWORD)((void *)&n), NULL); return(n); } int SendByte(int comport_number, unsigned char byte) { int n; WriteFile(Cport[comport_number], &byte, 1, (LPDWORD)((void *)&n), NULL); if(n<0) return(1); return(0); } int SendBuf(int comport_number, unsigned char *buf, int size) { int n; if(WriteFile(Cport[comport_number], buf, size, (LPDWORD)((void *)&n), NULL)) { return(n); } return(-1); } void CloseComport(int comport_number) { CloseHandle(Cport[comport_number]); } int IsCTSEnabled(int comport_number) { int status; GetCommModemStatus(Cport[comport_number], (LPDWORD)((void *)&status)); if(status&MS_CTS_ON) return(1); else return(0); } #endif void cprintf(int comport_number, const char *text) /* sends a string to serial port */ { while(*text != 0) SendByte(comport_number, *(text++)); }
Das ist jetzt natürlich nicht das vollständige Programm, aber die Animationen haben mit dem Fehler sicher nichts zu tun.
Ich hoffe, das war ausführlich genug und bedanke mich schon mal fürs Durchlesen. Wäre Klasse, wenn ihr mir da irgendwie weiterhelfen könntet.Grüße,
skawesome
-
Irgendetwas mag die WinAPI-Funktion
CreateFileA()
(Zeile 237) nicht.
Die Frage ist daher besser im WinAPi-Forum aufgehoben.
-
Okay, wenn das Thema wo anders besser aufgehoben ist, bitte ich jemanden der das kann, das Thema zu verschieben.
Das Problem mit der CreateFileA() kann ich bestätigen. Ich hab da grade mal eine GetLastError() eingebaut, das Problem ist "Das System kann die angegebene Datei nicht finden." Wisst ihr woran das liegen könnte?
*Update*
Nach ein bisschen rumprobieren kommt jetzt keine Fehlermeldung mehr, aber der Würfel spielt trotzdem nichts ab. Aber immerhin ein Fortschritt.
-
Sorry für den Doppelpost, aber das Problem hat sich wieder etwas geändert. Der Fehler oben ist aufgetreten, weil ich die falsche COM-Port-Nummer eingestellt habe (COM1 = 0 und nicht 1).
Das Problem diesmal ist, dass das Hauptprogramm quasi nicht läuft. Aber erst mal den Code dazu:
DWORD WINAPI cube_updater(LPVOID args) { unsigned char pushcube[8][8]; while (1) { memcpy(pushcube, &args, 64); cube_push(pushcube); } } int main(int argc, char **argv) { int i, x; HANDLE Cubethread = 0; DWORD threadId; cube_init(); Cubethread = CreateThread( NULL, 0, cube_updater, &rs232_cube, 0, &threadId); if ( Cubethread == NULL) ExitProcess(threadId); printf("Cubethread konnte nicht erzeugt werden.\n"); while (1) { printf("Effect: sidewaves\n"); sidewaves(2000,100); printf("Effect: ripples\n"); ripples(2000,100); printf("Effect: linespin\n"); linespin(2000,100); printf("Effect: sinelines\n"); sinelines(2000,100); printf("Effect: spheremove\n"); spheremove(1500,100); printf("Effect: fireworks\n"); fireworks(7,50,1200); printf("Effect: gol_play\n"); for (i=0; i<10; i++) { for (x=0; x<20; x++) setvoxel(rand()%4,rand()%4,rand()%4); gol_play(50,1000); } } CloseHandle(Cubethread); }
Anscheinend funktioniert das mit dem CubeThread() nicht, weil die Fehlermeldung erscheint (die bei CubeThread == NULL). Hab da dann auch mal einen GetLastError() eingebaut, der mir dann sagt: "Der Vorgang wurde erfolgreich beendet."
Allerdings läuft wie while-Schleife dann trotzdem, was mir durch printf("Effect: sidewaves\n") usw. angezeigt wird. Weiß jemand was da schief läuft?Grüße,
skawesome
-
Klammern vergessen. Das Einrücken ist zur besseren Lesbarkeit da.
if ( Cubethread == NULL) ExitProcess(threadId); printf("Cubethread konnte nicht erzeugt werden.\n");
ist so wie
if ( Cubethread == NULL) { ExitProcess(threadId); } printf("Cubethread konnte nicht erzeugt werden.\n");