Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[C++Builder] RS232 - odbiór danych, zdarzenia

arkady25 05 Wrz 2010 08:03 1089 0
  • #1 05 Wrz 2010 08:03
    arkady25
    Poziom 16  

    Witam,

    tworzę aplikację komunikującą się z urządzeniem za pomocą komend AT.
    Po przewertowaniu połowy internetu, przeczytaniu i wykorzystaniu przykładów z książki Daniluka "RS232C Praktyczne programowanie ..." nadal mam problem z właściwym odbiorem danych.
    Na obecną chwilę opierając się głównie na przykładach z w/w książki potrafię wysłać komendę/zapytanie i za chwilę odebrać odpowiedź oraz ją zinterpretować.
    Robię to za pomocą poniższego kodu:

    Code:

    //---------------------------------------------------------------------------
    #include <vcl.h>
    #include <math.h>
    #include <stdio.h>
    #include <string.h>
    #include <IniFiles.hpp>
    #include <fstream.h>

    #pragma hdrstop

    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    #define cbOutQueue 64      //rozmiar bufora danych wyjściowych
    #define cbInQueue  64      //rozmiar bufora danych wejściowych

    TForm1 *Form1;
        LPCTSTR query_mode = "A"; //"\x1b\x11\x01";    // zapytanie o stan
        LPCTSTR query_count = "B"; //"\x1b\x11\x06";   // zapytanie o stan licznika
        int         i;
        char    Buffer_O_COM[cbOutQueue]; // bufor danych wyjściowych
        byte    Buffer_I_COM[cbInQueue];  // bufor danych wejściowych
        DWORD   Number_Bytes_Read;          // liczba bajtów do czytania
        HANDLE  hCommDev;                   // identyfikatory portów
        LPCTSTR lpFileName;                 // przechowuje nazwę portu
        DCB     dcb;                        // struktura kontroli portu szeregowego
        DWORD   fdwEvtMask;
        COMSTAT Stat;
        DWORD   Errors;
        BOOL    bResult = TRUE;
        BOOL    bResult_Save;
        int     hThread_SR_COM;
        unsigned  uThreadID_SR_COM;
    //  -   menu
        FILE *pstream1;                     // wskaźnik do pliku
        long file_length;
    //--------------------------------------------------------------------
    void __fastcall TForm1::FormCreate(TObject *Sender)
    {




    TIniFile *StartUp = new TIniFile("\\ustawienia.ini"); //plik z ustawieniami w katalogu głównym
    }
    //---------------------------------------------------------------------------
    int __fastcall Write_Comm(HANDLE hCommDev, LPCVOID lpBuffer,
                              DWORD nNumberOfBytesToWrite)
    {
       DWORD NumberOfBytesWritten;
       if (WriteFile(hCommDev, lpBuffer, nNumberOfBytesToWrite,
                     &NumberOfBytesWritten , NULL) > 0)
         {
           WaitCommEvent(hCommDev, &fdwEvtMask, NULL);
           return TRUE;
          }
          else
             return FALSE;
    }
    //--------------------------------------------------------------------
    int __fastcall Read_Comm(HANDLE hCommDev, LPVOID lpBuffer, LPDWORD
                             lpNumberOfBytesRead, DWORD Buf_Size)
    {
        DWORD nNumberOfBytesToRead;
        ClearCommError(hCommDev, &Errors ,&Stat);
        if (Stat.cbInQue > 0)
          {
            if (Stat.cbInQue > Buf_Size)
                nNumberOfBytesToRead = Buf_Size;
              else
                nNumberOfBytesToRead = Stat.cbInQue;
            ReadFile(hCommDev, lpBuffer, nNumberOfBytesToRead,
                     lpNumberOfBytesRead, NULL);
          }
          else
            *lpNumberOfBytesRead = 0;
        return TRUE;
    }
    //---------------------------------------------------------------------------
    int __fastcall RS_Send_Receive_COM(Pointer Parameter)
    {
    //pstream1 = fopen("Data14.txt","a+");
     //  Pytanie o tryb pracy
     do {
    /*     strcpy(Buffer_O_COM, query_mode);
         for (i = 0; i <= cbInQueue - 1; i++)
              Buffer_I_COM[i] = NULL;
         do {
            FlushFileBuffers(hCommDev);
            }while (Write_Comm(hCommDev, Buffer_O_COM,
                  strlen(Buffer_O_COM)) == 0);
         Sleep(100);
         Read_Comm(hCommDev, &Buffer_I_COM[0], &Number_Bytes_Read,
                    sizeof(Buffer_I_COM));
         if (Number_Bytes_Read > 0)
            {
              if (Buffer_I_COM[0] == -16)
              if (Buffer_I_COM1[1] == -16)
              if (Buffer_I_COM1[5] == -16)
               
                {
              switch(Buffer_I_COM[6])
                {
               // case 0: Form1 -> Tryb14 -> Text = "Inicjalizacja"; break;
               // case 1: Form1 -> Tryb14 -> Text = "Tryb Jałowy"; break;
                };
              }
            };
     */
    //  Pytanie o licznik
    //     strcpy(Buffer_O_COM, query_count);
    //     do {
    //        FlushFileBuffers(hCommDev);
    //        }while (Write_Comm(hCommDev, Buffer_O_COM,
    //              strlen(Buffer_O_COM)) == 0);
         Sleep(1000);
         Read_Comm(hCommDev, &Buffer_I_COM[0], &Number_Bytes_Read,
                    sizeof(Buffer_I_COM));
         if (Number_Bytes_Read > 0)
            {
    //       for (i=0; i<6; i++)
    //            Buffer_I_COM[i] = 32;
    //       Form1 -> Licznik -> Text = "     ";
    //       Form1 -> Licznik -> Text = Buffer_I_COM;
            };
         }while (bResult);  // koniec nadrzędnego DO
       return TRUE;
    }
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    int i;

        lpFileName =  "\\\\.\\COM30";
        hCommDev = CreateFile(lpFileName, GENERIC_READ |
                   GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
        if (hCommDev != INVALID_HANDLE_VALUE)
          {
            SetupComm(hCommDev, cbInQueue, cbOutQueue);
            dcb.DCBlength = sizeof(dcb);
            GetCommState(hCommDev, &dcb);
              dcb.BaudRate = CBR_115200;
              //dcb.BaudRate = CBR_9600;
              dcb.Parity = NOPARITY;            // ustawienie parzystości
              dcb.StopBits = ONESTOPBIT;        // bity stopu
              dcb.ByteSize = 8;                 // bity danych
            //-przykładowe ustawienia flag sterujących DCB-
              dcb.fParity = TRUE;
              dcb.fDtrControl = DTR_CONTROL_DISABLE;
              dcb.fRtsControl = RTS_CONTROL_DISABLE;
              dcb.fOutxCtsFlow = FALSE;
              dcb.fOutxDsrFlow = FALSE;
              dcb.fDsrSensitivity = FALSE;
              dcb.fAbortOnError = FALSE;
              dcb.fOutX = FALSE;
              dcb.fInX = FALSE;
              dcb.fErrorChar = FALSE;
              dcb.fNull = FALSE;
            SetCommState(hCommDev, &dcb);
            GetCommMask(hCommDev, &fdwEvtMask);
            SetCommMask(hCommDev, EV_TXEMPTY);
            StatusBar1->Panels->Items[0]->Text = lpFileName;
            for (i = 0; i <= cbInQueue - 1; i++)
              {
               Buffer_O_COM[i] = NULL;
               Buffer_I_COM[i] = NULL;
              }
          }
          else
            {
             switch ((int)hCommDev)
               {
                case IE_BADID:
                  MessageBox(NULL, "Niewłaściwa nazwa portu COM lub port jest"
                             " aktywny.", "Błąd", MB_OK);
                  break;
               };
             }
    }
    //----------------------------------------------------------------------------
    int Close_Comm(HANDLE hCommDev)
    {
        CloseHandle(hCommDev);
        return TRUE;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::RozpocznijClick(TObject *Sender)
    {
    //******************  uruchomienie transmisji  *****************

        if (hCommDev > 0)   // powtórnie sprawdza czy port jest otwarty
        {
            for (i = 0; i <= cbInQueue - 1; i++)
                {
                Buffer_O_COM[i] = NULL;
                Buffer_I_COM[i] = NULL;
                }
            hThread_SR_COM = BeginThread (NULL,0,RS_Send_Receive_COM,NULL,0,uThreadID_SR_COM);
            Rozpocznij->Enabled = false;
        }
        else
            MessageBox(NULL, "Port nie został otwarty do transmisji.","Błąd", MB_OK);
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::OdczytajClick(TObject *Sender)
    {
    Read_Comm(hCommDev, &Buffer_I_COM[0], &Number_Bytes_Read, sizeof(Buffer_I_COM));
         if (Number_Bytes_Read > 0)
            rysuj_przebiegi();
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Zamknij1Click(TObject *Sender)
    {
    SuspendThread((HANDLE)hThread_SR_COM);
    fclose(pstream1);
    Close_Comm(hCommDev);
    Application->Terminate();
    }
    //---------------------------------------------------------------------------


    Natomiast nie wiem jak ugryźć odbiór wiadomości samoczynnie wysłanych przez urządzenie. Wypadało by reagować natychmiast, a nie po sekundzie pomiędzy zapytaniami (Sleep(1000)).
    Chodzi mi po głowie przekopiowanie zawartości bufora wejściowego do jakiejś tablicy jeśli pojawi się znak końca wiersza 0x0D. Ale nie bardzo wiem jak to opracować. Czy za pomocą Timera cyklicznie sprawdzać czy przyszło 0x0D ?

    Naczytałem się o zdarzeniach, korzystaniu z różnego rodzaju bibliotek (np. SerialPort()) ale nie potrafię tego dołączyć do własnego programu. Dodatkowo na obecną chwilę nie bardzo mogę sobie wyobrazić interpretację tak odbieranych wiadomości.
    Czy opracować w jednym bloku CASE zarówno odpowiedzi na wysłane komendy/zapytania jak i komunikaty wysłane przez urządzenie ?
    Z góry dziękuję za wszelką pomoc.

    Pozdrawiam
    Arkady25

    0 0