Uebertragung von Inhalt einer Textdatei über einen seriellen port RS232



  • Hallo esrtmal,

    ich bin anfänger im Gebiete WinApi und brauche ihre Unterstützung, um mein C++-Code zu beenden.

    Ich arbeite unter Windows XP und möchte die Positionen x und y von meiner Textdatei zu einem Mikrocontroller atmega644p über der serielle Port RS232 senden. Die Textdatei enthält die positionen x, y und andere Symbole. Für meine Arbeit beschäftige ich mich nur mit jeder Position x und y. Die andere Symbole sind unwichtig. In der Textdatei befinden sich die Positionen x und y in Ascii-Form.

    Ich habe versucht, ein c++-Code zu schreiben, damit man die Textdatei Zeile für zeile ausliest. Dann ich habe mit Hilfe der Funktion CreateFile versucht, der serielle Port RS232 zu oeffnen, um später jede Position x und y in Byte-Form ueber die serielle Schnittstelle zu uebertragen.

    Ich habe mein C++-Code debuggt und habe folgender Fehlermeldung auf mein Consol bekommen : " "Fehler: Die Oeffnung der serielle Port RS232 ist unmöglich" " .
    Warum bekomme ich diese Fehlermeldung ?

    Bitte, was soll ich noch in meinem programm ändert, damit ich mit Erfolg jede Position x und y von der Textdatei auf dem seriellen Port RS232 uebertrage.

    Danke im voraus.

    mfg arthurdubois

    Mein C++-Code lautet:

    [cpp]

    #include <fstream>
    #include <string>
    #include <iostream>
    #include <sstream>
    #include <stdio.h>
    #include <stdlib.h>

    #include <Windows.h>

    using namespace std;

    int main(void)
    {
    ifstream file("koordinaten.txt", ios::in | ios::binary);
    string line;

    if (!file)
    {
    cout << "Fehler: Die Oeffnung der Textdatei in Modus Auslesen ist unmöglich" << endl;
    return 1;
    }

    // Oeffung der Port COM1

    HANDLE h = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if (h == INVALID_HANDLE_VALUE)
    {
    cout << "Fehler: Die Oeffnung der serielle Port RS232 ist unmöglich" << endl;
    return 1;
    }

    DCB dcb = { 0 };
    BOOL dcbOk = GetCommState(h, &dcb);
    dcb.BaudRate = CBR_115200;
    dcb.ByteSize = 8;
    dcb.Parity = NOPARITY;
    dcb.StopBits = TWOSTOPBITS;
    dcb.fOutxCtsFlow = FALSE; // Warum das und dann ein manueller Test von CTS ?
    dcbOk = SetCommState(h, &dcb);

    // Auslesen Zeile pro Zeile

    while (getline(file, line))
    {
    int x ; // x, y von Textdatei
    int y ;
    int x_steps; // x, y in Motorschritt
    int y_steps;
    stringstream input; // Eingangsfluss (Eine Zeile von Text)
    stringstream output_x; // Ausgangsfluss (Ein Paar von Koordinaten)
    stringstream output_y;

    // Eine Zeile wird ein Eingangsfluss
    input.str(line);
    // Extraktion von X und von Y.
    if (input.get() != 'X')
    continue;
    input >> x;
    //cout << x << endl;
    if (input.get() != 'Y')
    continue;
    input >> y;
    //cout << y << endl ;
    // cout << x << ", " << y << endl;

    // Konversion der Positionen x und y in Motorschritt

    x_steps = (x * 127) / 500;
    //cout << x_steps << endl ;
    y_steps = (y * 127) / 500;
    //cout << x_steps << ", " << y_steps << endl;

    // Uebertragung von Koordinaten (x,y) ueber der serielle Port RS232

    DWORD written = 0;
    output_x << x_steps; // TODO: Ne manque-t-il pas un terminateur ou un cadrage ?
    WriteFile(h, output_x.str().c_str(), output_x.str().size(), &written, 0);
    output_y << y_steps; // TODO: Ne manque-t-il pas un terminateur ou un cadrage ?
    WriteFile(h, output_y.str().c_str(), output_y.str().size(), &written, 0);
    // TODO: Et là, il ne faut pas attendre un retour ?
    }
    CloseHandle(h);
    return 0;
    }

    [\cpp]

    Meine Textdatei sieht folgendermaße aus:

    [/code]

    %
    M48
    M72
    T01C0.0320
    T02C0.0394
    T03C0.0400
    T04C0.0440
    T05C0.0512
    T06C0.1181
    %
    T01
    X21101Y24101
    X10851Y16601
    X13851Y19101
    X10851Y22851
    X11851Y22851
    X12851Y22851
    X12351Y24851
    X11351Y24851
    X10351Y24851
    X9351Y24851
    X8351Y24851
    X7351Y24851
    X6351Y24851
    X16101Y22601
    X18101Y22601
    T04
    X23351Y15101
    X25351Y15101
    X27351Y15101
    X29351Y15101
    X29351Y19101
    X27351Y19101
    X25351Y19101
    X23351Y19101
    X23351Y21601
    X23351Y25601
    X25351Y25601
    X27351Y25601
    X29351Y25601
    X29351Y21601
    X27351Y21601
    X25351Y21601
    T05
    X33611Y6609
    X33611Y8609
    X33611Y10609
    X33611Y12609
    X33611Y14609
    X33611Y16609
    X33611Y18609
    X33611Y20609
    X33611Y22609
    X33611Y24609
    X24109Y6841
    X26109Y6841
    X28109Y6841
    X30109Y6841
    T06
    X2101Y2101
    X2101Y29601
    X37101Y2351
    X37351Y29601
    M30

    [code]



  • Statt Ausgabe einer eigenen, möglicherweise falschen Meldung, besser mit GetLastError() die Fehlernummer holen.
    Per FormatMessage kann man sich den Fehlertext dazu besorgen.
    Alternativ die Fehlernummer selbst nachschauen:
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381%28v=vs.85%29.aspx

    Gibt es COM1 auf deinem System?



  • Hi,

    Mein Pc hat die Schnittstelle "COM1".

    mfg

    arthurdubois



  • Nimm für cpp-/code-Tags doch lieber die Buttons, die verwechseln auch nicht Slash und Backslash. 😉



  • Das gibt Dir den Fehler als Fehlernummer und im Klartext.
    Dann weißt Du was nicht stimmt.

    char *fmsg  = NULL;
    int  fehler = 0;
    
    // Oeffung des Port COM1
    HANDLE h = CreateFile( "COM1",
                            GENERIC_READ | GENERIC_WRITE,
                            0,
                            NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if (h == INVALID_HANDLE_VALUE)
    {
      fehler = GetLastError(); 
      FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
                    FORMAT_MESSAGE_FROM_SYSTEM |
                    FORMAT_MESSAGE_IGNORE_INSERTS,
                    NULL,
                    fehler,
                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                    (LPTSTR) &fmsg,
                    0, NULL );
    
      cout << "Fehler: " << GetLastError() << endl << fmsg << endl;
    
      return 1;
    }
    


  • noergel schrieb:

    Das gibt Dir den Fehler als Fehlernummer und im Klartext.
    Dann weißt Du was nicht stimmt.

    Und wenn man es macht dann natürlich immer ...

    BOOL dcbOk = GetCommState(h, &dcb); 
       if (!dcbOk) {
          printf ("GetCommState failed with error %d.\n", GetLastError());
          return (2);
       }
    
    dcbOk = SetCommState(h, &dcb); 
    
      if (!dcbOk) {
         printf ("SetCommState failed with error %d.\n", GetLastError());
         return (3);
      }
    

    siehe: Configuring a Communications Resource
    http://msdn.microsoft.com/en-us/library/aa363201.aspx

    Möglicherweise sollte man auch auf die neue Schreibweise umstellen:

    To specify a COM port number greater than 9, use the following syntax: "\\.\COM10". This syntax works for all port numbers ...
    

    Baudrate und Bytesize sehen vertraut aus, allerdings sind 2 Stopbits eher unüblich.

    Da es sich vermutlich um eine Nullmodem-Verbindung (ohne Hardware Handshake)
    handelt würde mich die Verwendung von CTS und DTS wundern.

    Wenn es COM1 gibt und das erwartet Gerät wirklich angeschlossen ist sollte man
    mit einem Schnittstellentester oder Skope mal nachsehen ob was übertragen wird.

    Beim Senden gegen Ende habe ich Bedenken ob das zuverlässich klappt. Wenn man
    die X und Y Koordinaten mit variabler Länge ohne Trennzeichen als Text
    hintereinander sendet wie soll der Empfänger das zuverlässlich trennen ?

    !! Wie man der beigelegten Koordinatenliste auch schon entnehmen kann werden mal
    4 und mal 3 Byte gesendet!!

    DWORD written = 0; 
    output_x << x_steps; // TODO: Ne manque-t-il pas un terminateur ou un cadrage ? 
    WriteFile(h, output_x.str().c_str(), output_x.str().size(), &written, 0); 
    output_y << y_steps; // TODO: Ne manque-t-il pas un terminateur ou un cadrage ? 
    WriteFile(h, output_y.str().c_str(), output_y.str().size(), &written, 0); "
    

    Und der Kommentar "attendre un retour ?" ist auch unbedingt zu beachten.
    Bei einer Nullmodemverbindung ist es ratsam (und üblich) sich den Empfang
    bestätigen zu lassen bevor man weitere Daten sendet. Der PC ist wohl erheblich
    schneller als die meisten Microcontroller.

    Insbesondere:
    Wenn der Microcontroller WIRKLICH so langsam ist, das er ZWEI Stoppbits
    braucht ...

    (PS: Viele Grüsse nach Frankreich ...)



  • merano schrieb:

    Da es sich vermutlich um eine Nullmodem-Verbindung (ohne Hardware Handshake) handelt würde mich die Verwendung von CTS und DTS wundern.

    Was meinst du mit Nullmodem-Verbindung? Den Begriff verwendet man doch nur wenn man etwas was man normalerweise mit Modem macht, ohne Modem macht. Also z.B. zwei PCs über ein ausgekreuztes Kabel miteinander plaudern zu lassen.
    Und wieso sollte "Nullmodem-Verbindung" "ohne Hardware Handshake" implizieren?

    Die meisten Geräte die man so an die serielle Schnittstellen anhängt können Hardware Handshake. Und wenn sie es können, dann sollte man es auch verwenden.

    Bei einer Nullmodemverbindung ist es ratsam (und üblich) sich den Empfang
    bestätigen zu lassen bevor man weitere Daten sendet. Der PC ist wohl erheblich
    schneller als die meisten Microcontroller.

    Siehste, aus dem Grund verwendet man ja auch Hardware Handshake 😃



  • hustbaer schrieb:

    Und wieso sollte "Nullmodem-Verbindung" "ohne Hardware Handshake" implizieren?

    Die meisten Geräte die man so an die serielle Schnittstellen anhängt können Hardware Handshake.
    Und wenn sie es können, dann sollte man es auch verwenden.

    ... , aus dem Grund verwendet man ja auch Hardware Handshake 😃

    Genau so ist es; hatte ich auch nicht anders behauptet. Es macht nur keinen
    Sinn, wenn eines der beiden angeschlossenen Geräte keine Hardwareflusskontrolle
    unterstützt.

    Im konkreten Fall geht es um die Verbindung eines PCs mit einem Microcontroller.
    Dort ist es üblich 3-Draht-Nullmodem Verbindungen zu nutzen.

    Wenn Du mal einen Blick in das vom Fragesteller verwendete Datasheet vom
    ATmega644 wirfst, wirst Du gleich auf der ersten Seite unter Features
    "Byte-oriented Two-wire Serial Interface" finden.

    BTW: In meiner beruflichen Praxis setze ich serielle 3-Draht Verbindungen seit
    den 80ern bevorzugt ein, weil der Aufwand für Full-Handshake meist nicht lohnt.
    In Verbindung mit Nicht-PCs geht es meist garnicht anders.
    Mit einem Software Handshake kann man oft flexibler auf Probleme reagieren.



  • Oh, Sorry, hatte nicht gesehen dass da ein Typ angegeben war.
    Ja, OK, wenn Hardware Handshake nicht unterstützt wird, sollte man es natürlich auch eher nicht aufdrehen - wäre ja bloss verwirrend für jmd. der den Code später liest.



  • Moin nochmal,

    ich habe mein Programm verbessert, aber meine Übertragungsfunktion EnvoieCommande(), die die Positionen X und Y von der Textdatei in Richtung der serielle Schnittstelle RS232 sendet, läuft nicht einwandfreie.

    Mein verbessertes Programm lautet:

    #include <fstream>
    #include <string>
    #include <iostream>
    #include <sstream>
    
    #include <Windows.h>
    
    using namespace std;
    
    // Sendet ein Auftrag Charakter pro Charakter und prüft das Empfangen von ACK 
    static bool EnvoieCommande(HANDLE h, const char *s)
    {
    	DWORD	dummy;
    	char	c;
    
           // Wenn es gab, ab dem letzten Auftrag Antworten zu lesen, dann zu spät, 
           //man löscht die Antworten
    	PurgeComm(h, PURGE_RXCLEAR);
    	for (int i = 0; s[i] != 0; ++i)
    		if (!WriteFile(h, s + i, 1, &dummy, 0))
    			return false;
    	if (!ReadFile(h, &c, 1, &dummy, 0))
    		return false;	// Time-out
    	return c == '\x06';	// ACK ---> in AScii x06
    }
    
    int main(void)
    {
    	ifstream file("koordinaten.txt", ios::in | ios::binary);
    	string line;
    
    	if (!file)
    	{
    		cout << "Fehler: Öffnung der Textdatei in Modus Lesen ist unmöglich" << endl;
    		return 1;
    	}
            char *fmsg  = NULL;
            int  fehler = 0;
    
    	// Öffnung der serielle Port COM1Ouverture du port COM
    	HANDLE h = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    	if (h == INVALID_HANDLE_VALUE)
    	{
    
           fehler = GetLastError();
      FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                    FORMAT_MESSAGE_FROM_SYSTEM |
                    FORMAT_MESSAGE_IGNORE_INSERTS,
                    NULL,
                    fehler,
                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                    (LPTSTR) &fmsg,
                    0, NULL );
    
                cout << "Fehler: " << GetLastError() << endl << fmsg << endl;
                cout << "Fehler: Öffnung der serielle Port unmöglich" << endl;
    		return 1;
    	}
    	DCB dcb = { 0 };
    	BOOL dcbOk = GetCommState(h, &dcb);
    	dcb.BaudRate = CBR_115200;
    	dcb.ByteSize = 8;
    	dcb.Parity = NOPARITY;
    	dcb.StopBits = TWOSTOPBITS;
    	dcbOk = SetCommState(h, &dcb);
    	COMMTIMEOUTS timeouts = { 0 };
    	timeouts.ReadIntervalTimeout = 100;
    	timeouts.ReadTotalTimeoutMultiplier = 100;
    	timeouts.ReadTotalTimeoutConstant = 100;
    	timeouts.WriteTotalTimeoutMultiplier = 100;
    	timeouts.WriteTotalTimeoutConstant = 100;
    	if (!SetCommTimeouts(h, &timeouts))
    	{
    		cout << "Fehler: SetCommTimeouts" << endl;
    		return 1;
    	}
            if (!dcbOk) {
          printf ("GetCommState failed with error %d.\n", GetLastError());
          return (2);
           }
       if (!dcbOk) {
         printf ("SetCommState failed with error %d.\n", GetLastError());
         return (3);
           }
    	// Lesen Zeile pro Zeile 
    	while (getline(file, line))
    	{
    		int x;					// x, y von Textdatei
    		int y;
    		int x_steps;			// x, y in Schrittmotor
    		int y_steps;
    		stringstream input;		// Eingangsfluss (Eine Zeile von Textdatei)
    		stringstream output;	// Ausgangsfluss (Ein Paar von Koordinaten)
    
    		// Eine Zeile wird einen Eingangsfluss 
    		input.str(line);
    		// Extraktion von X und Y.
    		if (input.get() != 'X')
    			continue;
    		input >> x;
    		if (input.get() != 'Y')
    			continue;
    		input >> y;
    		// Konversion von Positionen X und Y in Schrittmotor
    
    		x_steps = x * 127 / 500;
    		y_steps = y * 127 / 500;
    		// Sendung von koordinaten über der serielle port RS232
    		output << '\n';
    		output << x_steps;
    		output << ',';
    		output << y_steps;
    		output << '\r';
    		cout << "Sendung von : " << output.str() << endl;
    		if (EnvoieCommande(h, output.str().c_str()))
    			cout << "OK" << endl;
    		else
    			cout << "Fehler" << endl;
    	}
    	CloseHandle(h);
    	return 0;
    }
    

    Die Fehlermeldung lautet:

    Sendung von :
    5359,6121
    Fehler
    Sendung von :
    2756,4216
    Fehler

    Die Sendefunktion EnvoieCommande() schickt kurz gesagt keine Daten . Meine Sendefunktion macht eigentlich nicht seine Aufgabe.

    Bitte, kann jemand mir sagen, was in meinem Programm schiefläuft. Ich komme einfach nicht klar !! Ich bin auch für Korrektur offen.

    Danke im Vorraus.

    mfg



  • Wenn WriteFile/ReadFile fehlschlagen, sollte man eigentlich GetLastError aufrufen, um der Sache auf den Grund zu gehen. Du weißt so ja nicht mal, welche der beiden Funktionen fehlschlägt, geschweige denn, was im Detail schiefläuft.



  • Vielen Dank für deine Rückmeldung _matze .

    Ich habe deine Anweisung befolgt und habe festgestellt, dass der Fehler nicht von meinem C++-Programm kommt, sondern von meinem µC. Weil der µC statt "ACK" komische Antwort zum PC zurückschickt. Deswegen hatte zum ersten mal meine Funktion EnvoieCommande() nicht funktioniert.

    mfg



  • Hallo,

    ich bin´s noch. Es geht immer über die Übertragung Zeile pro Zeile von Postionskoordinaten meiner Textdatei von PC zu den Mikrocontroller.

    Eigentlich habe ich ein Kommunikationsproblem. Ich habe mein PC-Code geschrieben, so dass der PC Positionskoordinaten von der Textdatei zeile pro Zeile zum Mikrocontroller senden soll. Wenn der PC die erste Positionskoordinaten(X,Y) zum Mikrocontroller sendet, dann soll der PC auf eine Benachrichtigung der Mikrocontroller warten, bevor er die nächste Positionskoordinaten(X,Y) schickt.

    Wenn ich die Positionskoordinaten(X,Y) der Textdatei Zeile pro Zeile (Schritt für Schritt) zum Mikrocontroller sende, läuft alles wunderbar.
    Aber wenn ich auf einmal alle Positionskoordinaten der Textdatei zum Mikrocontroller sende, wird nur ein, zwei oder höchstens drei Positionskoordinaten ausgeführt. Aber die Andere Positionskoordinaten(X,Y) von Textdatei werden nicht gesendet.

    Woran kann das liegen ? Habe ich zufällig ein Problem von Handschake-Signal (RTS/CTS)? Wenn ja, wie soll ich das einsetzen.

    Bemerkung: Der Mikrocontroller empfängt die Positionskoordinaten(X,Y), die vom PC gesendet wurde, mit Hilfe der Funktion ISR(USART0_RX_vect). Dann wird später in der Funktion ProcessCommand() eine Benachrichtigung zum PC gesendet, damit der PC die nächste Positionskoordinaten sendet.

    Ich wäre sehr dankbar, wenn sie mir helfen.

    Danke im Voraus.

    C++-Code:

    #include <fstream>
    #include <string>
    #include <iostream>
    #include <sstream>
    
    #include <Windows.h>
    
    using namespace std;
    
    // Senden eines Befehls Charakter pro Charakter und man prüft das Empfangen eines  ACK, bevor die Sendung der nächsten Positionskoordinaten
    static bool SendungBefehl(HANDLE h, string s)
    {
    	DWORD	length;
    	char	c;
            // Wenn es seit dem letzten Befehl Antorten  zu lesen gab,
    	// Zu spät, alles muss gelöscht werden.
    	PurgeComm(h, PURGE_RXCLEAR);
    	if (!WriteFile(h, s.c_str(), s.size(), &length, 0) || length != s.size())
    	{
    		cout << "Error von WriteFile" << endl;
    		return false;
    	}
    	if (!ReadFile(h, &c, 1, &length, 0) || length != 1)
    	{
    		cout << "Error von ReadFile (time-out)" << endl;
    		return false;
    	}
    	cout << "Antwort : " << (int)c << endl;
    	return c == '\x06';	// ACK
    }
    
    int main(void)
    {
    	ifstream file("koordinaten.txt", ios::in | ios::binary);
    	string line;
    
    	if (!file)
    	{
    		cout << "Error: Die Öffnung der Textdatein in Lesen-Modus ist unmöglich" << endl;
    		return 1;
    	}
    	// Öffnung des seriellen Ports COM1
    	HANDLE h = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    	if (h == INVALID_HANDLE_VALUE)
    	{
    		cout << "Error: Öffnung der seriellen Port ist unmöglich" << endl;
    		return 1;
    	}
    	DCB dcb = { 0 };
    	BOOL dcbOk = GetCommState(h, &dcb);
    	dcb.BaudRate = CBR_9600;
    	dcb.ByteSize = 8;
    	dcb.Parity = NOPARITY;
    	dcb.StopBits = ONESTOPBIT;
    	dcbOk = SetCommState(h, &dcb);
    	COMMTIMEOUTS timeouts = { 0 };
    	timeouts.ReadIntervalTimeout = 100;
    	timeouts.ReadTotalTimeoutMultiplier = 100;
    	timeouts.ReadTotalTimeoutConstant = 100;
    	timeouts.WriteTotalTimeoutMultiplier = 100;
    	timeouts.WriteTotalTimeoutConstant = 100;
    	if (!SetCommTimeouts(h, &timeouts))
    	{
    		cout << "Erreur: SetCommTimeouts" << endl;
    		return 1;
    	}
    	// Lesen Zeile pro Zeile
    	while (getline(file, line))
    	{
    		int x;					// x, y von der Textdatei
    		int y;
    		int x_steps;			// x, y in Schrittmotor
    		int y_steps;
    		stringstream input;		// Eingangsfluß (Eine Zeile der Textdatei)
    		stringstream output;	// Ausgangsfluß (Ein Koordinatenpaar)
    
    		// Eine Zeile wird ein Eingangsfluß sein
    		input.str(line);
    		// Extraktion von X et du Y.
    		if (input.get() != 'X')
    			continue;
    		input >> x;
    		if (input.get() != 'Y')
    			continue;
    		input >> y;
    		// Konvertierung von Positionkoordinaten(X,Y) in Schrittmotor
    
    		x_steps = x * 127 / 500;
    		y_steps = y * 127 / 500;
    		// Sendung der PositionsKoordinaten Zeile pro Zeile über der serielle Port (COM1)
    		output << 'D';
    		output << x_steps;
    		output << ',';
    		output << y_steps;
    		output << 'F';
    		cout << "Sendung von : " << output.str() << endl;
    		if (SendungBefehl(h, output.str()))
    			cout << "OK" << endl;
    		else
    			cout << "ERROR" << endl;
    	}
    	CloseHandle(h);
    	return 0;
    }
    

    Mikrocontroller-Code:

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdint.h>
    # define F_CPU 3686400UL
    #include <util/delay.h>
    
    #define FOSC 7372000 // Clock Speed
    #define BAUD 9600UL
    
    #define UBRR_VAL ((FOSC+BAUD*8)/(BAUD*16)-1)   // clever runden
    ///////////////////////////////////////////////////////////////////
    #define usart_buffer_max_size 512u
    #define usart_command_max_size 20
    
    char usart_command[usart_command_max_size + 1] = {0};
    char usart0_tx_buffer[usart_buffer_max_size];
    char usart1_tx_buffer[usart_buffer_max_size];
    volatile uint8_t usart_command_size = 0;
    volatile uint8_t usart0_tx_buffer_size = 0;
    volatile uint8_t usart0_tx_buffer_start = 0;
    volatile uint8_t usart1_tx_buffer_size = 0;
    volatile uint8_t usart1_tx_buffer_start = 0;
    /////////////////////////////////////////////////////////////////////
    volatile uint8_t command_ready = 0;
    
    /////////////////////////////////////////////////////////////////////
    // Eingang vom Ringpuffer
    void USART0_QueueIn(char c)
    {
      int i;
    
      if (usart0_tx_buffer_size < usart_buffer_max_size)
      {
        i = (usart0_tx_buffer_size + usart0_tx_buffer_start) % usart_buffer_max_size;
        usart0_tx_buffer[i] = c;
        ++usart0_tx_buffer_size;
      }
      else
      {
        usart0_tx_buffer_size = 0;
      }
    }
    
    // Ausgang vom Ringpuffer
    char USART0_QueueOut(void)
    {
      char c;
    
      if (usart0_tx_buffer_size == 0)
        return 0;
      c = usart0_tx_buffer[usart0_tx_buffer_start];
      --usart0_tx_buffer_size;
      usart0_tx_buffer_start = (usart0_tx_buffer_start + 1) % usart_buffer_max_size;
      return c;
    }
    
    // Eingang vom Ringpuffer
    void USART1_QueueIn(char c)
    {
      int i;
    
      if (usart1_tx_buffer_size < usart_buffer_max_size)
      {
        i = (usart1_tx_buffer_size + usart1_tx_buffer_start) % usart_buffer_max_size;
        usart1_tx_buffer[i] = c;
        ++usart1_tx_buffer_size;
      }
      else
      {
        usart1_tx_buffer_size = 0;
      }
    }
    
    // Ausgang vom Ringpuffer
    char USART1_QueueOut(void)
    {
      char c;
    
      if (usart1_tx_buffer_size == 0)
        return 0;
      c = usart1_tx_buffer[usart1_tx_buffer_start];
      --usart1_tx_buffer_size;
      usart1_tx_buffer_start = (usart1_tx_buffer_start + 1) % usart_buffer_max_size;
      return c;
    }
    
    // Sendung einer Antwort über der Ringpuffer zum USART0
    static void USART0_Send(const char *s)
    {
      int i;
    
      for (i = 0; s[i] != 0; ++i)
        USART0_QueueIn(s[i]);
      if (usart0_tx_buffer_size > 0)
        UCSR0B |= 1 << UDRIE0;
    }
    
    // Sendung eines Befehls über der Ringpuffer zum USART1
    static void USART1_Send(const char *s)
    {
      int i;
    
      for (i = 0; s[i] != 0; ++i)
        USART1_QueueIn(s[i]);
      if (usart1_tx_buffer_size > 0)
        UCSR1B |= 1 << UDRIE1;
    }
    
    // Verarbeitung eines Befehls
    static void ProcessCommand(void)
    {
      int i;
      int x;
      int y;
      char x_moteur[12];
      char y_moteur[12];
    
      for (i = 0; i < usart_command_size; ++i)
        if (usart_command[i] == ',')
          break;
    
      if (i <= 0 || i >= usart_command_size - 1)
      {
        // Man hat kein Kommazeichen in Mitte des Strings gefunden -> Fehler
        USART0_Send("\x15");  // NAK, Sendung hat nicht geklappt.
        usart_command_size = 0;
        return;
      }
      // Ich wandle x und y in Integer um, um Berechnung durchzuführen, wenn es nötig ist
      // Extraktion von X und Y   
        usart_command[i] = 0;
        usart_command[usart_command_size] = 0;
        x = atoi(usart_command);
        y = atoi(usart_command + i + 1);
        usart_command_size = 0;
        itoa(x, x_moteur, 10);
        itoa(y, y_moteur, 10);
    
            // Sendung position x_moteur
       USART1_Send("#1s");
       USART1_Send(x_moteur);
       USART1_Send("\r");
       USART1_Send("#1A\r"); // Losfahren der Platine auf die x-Achse
    
      // _delay_ms(30000); // Warten 15000ms --> 15s
    
           // Sendung position y_moteur
       USART1_Send("#2s");
       USART1_Send(y_moteur);
       USART1_Send("\r");
       USART1_Send("#2A\r"); // Losfahren der Platine auf die y-Achse
    
       _delay_ms(30000); // Warten 30000ms --> 30s
    
       USART0_Send("\x06"); // ACK --> Freigage: PC kann nächste Data senden.
    
      }
    
    // Interruptsfunktion für das Empfangen von Byte
    // Diese Funktion ist High, wenn RXCIE0 = 1  
    ISR(USART0_RX_vect)
    {
      char data;
      data = UDR0;
    
     // Verarbeitung des Befehls -->("D X,Y F")
        // X = x_moteur und Y = y_moteur
      if (data == 'F')
      {    
        command_ready = 1;      
       }
    
      else if (data == 'D')
      {
        // Erzeugung eines neuen Befehls
        usart_command_size = 0;
      }
    
      else
      {
        // Als man weder F, noch D empfängt, speichert man
        //die Koordinatenposition(X,Y) in einem Befehl
        if (usart_command_size < usart_command_max_size)
        {
          usart_command[usart_command_size] = data;
          ++usart_command_size;
        }
    	else
    	{
          usart_command_size = 0;
    	}
      }
    }
    
    // Interruptsfunktion für Byte-Übertragung
    // Diese Funktion ist an, wenn UDRIE1 = 1
    ISR(USART0_UDRE_vect)
    {
      UDR0 = USART0_QueueOut();
      // Sendung stoppen, wenn es keine Daten mehr gibt zu senden
      if (usart0_tx_buffer_size == 0)
        UCSR0B &= ~(1 << UDRIE0);
    }
    
    // Interruptsfunktion für Byte-Übertragung
    // Diese Funktion ist an, wenn UDRIE1 = 1
    ISR(USART1_UDRE_vect)
    {
      UDR1 = USART1_QueueOut();
      // Sendung stoppen, wenn es keine Daten mehr gibt zu senden
      if (usart1_tx_buffer_size == 0)
        UCSR1B &= ~(1 << UDRIE1);
    }
    
    void VorEinstellungMotor(void)
     {
       //USART1_Send("#1|0\r"); // Deaktivierung von Antwort der Motorsteuerung Nr 1
       //USART1_Send("#2|0\r"); // Deaktivierung von Antwort der Motorsteuerung Nr 2
       //USART1_Send("#1:baud=7"); // Baudrate = 9600
       //USART1_Send("#2:baud=7"); // Baudrate = 9600
       USART1_Send("#1D0\r"); // Festlegen der Position der Platine als Ursprung auf die x-Achse
       USART1_Send("#2D0\r"); // Festlegen der Position der Platine als Ursprung auf die y-Achse
       USART1_Send("#1p2\r"); // Modus: Absolut Positionierung --> p=2
       USART1_Send("#2p2\r"); // Modus: Absolut Positionierung --> p=2
    
     }
    
    int main (void)
    {
      USART_Init(UBRR_VAL); // Initialisierung von USART0 and USART1
      VorEinstellungMotor(); // Initialisierung Motorsteuerung
      sei(); // Aktierung Interruptsfunktion
    
      while (1) // Endlosschleife
      {
       if(command_ready)
        {
          ProcessCommand();
          command_ready = 0;
    
        }    
      }
    
    }
    

Anmelden zum Antworten