Problem mit Algorithmus um auf die serielle Schnittstelle zu schreiben
-
Hallo,
habe folgendes Problem:
In dem untenstehende Code, wird in dem Abschnitt "Senden des INIT-String an serielle Schnittstelle", ein Algorithmus ausgeführt, welcher in dem INT Array "sende" die Timestamp einfügt und eine Checksumme neu berechnet.
Das ganze benötige ich, um mit einem Wechselrichter einer Solaranlage zu kommunizieren. Diesem Wechselrichter muss ich folgenden HEX-String: AAAA680404680000000080000AC252C23E9E02165555AAAA680303680000140000000B0F09003700165555" zur Initialisierung schicken, worauf er mir die aktuellen Werte als eine Zeichenkette von HEX-Werten schickt.
Der Sendeteil ist deshalb so komisch und vielleicht auch umständlich geschrieben, weil ich die Timestamp und die Checksumme noch einfügen muss, wobei diese als HEX-Werte eingefügt und byteweise umgedreht werden müssen.
Mein Problem liegt daran, dass ich den INIT-String komplett in einem Rutsch an die serielle Schnittstelle senden muss, aber nicht weis wie das geht. So wie ich es in dem Code unten gemacht habe funktioniert es ja nicht, da er immer nur ein Zeichen sendet.
Wie kann ich das also anders schreiben bzw. kann ich mit dem Code noch was anfangen oder nicht.
Bin für Verbesserungsvorschläge immer zu haben, da ich das Programm nächste Woche abgeben soll.Und nun der Code:
void auslesen() { int j,k; char chRead; unsigned char bin_values[87]=""; int length, i; char hex[9], *hexum, var1, var2, help[3], checkchar[4],check1[3]="",check2[3]=""; int a,b,c,d,e; int sende[43]={0xAA,0xAA,0x68,0x04,0x04,0x68,0x00,0x00,0x00,0x00,0x80,0x00,0x0A,0xFF,0xFF,0xFF,0xFF,0xDD,0xDD,0x16,0x55,0x55,0xAA,0xAA,0x68,0x03,0x03,0x68,0x00,0x00,0x14,0x00,0x00,0x00,0x0B,0x0F,0x09,0x00,0x37,0x00,0x16,0x55,0x55}; unsigned int checksumme=0; /*###############################################################################*/ /*Schnittstelle öffnen und konfigurieren*/ /*###############################################################################*/ HANDLE hKommunikation; DCB dcb; DWORD dwRead; /* Öffnen der Kommunikation */ hKommunikation = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL); GetCommState(hKommunikation, &dcb); /* Datenstruktur mit den aktuellen Werten fuellen (WICHTIG!!) */ /* Spezielle Werte Initialisieren */ dcb.BaudRate = CBR_1200; dcb.ByteSize = 8; dcb.Parity = 0; dcb.StopBits = ONESTOPBIT; dcb.fDtrControl = DTR_CONTROL_DISABLE; dcb.fInX = FALSE; SetCommState(hKommunikation, &dcb); /* Initialisieren mit den geaenderten Werten */ /*#############################################################################*/ /*Hier wird der Init-String an das Powerline Modem der Solaranlage gesendet.*/ /*#############################################################################*/ time_t timestamp = time(NULL); sprintf(hex,"%X",timestamp); printf("\nDas ist der HEX-String: %s\n", hex); //Algorithmus um die Timestamp in eine HEX-Zeichenkette umzuwandeln und anschließen byteweise umzudrehen e=-2; b=strlen(hex); hexum = malloc(b+1); for (a=b; a>0; a-=2) { e=e+2; var1=hex[a-1]; var2=hex[a-2]; hexum[e]=var2; hexum[e+1]=var1; help[0]=var2; help[1]=var1; sende[13+e/2]=strtoul(help,NULL,16); } for (c=6;c<17;c++) { checksumme+=sende[c]; //Generieren der Checksumme } sprintf(checkchar,"%04X",checksumme); //Umwandeln der Integer Checksumme in eine Zeichenkette var1=checkchar[0]; //Hilfsvariable zum Byteweisen umdrehen der Checksumme als CHAR var2=checkchar[1]; //Hilfsvariable zum Byteweisen umdrehen der Checksumme als CHAR checkchar[0]=checkchar[2]; checkchar[1]=checkchar[3]; checkchar[2]=var1; checkchar[3]=var2; check1[0]=checkchar[0]; check1[1]=checkchar[1]; //Speichern der ersten beiden Elemente von checkchar in check1 check2[0]=checkchar[2]; check2[1]=checkchar[3]; //Speichern der letzten beiden Elemente von checkchar in check2 sende[17]=strtoul(check1,NULL,16); //Umwandeln des HEX-Bytes in einen Integer Wert und ablegen in sende sende[18]=strtoul(check2,NULL,16); //Umwandeln des HEX-Bytes in einen Integer Wert und ablegen in sende d=0; do { WriteFile(hKommunikation, sende[d], 1, &dwRead, 0); //Hier ist das Problem d++; } while (d<42); /*#############################################################################*/ /*Hier wird der Antwortstring der Solaranlage eingelesen.*/ /*#############################################################################*/ i=0; do { ReadFile(hKommunikation, &chRead, 1, &dwRead, NULL); i=i+1; bin_values[i]=chRead; } while (i<84); length=i; /*#############################################################################*/ /*Hier wird der Antwortstring überarbeitet.*/ /*#############################################################################*/ //printf("\n Anzahl eingelesener Zeichen: %i\n\n", length); for (j=0; j<length; j++) { snprintf(&(buf[j*2]), 3, "%02X", bin_values[j]); } for (k=0; k<(length); k++) { printf("\n"); printf("(%i) ASCII-String: \%c HEX-String: %c%c",k+1, bin_values[k], buf[k*2], buf[(k*2)+1]); } printf("\n"); printf("\n"); printf(buf); printf("\n"); /*###############################################################################*/ /*Alles wieder schließen*/ /*###############################################################################*/ CloseHandle(hKommunikation); }
Es wäre also echt super, wenn ihr mir helfen könntet.
Ich würde auch nicht nein sagen, wenn mir jemand den Code teilweise umschreiben oder verbessern würde.
MfG
MTC
-
Ist kein Standard C - sieht nach winapi aus. - stimmt das?
Wie wärs, wenn du die Doku zu WriteFile ansiehst und feststellst, warum du immer eine 1 als größe übergibst und nicht einfach das ganze Array auf einmal?
-
Erstmal ist es richtig das es kein Standard-C ist sondern zur WinAPI gehört, deswegen bitte ich auch um Verschiebung.
Aber trotzdem frag ich gleich nochmal nach meinem Problem:
In einer ersten Version meines Programmes hab ich das WriteFile folgendermaßen benutzt:
WriteFile(hKommunikation, "\xAA\xAA\x68\x04\x04........."
Da konnte ich auch mit der Solaranlage kommunizieren. Nachdem ich aber festgestellt habe dass ich die Timestamp und die Checksumme noch mit einbauen mußte, und ich dieses nur über ein INT Array realisieren konnte, habe ich das Problem, dass ich nicht mehr weiss, wie ich mit dem Writefile umgehen muss.
Mein Problem ist auch, das ich nicht weiss ob das 43malige Senden von einem Wert dasselbe ist wie das 1malige Senden von 43 Werten.
Nen anderes Problem ist auch noch und zwar wüßte ich gerne, wie ich das INT-Array wieder in so eine Form bringen kann: "\xAA\xAA\x68\x04\x04........", weil es ja so funktioniert hatte in Verbindung mit WriteFile.
Vielen Dank schonmal im Voraus,
MfG
MTC
-
Als erstes würde ich dir raten, dass du dir mal das anschaust: http://www.c-plusplus.net/forum/viewtopic.php?t=39312
Das hilft dir vielleicht weiter wegen der seriellen Kommunikation
Dann etwas zur seriellen Kommunikation allgemein:
Seriell heißt ja, dass etwas einzeln übergeben wird. An der seriellen Schnittstelle wird also jedes Zeichen einzeln übertragen. Daher ist es normalerweise(!) egal, ob du nun bei einer Funktion zum Übertragen alle Zeichen sofort angibst oder einzeln. Da du aber anscheinend Probleme beim Senden von einzelnen Zeichen mit WriteFile() hast, rate ich dir, dass du gleich alles an WriteFile() übergibst (Anscheinend macht WriteFile() noch ein wenig mehr als nur die Zeichen an die serielle Schnittstelle zu übergeben ;)).Was mich zum nächsten Punkt (Rat) bringt:
Ersetze mal dein int vor sende[] mit einem char und dann übergib sende[] direkt an WriteFile()
-
hmmm
ich würde zuerst einmal eine header-datei für die serielle schnittstelle includen, dann wird die kommunikation einfacher, und dann mal nach den specs für die solaranlage gucken, baud von 1200 sieht mir arg niedrig aus, und evtl kommen die daten zu schnell vom port. könnte gut möglich sein das du noch ein
_sleep
mit einbauen musst, und ich würde die daten über einen pointer senden, der auf den anfang des feldes zeigt und dann in einer schleife erhöht wird
-
@chRis
Das mit den Baud könnte ja noch ein guter Rat sein, aber der Rest. Außerdem bist du ca. ein halbes Jahr zu spät dran.