A
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;
}
}
}