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");
    

Anmelden zum Antworten