Wysyłanie i odbieranie ramek po RS232

0

Witam

Mam problem z komunikacją po rs232.
Nie potrafię zmusić programu aby wysyłał i odbierał dane z rs.

Program ma za zadanie wysłać zapytanie do urządzenia, pobrać 1 ramkę, wyświetlić wynik i przejść do następnego zapytania.
Generalnie są 3 zapytania.

Zapytanie 1 - status
Zapytanie 2 - waga
Zapytanie 3 - waga_tymczasowa

Zrobiłem już jakąś transmisję ale zdarza się że dane ze statusu trafiają do wagi, wynik wagi jest zafałszowany.
Wydaje mi się że problem polega na buforze. Mam wrażenie że gdy przechodzę do zapytania 2 to przychodzi ramka ze statusu.

Funkcje potrzebne do RS232

int __fastcall Read_Comm(HANDLE hComm,
                         LPDWORD lpNumberOfBytesRead, DWORD Buf_Size)
{
    DWORD nNumberOfBytesToRead;

    ClearCommError(hComm, &Errors ,&Stat);

    if (Stat.cbInQue > 0)
      {
        if (Stat.cbInQue > Buf_Size)
            nNumberOfBytesToRead = Buf_Size;
          else
            nNumberOfBytesToRead = Stat.cbInQue;

        ReadFile(hComm, &Buffer_I[0], nNumberOfBytesToRead,
                 lpNumberOfBytesRead, NULL);
      }
      else
        *lpNumberOfBytesRead = 0;
    return TRUE;
} 

Zapytanie 1 - Status

 void sprawdzStatus()
    {
        FlushFileBuffers(hComm);
        WriteFile(hComm, status, sizeof status, &RS_ile, 0);
        Read_Comm(hComm, &Number_Bytes_Read, sizeof(Buffer_I));
        Sleep(100);
        if (Buffer_I[0] == 02 && Buffer_I[1] == 03 && Buffer_I[2] == 04 && Buffer_I[3] == 00 && Buffer_I[4] == 00 && Buffer_I[5] == 00 && Buffer_I[6] == 03) {
             status_wagi = true;
        }
        if (Buffer_I[0] == 02 && Buffer_I[1] == 03 && Buffer_I[2] == 04 && Buffer_I[3] == 00 && Buffer_I[4] == 00 && Buffer_I[5] == 00 && Buffer_I[6] == 01) {
             status_wagi = false;
        }
        blokada_pomiaru = false;
    }

Zapytanie 2 - Waga

void licznikGlowny()
{
     FlushFileBuffers(hComm);
     WriteFile(hComm, wagaGlowna, sizeof wagaGlowna, &RS_ile, 0);
     Read_Comm(hComm, &Number_Bytes_Read, sizeof(Buffer_I));
     Sleep(100);
     wynik2=(Buffer_I[4]*65536)+(Buffer_I[5]*256)+Buffer_I[6];
} 

I teraz w Timer co określony czas wywołuję funkcję.

void __fastcall TForm3::Timer1Timer(TObject *Sender)
{
    zmienna++;
    if(zmienna >= 5) zmienna = 0;

    if (zmienna == 2) {
         licznikGlowny();
    }
    if (zmienna == 4) {
         sprawdzStatus();
    }
} 
0
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <cmath>

#include "Unit3.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
#define cbOutQueue 8          //rozmiar bufora danych wyjściowych
#define cbInQueue  8          //rozmiar bufora danych wejściowych
TForm3 *Form3;
    unsigned char    Buffer_O[cbOutQueue]; // bufor danych wyjściowych
    unsigned char    Buffer_I[cbInQueue]; // bufor danych wejściowych
    DWORD   Number_Bytes_Read; // liczba bajtów do czytania
    char statuss;
    static DCB dcb;
    char hex[6] = {0x02,0x03,0x00,0x02,0x00,0x02};
    char status[6] = {0x02,0x03,0x00,0x04,0x00,0x02};
    char wagaGlowna[6] = {0x02,0x03,0x00,0x02,0x00,0x02};
    char stat[8];
    HANDLE hComm;
    char lpBuffor_read[8], lpBuffor_write[8];
    DWORD RS_ile;
    bool abContinue = true;
    int isRead = false;
    bool CommFlag;
    DWORD   fdwEvtMask;    // informacja o aktualnym stanie transmisji
    COMSTAT Stat;             // dodatkowa informacja o zasobach portu
    DWORD   Errors;           // reprezentuje typ ewentualnego błędu
    int liczba0 = 12.5;
    int mod0, mod1, mod2, mod3, mod4, mod5, mod6, mod7, mod8,wynik1;
    unsigned char mo0, mo1, mo2, mo3, mo4, mo5, mo6, mo7, mo8, wynik;
    unsigned char mmo0, mmo1;
    double wynik2;
    char wynikk[6];
    bool status_wagi, blokada_pomiaru, blokada_pomiaruwagi = false;
    int zmienna;

