User Login


Sie sind noch nicht eingeloggt!

     anmelden |  registrieren

Termine


08. - 10.12.2014: Frankfurt |
PLC2 - Video Signal Processing

08. - 12.12.2014: Freiburg |
PLC2 - Expert FPGA Schaltungstechnik

08. - 10.12.2014: Mnchen |
PLC2 - Compact ZYNQ for HW Designers

Boards


Spartan 6 FPGA SP605 Evaluation Kit (XC6SLX45T-FGG484)
    

Links


FPGA Hersteller:  Altera
Xilinx
Lattice
FPGA Schulungen:  PLC2
El Camino
Trias
Weiteres:  VHDL ORG

Literatur


Dieter Wecker

Prozessorentwurf

Jahr: 2015
ISBN-10: 3110 4029 63

2. Beispiel für CPP

Eine einfache Möglichkeit Daten mit einem Gerät auszutauschen.

2. Beispiel für CPP

Beitragvon Thomas » Mi 24. Feb 2010, 10:15

Im Folgenden wird eine Klasse für die Kommunikation über die serielle Schnittstelle unter Verwendung des Visual Studios erstellt. Dabei wird die objektorientierte Programmierung mit C++ verwendet.

So jetzt geht es los. Als erstes legen wir in unserem Projekt eine neu Klasse an. Dabei sollte es sich um eine leere C++ Klasse handeln, es kann auch eine MFC-Bibliothekklasse (z.B. CDialog) verwendet werden. Ich verwende im Folgenden den Klassennamen C_COM_Port, damit werden automatisch folgende Dateien erstellt:

C_COM_Port.h
Code: Alles auswählen
#pragma once
class C_COM_Port
{
public:
   C_COM_Port(void);
   ~C_COM_Port(void);
}


C_COM_Port.cpp
Code: Alles auswählen
#include "StdAfx.h"
#include "C_COM_Port.h"

C_COM_Port::C_COM_Port(void)
{
}

C_COM_Port::~C_COM_Port(void)
{
}


In die Headerdatei fügen wir Folgendes ein:
Code: Alles auswählen
private:
   HANDLE   m_hPort;

m_hPort wird innerhalb der Klasse zum Zugriff auf die Schnittstelle verwendet. Damit der Variableninhalt nicht versehentlich von außen geändert wird, wird die Variable als private deklariert.
Als nächstes kommen die Methoden zum Öffnen und Schließen der Schnittstelle. Die Deklaration sieht folgendermaßen aus
Code: Alles auswählen
   void   COM_Close(void);
   bool   COM_Open(BYTE Port, int Baud, BYTE Parity, BYTE Databit, BYTE Stopbit);

Und der dazugehörige Code:
Code: Alles auswählen
void C_COM_Port::COM_Close(void)
{
  if ((m_hPort!=NULL)&&(m_hPort!=INVALID_HANDLE_VALUE))
  {
    PurgeComm(m_hPort,PURGE_TXABORT | PURGE_RXABORT |
         PURGE_TXCLEAR | PURGE_RXCLEAR);
    SetCommMask(m_hPort, 0);
    if (!CloseHandle(m_hPort))
      m_hPort   = NULL;
  }
  m_hPort   = NULL;
}

bool C_COM_Port::COM_Open(BYTE Port, int Baud, BYTE Parity, BYTE Databit, BYTE Stopbit)
{
   if ((Baud!=CBR_110)     && (Baud!=CBR_300)   &&
      (Baud!=CBR_600)     && (Baud!=CBR_1200)   &&
      (Baud!=CBR_2400)  && (Baud!=CBR_4800)   &&
      (Baud!=CBR_9600)  && (Baud!=CBR_14400)   &&
      (Baud!=CBR_19200) && (Baud!=CBR_38400)   &&
      (Baud!=CBR_56000) && (Baud!=CBR_57600)   &&
      (Baud!=CBR_115200)&& (Baud!=CBR_128000)   &&
      (Baud!=CBR_256000) ) return false;
   if ((Parity<NOPARITY)||(Parity>SPACEPARITY)) return false;
   if ((Databit<7)||(Databit>8)) return false;
   if ((Stopbit<ONESTOPBIT)||(Stopbit>TWOSTOPBITS)) return false;

   if (m_hPort!=NULL)
      COM_Close();

   CString s1;
   s1.Format("\\\\.\\COM%i", Port);
    m_hPort = CreateFile ((LPCSTR)s1, GENERIC_READ | GENERIC_WRITE,
                      0, 0, OPEN_EXISTING,
                     FILE_FLAG_NO_BUFFERING | FILE_ATTRIBUTE_NORMAL,
                      NULL);
   if ((m_hPort==NULL)||(m_hPort==INVALID_HANDLE_VALUE))
   { m_hPort = NULL; return false; }

   if (!SetupComm(m_hPort, 512, 512))
   { CloseHandle(m_hPort); m_hPort = NULL; return false; }

   if (!PurgeComm(m_hPort,PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR |       
                           PURGE_RXCLEAR))
   { CloseHandle(m_hPort); m_hPort = NULL; return false; }

   DCB      DCB_Port;
   DCB_Port.DCBlength   = sizeof (DCB_Port);
   GetCommState (m_hPort ,&DCB_Port);
   DCB_Port.BaudRate         = Baud;   
   DCB_Port.Parity            = Parity;
   DCB_Port.StopBits         = Stopbit;
   DCB_Port.ByteSize         = Databit;
   DCB_Port.EvtChar         = 0;   
   DCB_Port.fDtrControl      = DTR_CONTROL_DISABLE;
   DCB_Port.fRtsControl      = RTS_CONTROL_DISABLE;
   DCB_Port.fOutxCtsFlow      = false;         
   DCB_Port.fOutxDsrFlow      = false;         
   DCB_Port.fDsrSensitivity   = false;         
   DCB_Port.fErrorChar         = false;         
   DCB_Port.fNull            = false;         
   DCB_Port.fAbortOnError      = false;         
   DCB_Port.fParity         = true;            
   DCB_Port.fBinary         = true;            
   if (!SetCommState(m_hPort, &DCB_Port))
   { CloseHandle(m_hPort); m_hPort = NULL; return false; }

   return true;
}

