Forum: PC-Programmierung Problem serielle Schnittstelle


von evi (Gast)


Lesenswert?

Hi,

ich habe ein merkwürdiges Problem mit meiner seriellen Schnittstelle.
Nachdem mein PC hochgefahren ist, muss ich immer einmal Hyperterminal 
starten, damit mein C++ Programm funktioniert. Dann funktioniert aber 
mein C++ programm solange bis ich den PC neu starte. Daher vermute ich, 
dass es am Init der Schnittstelle liegt.

Meine Init (aus dem C++ Forum):
1
bool CSERIELL::Init(int iPort=3, int iBaud=9600, int iSize=8, int iParity=0, int stopbit=1, int fRtsControl=0, int iTimeout=0, int iTotalTimeout=0)
2
{
3
    char port[]= "COM0123456789:";          
4
    sprintf(port, "COM%i:", iPort);
5
           
6
    m_hPort = CreateFile(   port,
7
        GENERIC_READ | GENERIC_WRITE,
8
        0,
9
        NULL,
10
        OPEN_EXISTING,
11
        FILE_ATTRIBUTE_NORMAL,
12
        NULL);
13
    if((int)this->m_hPort == -1)         //COMx ist nicht vorhanden
14
            this->m_hPort=0;
15
    if(this->m_hPort !=0)                    
16
    {
17
        COMMTIMEOUTS comtime;  
18
        GetCommTimeouts(this->m_hPort, &comtime);
19
        comtime.ReadIntervalTimeout= iTimeout;
20
        comtime.ReadTotalTimeoutConstant= iTotalTimeout;
21
        comtime.WriteTotalTimeoutConstant= iTotalTimeout;
22
        comtime.ReadTotalTimeoutMultiplier=2;
23
        comtime.WriteTotalTimeoutMultiplier=0;
24
        SetCommTimeouts(this->m_hPort, &comtime);
25
26
        DCB dcb;           //Gerätekommunikationsanpassung
27
        GetCommState(this->m_hPort, &dcb);
28
        dcb.BaudRate= iBaud;
29
        dcb.ByteSize= iSize;
30
        dcb.DCBlength= 28;
31
        dcb.EofChar= 0;
32
        dcb.ErrorChar= 0;
33
        dcb.fRtsControl= fRtsControl;
34
        dcb.Parity= iParity;
35
        dcb.StopBits= stopbit;
36
        dcb.fInX=0;
37
        dcb.fOutX=0;
38
        dcb.fAbort O n E r r o r = 1;  //Bitte hier die leerzeichen
39
                // wegmachen. Vermutlich Bug im Forum
40
    SetCommState(this->m_hPort, &dcb);
41
    return true;

beim Hyperterminal verwende ich 9600-N-1.

gruß

evi

von Peter II (Gast)


Lesenswert?

laden mal voher die alten einstellungen mit
GetCommState
(gleich nach DCB dcb; )

dann änderst du wie werte wie du es jetzt machst, und dann wieder 
speichern mit SetCommState

von Volker Z. (vza)


Lesenswert?

Versuchsmal mit:
1
{
2
    char port[]= "COM0123456789:";          
3
    sprintf(port, "\\\\.\\COM%i", iPort);
4
...

Aber erkläre mal, was heißt: "Funktioniert nicht"

Volker

von Volker Z. (vza)


Lesenswert?

evi schrieb:
> if((int)this->m_hPort == -1)         //COMx ist nicht vorhanden
>             this->m_hPort=0;
>     if(this->m_hPort !=0)
>     {

Anstelle dieser merkwürdigen Konstruktion könnte Dir,
je nach dem in welcher Umgebung du deine Objekt laufen lässt,
der folgende Code hilfreich sein:
1
  if(m_hPort == INVALID_HANDLE_VALUE)
2
  {
3
    error = GetLastError();
4
    switch(error)
5
    {
6
    case 2  : 
7
      sprintf(str,"Open(%s) not exist.\n",device); 
8
      break;
9
    case 5  : 
10
      sprintf(str,"Open(%s) Access is denied (is open).\n",device); 
11
      break;
12
    default :
13
         sprintf(str,"Open(%s) Error=0x%08lx.\n",device,error);
14
    }
15
    printf(str);
16
    return FALSE;
17
  }

von evi (Gast)


Lesenswert?

hi,

danke schonmal für die ganzen antworten.

@Peter II: welche alten einstellungen meinst du?

@Volker: Habe ich probiert hat aber leider nicht geholfen :-( trotzdem 
danke.

Mit fehler meine ich: Ich schicke daten von meinem PC los, nur leider 
reagiert die Schaltung nicht. Wenn ich dann Hyperterminal starte und 
daten schicke,  kommen die bei der Schaltung an. Danach starte ich mein 
Programm wieder und dann kommen auch dessen daten an.
Wenn ich beide programm gleichzeitig starte beschweren sie sich auch, 
dass der Port schon belegt ist.

Außerdem habe ich auch nochmal deine Fehlerabfrage eingefügt, aber sie 
wird garnicht erst aufgerufen. Mein Programm scheint auch überall die 
richtigen Abzweigungen zu nehmen. Ich habe bei mir noch einige TRACE 
anweisungen eingefügt und weiß daher, dass alle Bedingungen erfüllt 
werden.

danke schonmal für die Hilfe

habt ihr noch ideen woran es liegen könnte??

von Peter II (Gast)


Lesenswert?

evi schrieb:
> @Peter II: welche alten einstellungen meinst du?

die vom System vorgeben sein. Du legst mit DCB dcb;  eine leere konfig 
an. Ich lese danach immer zu erst die aktuellen Daten aus und ändere 
dann nur. Da du aber bei 0 anfängst und eventuell einen Wert vergisst zu 
setzen kann das zu diesen effekt führen.

von DirkB (Gast)


Lesenswert?

Was für ein Kabel ist denn zwischen den Geräten?

Hyperterm wird eine der Steuerleitungen anders ansprechen. (DTR, CTS 
...)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

1
        DCB dcb;           //Gerätekommunikationsanpassung
2
        GetCommState(this->m_hPort, &dcb);

Hier fehlt die Initialisierung von /dcb/:
1
        DCB dcb;           //Gerätekommunikationsanpassung
2
3
        memset(&dcb, 0, sizeof (dcb));
4
5
        dcb.DCBlength = sizeof (dcb);
6
7
        GetCommState(this->m_hPort, &dcb);

von Volker Z. (vza)


Lesenswert?

> Mit fehler meine ich: Ich schicke daten von meinem PC los, nur leider
> reagiert die Schaltung nicht.

Also das Öffnen des Ports geht ohne Fehler und Du kannst senden?
Wie hast Du das verifiziert?
Was ist der Rückgabewert von WriteFile(...) ?

Wenn du Senden kannst (im richtigen Format), liegt der Fehler nicht beim 
Öffnen des Ports.

Sicherheitshalber würde ich aber noch die beiden Funktionen
1
ClearCommError(...); PurgeComm(...);
aufrufen.

Volker

von evi (Gast)


Lesenswert?

@Peter II: okay macht sinn. Leider weiß ich nicht genau, wie ich die 
Systemeinstellungen auslese (sorry bin noch anfänger). Könntest du mir 
da nochmal einen tip geben. Danke

@Dirk: ich verwende ein USB Kabel. Signalkette ist so:
PC( mit Virtual com treiber) -> USB Kabel-> ft232-> µC. Müsste 
eigentlich klappen. Ich kann ja auch daten senden, nur leider nicht von 
anfang an ;-).

@Rufus: ich habe die Zeilen von dir eingefügt. hat aber leider zu keiner 
verbesserung bei getragen.

von DirkB (Gast)


Lesenswert?

Versuch doch mal hterm. (nicht Hyperterm)
Da kannst du die Steuerleitungen sehen und mit rumspielen.

von evi (Gast)


Lesenswert?

@ Volker: also das Problem ist halt nur das sende bevor ich einmal das 
Hyperterminal gestarte habe. Einmal Hyperterminal benutzt, danach kann 
ich wieder mein c++ programm öffnen und solange und soviele daten 
schicken wie ich will. Die kommen auch richtig bei der Schaltung an.

daher gehe ich davon aus, dass das hyperterminal noch irgendwas 
einstellt oder macht, was ich vergessen habe. oder das ich an einer 
stell einen fehler habe.

Habt ihr noch irgendeine idee woran es liegen könnte?

lg evi

von Volker Z. (vza)


Lesenswert?

Sendet dein Programm nun oder nicht?
Wie hast Du das Festgestellt?

Hast Du dein Programm im Debugger laufen?
Setze mal Breakpoints.

Volker

von Uwe (Gast)


Lesenswert?

Wird sich schon finden ! Aber du kannst doch auch die DLL von FTDI 
benutzen dann kannste dir das Comport Progen sparen. Die hat noch 
zusätliche Features und kann zum Beispiel auch Baudraten einstellen wie 
3141592 Baud auch kann man dann das Gerät über den Namen öfnen und 
braucht sich nicht um die von Windows vergebene Commport Nummer zu 
kümmern.
http://www.ftdichip.com/Support/Documents/ProgramGuides/D2XX_Programmer%27s_Guide%28FT_000071%29.pdf

von evi (Gast)


Lesenswert?

@volker: also das Programm läuft eigentlich. Nur wenn ich den Pc 
neustarte und probiere daten zu senden kommen die nicht an (schaltung 
macht nichts). Wenn ich dann Hyperterminal starte, eine Verbindung mit 
der Schaltung herstelle und danach wieder Hyperterminal beende, dann 
kann ich danach auch mit meinem c++ programm daten senden. sooft und 
solange ich will. Ich kann zwischendurch auch die Schaltung ausschalten 
und wieder an, es funktioniert immer. Wenn ich den Pc neustarte 
funktioniert es wieder nicht.

Daher denke ich, dass ich bei der Schnittstelle irgendwas vergessen habe 
zu setzen.

habe das programm im debugger laufen. werde mal gucken ob ich irgendwas 
mit breakpoints rausfinde.

habt ihr sonst noch ideen?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

evi schrieb:
> @Rufus: ich habe die Zeilen von dir eingefügt. hat aber leider zu keiner
> verbesserung bei getragen.
1
        dcb.DCBlength= 28;

Mach das weg. Das ist aus zweierlei Gründen falsch: Einerseits, was ist 
28? Andererseits ist, wenn Du vor dem Aufruf von GetCommState die 
Struktur richtig initialisierst, dieses Feld sowieso auf den korrekten 
Wert gesetzt.

von evi (Gast)


Lesenswert?

@rufus: habe ich schon nach deinem ersten beitrag gemacht. Trotzdem 
danke

von Uwe (Gast)


Lesenswert?

Benutz die DLL

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Uwe schrieb:
> Benutz die DLL

Also nicht das Problem lösen, sondern es umgehen?

Halt ich nicht für einen sinnvollen Ansatz.

evi schrieb:
> @rufus: habe ich schon nach deinem ersten beitrag gemacht.

Dann poste doch bitte mal den aktuellen Stand Deines Codes. Es ist ja 
nicht so, daß es nicht möglich ist, eine serielle Schnittstelle unter 
Windows zu nutzen, das haben schon ganz andere hinbekommen.

von Karl H. (kbuchegg)


Lesenswert?

und gewöhn dir an, die Returnwerte der Funktionen auszuwerten.
Wenn, wie im Falle von SetCommState die Funktion einen BOOL zurückgibt, 
dann reicht es schon, wenigstens eine MessageBox mit "Fehler" drinn 
auszugeben, wenn die Funktion FALSE liefert.

Wer Returnwerte ignoriert bzw in einer Debug Version nicht wenigstens 
meldet (und sei es nur mit einem ASSERT, so dass der Debugger stehen 
bleibt) und hinterher jammert, dass nichts funktioniert, kriegt von mir 
kein Mitleid. Er kriegt höchstens ein mitleidiges Lächeln gepaart mit 
einem "selber Schuld wenn du stundenlang Fehler suchst"

von Uwe (Gast)


Lesenswert?

Nö ist einfach eleganter mit dll.

von Peter II (Gast)


Lesenswert?

Uwe schrieb:
> Nö ist einfach eleganter mit dll.

woher weisst du überhaupt das es ein FTDI umsetzer ist? Es gibt auch 
leute die habe noch eine echte COM-Schnittstelle.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Uwe schrieb:
> Nö ist einfach eleganter mit dll.

Ist es überhaupt nicht, weil damit nur die von der DLL unterstützten 
USB-Seriell-Bridges verwendbar sind, nicht aber serielle Schnittstellen 
allgemein.

Solange nicht irgendwelche Spezialiäten betrieben werden, die zwingend 
auf Funktionen der FTDI-Bausteine zugreifen (Auslesen der Seriennummer, 
Ansteuern der MPSSE oder Bitbanging), ist es definitiv nicht ratsam, 
die DLL zu nutzen.

Und die Hoffnung, daß der Threadstarter hier seine 
7287884731894789234ste Implementierung der Ansteuerung serieller 
Schnittstellen über die Win32-API noch richtig auf die Beine bekommt, 
die will ich noch nicht aufgeben.

von Dennis H. (c-logic) Benutzerseite


Lesenswert?

Wenn es dir nicht zu aufwendig ist, installiere doch mal die freie 
Version von Serialport Monitor und schaue mal deinem Programm und 
Hyperterminal über die Schulter.
Das hat bei mir auch schon bei manchen Problemen geholfen.
Möglich das vielleicht einfach nur was am Protokoll nicht richtig 
eingestellt ist.

Gruß Dennis

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.