//---------------------------------------------------------------------------
0

ściągnij http://www.serial-port-monitor.com/ zainstaluj i zobacz co jest wysyłane do urządzenia

0

Monitor RS pokazuje dane tak trzeba.

Jak mogę sprawdzić czy transmisja się zakończyła.

1

co to wg Ciebie znaczy transmisja się zakończyła.
Jaki to typ wagi? Z doświadczenia mogę powiedzieć, że część urządzeń wymaga znaku końca linii 0D 0A po każdej komendzie co nie zawsze znajduje się w dokumentacji.

0

Generalnie waga odpowiada ładnie gdy wywołuję tylko jedno zapytanie.

Chciałbym tak zrobić żeby po wywołaniu funkcji sprawdzStatus() odebrał dane sprawdził czy jeszcze coś idzie jak nie to wywołaj drugą funkcję licznikGlowny(); i tak w koło.

Wtedy nie powinno być sytuacji że na wysłane zapytanie np sprawdzenie statusu przychodzi odpowiedz na zupełnie inne zapytanie.

0

to z czym masz w końcu problem bo piszesz, że waga odpowiada

0

No waga odpowiada, chciałbym żeby odbieranie danych było tylko w określonym czasie.

Wysyłam ramkę o status-> czekam 5 sekund w tym czasie odbieram dane-> zamykam możliwość odbierania danych->Wysyłam ramkę o wagę-> otwieram możliwość odbierania danych-> czekam 5 sekund w tym czasie odbieram dane->zamykam możliwość odbierania danych-> itd

0

to tak nie działa - po jednej stronie masz komputer i tutaj masz jakieś pole manewru ale po drugiej stronie masz wagę i na nią nie masz wpływu. Nie możesz założyć, że np. po 5 sekundach to jak Ci waga odpowie to będzie za późno. Waga po prostu Ci coś odeśle i ją to nie interesuje co z tą odpowiedzią zrobisz. Nie wiem jaki masz model wagi (nie napisałeś) ale większość z jakimi miałem do czynienia (min. radwag, fawag, rhewa, axis, digi, mettler toledo) odpowiadają w taki sposób, że wiadomo na jaki rozkaz (albo kod rozkazu jest w ramce odpowiedzi albo są po prostu różne ramki). Inna sprawa, że nie zdarzyło mi się żebym musiał czekać dłużej na odpowiedź od wagi niż kilka - kilkanaście milisekund (oczywiście o ile nie było żadnego błędu po drodze)

0

Typ wagi to WMTP

No dobrze ale skąd mogę wiedzieć że dane przyszły już całe, w monitorze portu widzę że przyszło ale czy jest jakaś flaga którą mogę badać.

W tej wadze aby odczytać dane które mnie interesują muszę wysłać 3 różne ramki.
W odpowiedzi dostaje ramki, które są bardzo podobne do siebie, np. ramka odpowiedzi o statusie wygląda tak 02 03 04 00 00 00 01 08 F3, ramka odpowiedzi z wagą wygląda tak 02 03 04 00 00 04 23 8A 2A.

Teraz jak je rozróżniać i interpretować.
Czy rozwiązanie poniżej wystarczy na złapanie całej ramki.

        WriteFile(hComm, status, sizeof status, &RS_ile, 0);
        Read_Comm(hComm, &Number_Bytes_Read, sizeof(Buffer_I)); 

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0