Mit dem bisherigen Code sind wir in der Lage eine serielle Schnittstelle zu öffnen und parametrieren. Als nächstes kommt das Senden und Empfangen von Daten.
Thomas
 
Beiträge: 21
Registriert: Di 5. Jan 2010, 09:22

Re: 2. Beispiel für CPP

Beitragvon bertg1987 » Mi 19. Jan 2011, 10:20

Hallo Thomas,
wann geht es weiter mit der seriellen Schnittstelle :?:
Gruß
Bert
bertg1987
 
Beiträge: 6
Registriert: Fr 10. Sep 2010, 07:54

Re: 2. Beispiel für CPP

Beitragvon Thomas » Mi 19. Jan 2011, 10:48

Hallo Bert,
klar geht es weiter.
Thomas
Thomas
 
Beiträge: 21
Registriert: Di 5. Jan 2010, 09:22

Re: 2. Beispiel für CPP

Beitragvon Thomas » Mi 19. Jan 2011, 11:04

So, jetzt kommt der nächste Teil.
Die Klasse C_COM_Port wird um 2 weitere Funktioen zum Senden und Empfangen von Daten erweitert.
In der Headerdatei muss folgende Deklaration im Bereich public hinzugefügt werden:
Code: Alles auswählen
bool   COM_Send(BYTE *Data, BYTE Length);
bool   COM_Recv(BYTE Timeout, BYTE Size, BYTE *Data, BYTE &Length);


Der Code für die Sende-Funktionen sieht wie folgt aus:
Code: Alles auswählen
bool C_COM_Port::COM_Send(BYTE *Data, BYTE Length)
{
   if (!Data)   return false;   //   Parameterfehler
   if (!Length)return true;   //   keine Daten zu senden
   if ((m_hPort==NULL)||(m_hPort==INVALID_HANDLE_VALUE))
      return false;   //   kein serielle Port geöffnet

   DWORD   dw_val;
   if (WriteFile(m_hPort, Data, Length, &dw_val, NULL)==0)
      return false;   //   interner Fehler beim Senden der Daten

   return true;
}

Dabei gibt der Parameter Data eine Buffer an, der die zu sendenden Daten enthält.
Der Parameter Length gibt die Anzahl der zu sendenden Zeichen an.
Wurden alle Zeichen gesendet, liefert die Funktion ein true zurück.

Der Code für die Empfangs-Funktion ist etwas umfangreicher.
Code: Alles auswählen
bool C_COM_Port::COM_Recv(BYTE Timeout, BYTE Size, BYTE *Data, BYTE &Length)
{
   if ((!Data)||(Size<1))      return false;   //   Parameterfehler

   /// warte bis genügend Daten vorhanden sind
   clock_t to    = clock()+Timeout;
   DWORD   dw_val;
   int      recv = 0;
   do
   {
      COMSTAT   comstat;
      if (!ClearCommError(m_hPort, &dw_val, &comstat))
         return false;   
      recv = comstat.cbInQue;

   } while ((recv<Length)&&(to>=clock()));
   if (recv==0)   { Length = 0; return false;   } // nichts empfangen

   if (recv>Size)   recv = Size;
   if(!ReadFile(m_hPort, Data, recv, &dw_val, NULL))
      return false;
   Length = (BYTE)dw_val;
   return true;
}

Im Parameter Length wird der Funktion die Anzahl der angeforderten Zeichen übergeben. Sie sollte kleiner oder gleich der vorhandenen Buffergröße sein, die im Parameter Size angegeben wird. Die Empgangenen Daten werden in dem Buffer gespeichert, der im Parameter Data angegeben ist.
Der Parameter Timeout gibt die maximale Zeit an, die auf die angeforderten Daten gewartet wird. Length enthält nach Aufruf der Funktion die empfangene Anzahl an Zeichen.

Mit den bisher aufgeführtem Code ist man nun in der Lage die serielle Schnittstelle zur Steuerung von Geräten oder dem Aislesen von Daten zu nutzen.

Also viel Erfolg damit.
Thomas
Thomas
 
Beiträge: 21
Registriert: Di 5. Jan 2010, 09:22


Zurück zu Die Serielle Schnittstelle

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast

cron