Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Wysyłanie i odbieranie danych z rs232 w C

xPatryk 23 Apr 2005 10:51 22002 26
  • #1
    xPatryk
    Level 15  
    No właśnie..
    przeglądnąłem elektrodę - nic - albo bornald c++ albo delphi albo ms visual basic :(
    przeglądnąłem google - nic - najczęściej interfacy komunikacyjne przeznaczone do urządzeń fabryczynych...

    No to postanowilem spytac,
    jak najprosciej czytac z portu rs232 i do niego zapisywac (z poziomu C a nie C++)...

    I prosze nie polecać książki "Programowanie praktyczne Rs232...", bo ją przczytałem i nadal nic ciekawego odnośnie C z niej nie wynikło...

    Proszę o wszystkie sugestie, uwagi i przykłady gotowych funkcji
    Pozdrawiam
    Patryk
  • #2
    mentyl
    Level 14  
    Opisz dokładniej na jaką platformę chcesz pisać WINDOWS, UNIX, MAC, uC .. czy jaką?
  • #3
    elektryk
    Level 42  
    xPatryk wrote:
    z poziomu C a nie C++
    Jakbyś rozumiał różnice między C++ a C to byś zauważył że podane przykłady są napisane w C.
  • #4
    xPatryk
    Level 15  
    naprawde Elektryku?

    pierwszy lepszy kod - 3 linijka:
    Code:
    using namespace std;
    ,
    budowa obiektowa, zakladki,
    no i wiekszosc uzywa windows API, a tego chcialbym uniknac, bo calosc ma dzialac pod linuxem...
  • #5
    KeinXor
    Level 24  
    Witam i dołanczam się do pytania... prosze o jakiś przykład komunikacji przez rs232.
    pozdro
  • #6
    xPatryk
    Level 15  
    hmm... ja rozwiązełem ten problem w sposób może dosyć prozaiczny, ale najprostszy -

    ./program.o < /dev/ttyS0 > /dev/ttyS0 - program zamiast na standardowe wyjscie kieruje wyniki bezposrednio na port...

    pomijam wiele wad takiego rozwiazania - ma ono jedna zalete - jest proste...
  • #9
    antyBrygadaW
    Level 15  
    a może wiecie jak zrobić to w WinAPI C?

    P.S. a może wiecie jak zrobić komunkację przez USB?
  • #10
    fantom
    Level 31  
    antyBrygadaW wrote:
    a może wiecie jak zrobić to w WinAPI C?

    P.S. a może wiecie jak zrobić komunkację przez USB?

    Tak wiemy ale poniewaz jak sam w innym temacie pisales dopiero zaczynasz pisac w WinAPI wiec ta wiedza i tak ci sie na nic nie przyda (na razie).Poki co dostales literature do RS-a ("Praktyczne programowanie ...") no i jak ci sie uda zdobyc to mozesz zajrzec do "USB Complete".
  • #11
    maciek11
    Level 17  
    Też dopiero zaczynam programować z użyciem WinAPI, ale wystarczy mi tylko wiedzieć jak zainicjować port i wysłać jakieś słowo po linii, albo ustawić odpowiednie stany na liniach portu.

    Dodano po 16 [minuty]:

    Zapomniałem zapytać: Czy miałby ktoś książkę RS232 praktyczne programowanie w formacie pdf. Jeśli tak to proszę o e-mail: mpankowiec(malpa)o2.pl Z góry dziękuję.
  • #12
    fish26
    Level 13  
    Witaj,
    poniżej wkleiłem przykładowy kod z RS

    Code:

    #include <windows.h>
    #include <stdio.h>

    int main(int argc, char** argv)
    {
        HANDLE hCom;      //uchwyt portu
        DCB dcb;         //konfiguracja portu
        BOOL fSuccess;      //flaga pomocnicza
       BYTE RS_buf;      //bufor danej
       DWORD RS_ile;      //ilosc bitow wyslanych
       
       //otwarcie portu COM1 z prawami RW
        hCom = CreateFile( TEXT("COM1"), GENERIC_READ | GENERIC_WRITE,
            0,    // exclusive access
            NULL, // default security attributes
            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
       
        if (hCom == INVALID_HANDLE_VALUE)
        {
            printf("CreateFile failed with error %d.\n", GetLastError());
            return 1;
        }

       //pobranie aktualnych ustawien portu
        fSuccess = GetCommState(hCom, &dcb);
        if (!fSuccess)
        {
          printf ("GetCommState failed with error %d.\n", GetLastError());
          return 2;
        }
       
       //ustawienie naszej konfiguracji
       dcb.BaudRate = CBR_19200;     // predkosc transmisji
       dcb.ByteSize = 8;             // ilosc bitow danych
       dcb.Parity = NOPARITY;        // brak bitu parzystosci
       dcb.StopBits = TWOSTOPBITS;    // dwa bity stopu

       fSuccess = SetCommState(hCom, &dcb);

       if (!fSuccess)
       {
          printf ("SetCommState failed with error %d.\n", GetLastError());
          return 3;
       }
       
       //wyslanie 1 bajta przez RS
       RS_buf='a';
        fSuccess = WriteFile( hCom, &RS_buf, 1, &RS_ile, 0);
        if (!fSuccess)
        {
          printf ("WriteFile failed with error %d.\n", GetLastError());
          return 4;
        }

       while(1)
       {           
            fSuccess = ReadFile( hCom, &RS_buf, 1, &RS_ile, 0);
            if (!fSuccess)
            {
                printf ("ReadFile failed with error %d.\n", GetLastError());
                return 5;
            }
          
          if(RS_ile==1)
          {
             if(RS_buf == 1)   break;
             printf("%c", RS_buf);
          }
       }
       return 0;
    }
  • #14
    Rinoko
    Level 1  
    Dzieki Ci fisz26 za kod :) Wszedzie takiego szukałem. Z jakiego źródła jest on zaczerpniety ?
  • #15
    Fyszo
    Level 37  
    Kubbaz wrote:
    Hej
    a co zrobić/zmienić, aby kod/program działał na porcie COM5 ?? i to w dodatku na adapterze USB->COM (adapter działa na hyper terminalu)

    System razem ze sterownikiem usb emuluje COM5 ( i działa jak zwykły com) zmień port.
  • #16
    antyBrygadaW
    Level 15  
    a może ktoś (ten który się pochwalił) mógłby wkleić taki kod dla USB?
  • #17
    Smashing
    Level 20  
    PC +AT89C5131 + USB


    AT89C5131KEIL
    Skorzystałem z gotowego projektu ze strony atmela. Przeanalizowałem cały program i wprowadziłem trochę zmian. Wszystkie Endpointy mają długość ośmiu bajtów- można zwiększyć do 512.
    Nie będę się rozpisywał o transmisji USB, napisze tylko jak odebrać i wysłać dane.
    Znaleźć usb_task.c w Prog_Main (linia 189) mamy tam dwie tablice Recive_data i Send_data są to tablice 8 elementowe. W jednej są dane do zapisu w drugiej odczytane z USB.
    P3_2- jak chce coś wysłać to zwieram wyjście z tego portu do masy i wtedy układ wysyła dane do PC. Obiór danych jest w linii 153.
    Układ zaprogramowałem Flip 3.0.4 przez USB. Projekt płytki w protelu99se.

    Sterownik
    Użyłem gotowego sterownika, który był dostarczony z pakietem DDK. Jak Chcesz użyć tego sterownika do innego układu z USB ustaw w swoim układzie:
    VENDOR_ID 0547
    PRODUCT_ID 1002
    Dodatkowo musisz mieć trzy Endpointy skonfigurowane na Out interupt, In Bulk, oraz Out Bulk. Wtedy sterownik ‘ zobaczy ’ twój układ USB. O Sterowniku USB będzie jeszcze osobny projekt na stronie.
    Instalacja sterownika:
    Po zaprogramowaniu AT89C5131 i naciśnięciu w Flip’e Start Application, PC znajdzie nowe urządzenie pod nazwą osrusbfx2 (nazwę można zmieć w Atmelu i w sterowniku). Pokazujemy ścieżkę gdzie jest nasz sterownik i komputer sam zrobi resztę.

    USB_builder
    Aplikacja przerobiona z gotowego projektu napisanego w dosie dostarczonego z DDK. Wzorując się na tej aplikacji, napisałem tą w Builde’rze. Odbiór danych zrobiony jest na wątku. Naciskając Start włączamy wątek. Wysłanie danych polecałbym również zrobić na osobnym wątku. Odebrane dane są po w lewym oknie. Wysyłane dane są w tablicy bufW, którą przed wysłaniem można czymś zapełnić (np. pianą :)).
    Jak widać projekt jest nie skończony, ale ktoś co się zna trochę na programowaniu powinien sobie poradzić. Jak ktoś chce napisać wszystko od nowa trzeba dodać usbd.lib i setupapi.lib do całego projektu. Opis tych bibliotek na stronie Windowsa.
    Cały układ jest dość prosty, ale można się z niego coś nauczyć pisząc coś swojego.
    Attachments:
  • #18
    michalgorny

    Level 17  
    Witam.

    Przeszukałem już forum ale niestety nie udało mi się znaleźć satysfakcjonującej odpowiedzi: poszukuję rzetelnego opisu odczytu danych z portu com komputera zrealizowanego pod win98 w języku c/c++.

    Problem, który potrzebuję rozwiązać wygląda dokładnie tak:
    czytnik kart rfid po pojawieniu się w polu jego zasięgu karty wysyła do portu com komputera na jeden jego pin ciąg 40 bitów.
    Potrzebuję odczytać te 40 bitów i przedstawić je jako liczbę.

    Następnie muszę tą liczbę porównać z tablicą liczb, pod kątem obecności tej liczby w tablicy. W zależności od wyniku porównania muszę wyświetlić odpowiednią informację.
  • #19
    markosik20
    Level 33  
    Quote:
    wysyła do portu com komputera na jeden jego pin ciąg 40 bitów

    To jak to jest? COM w PC działa na warstwie fizycznej RS232. Z tego co wiem minimalna paczka danch to 8bitów, więc dane powinny "lecieć" paczkami po jednym bajcie. Ten pin to RxD?. I dlaczego nie chcesz korzystać w WinAPI do obsługi UARTA w PC, wystarczy parę linijek a opisów jest dużo w sieci?

    Quote:
    Następnie muszę tą liczbę porównać z tablicą liczb

    A to już nie ma nic wspólnego z COM'em. :wink:
  • #20
    diridiri
    Level 2  
    Code:
    while(1)
    
       {           
            fSuccess = ReadFile( hCom, &RS_buf, 1, &RS_ile, 0);
            if (!fSuccess)
            {
                printf ("ReadFile failed with error %d.\n", GetLastError());
                return 5;
            }
         
          if(RS_ile==1)
          {
             if(RS_buf == 1)   break;
             printf("%c", RS_buf);
          }


    Spróbowałem ten kod i okazuje sie że on czeka tak długo jak coś nie przyjdzie na RS i dopiero po tym przystępuje do dalszej części programu. Może ktoś z was wie jak zrobić aby nie trzeba było czekać tylko jeśli nic nie przychodzi tylko w tej samej chwili zwracał zmienna lub coś w tym stylu. Pisze program w którym odbiór odbywa się w pewnych ramach czasowych i to czekanie w nieskończoność na dane jest nie na miejscu.

    dziękuje i pozdr :)
  • #21
    piotrekcez
    Level 11  
    Właśnie jak można zrobić w API zdarzenie które bedzie wywoływane dopiero po odebraniu danych przez RS232 PC-ta?
  • #22
    Mustela73
    Level 12  
    diridiri
    rejestrujecz event na COM'a, albo przed wywolaniem funkcji ReadFile(...) sprawdzasz ile bajtow jest w buforze:


    DWORD Errors = 0;
    BOOL Result;
    COMSTAT ComStatus;

    Result = ClearCommError( hComPort, &Errors,
    &ComStatus );

    w
    DWORD Data2Read = ComStatus.cbInQue;
    masz liczbe bajtow w buforze wejsciowym
    teraz mozesz odczytac:

    Result = ReadFile( hComPort, &Data, Data2Read, &DataInBuffer, NULL );
  • #23
    diridiri
    Level 2  
    dziekuje ;)

    Mam jeszcze jedna prosbę, może ktoś z was orientuje się jak ustawić 1 logiczną (stan wysoki) na stałe na lini DCD (wykorzystuje winapi w C++)
  • #24
    piotrkopec
    Level 17  
    DCD jest sygnałem wejściowym( patrząc od Twojej strony) więc musisz go podpiąć pod +15V( chyba... albo odwrotnie... nigdy nie wiadomo z tymi stanami :))
    Za pomocą funkcji EscapeCommFunction możesz ustawić stan linii DTR i RTS
    Code:

    BOOL EscapeCommFunction(
      HANDLE hFile,
      DWORD dwFunc
    );

    gdzie 'hFile' to uchwyt do portu a 'dwFunc' to jedno z CLRDTR( sygnał DTR nieaktywny), SETDTR( sygnał DRT aktywny), CLRRTS, SETRTS
    http://msdn2.microsoft.com/en-us/library/aa915335.aspx
    te same efekty daje DeviceIoControl
    http://msdn2.microsoft.com/en-us/library/aa363216.aspx
    z kodami
    IOCTL_SERIAL_SET_DTR
    IOCTL_SERIAL_CLR_DTR
    IOCTL_SERIAL_SET_RTS
    IOCTL_SERIAL_CLR_RTS
    i #include <ioctl.h>
    Powodzenia
    kac
  • #25
    antyBrygadaW
    Level 15  
    Smashing dzięki! podaj jeszcze adres swojej strony na której umieszczasz najnowsze informacje.
  • #26
    antyBrygadaW
    Level 15  
    smashing mógłbyś mi powiedzieć w których plikach i które procedury służą do procesu inicjalizacji transmisji (enumerating)? chciałbym je sobie wyciąć i wkleić do swojego programu...
  • #27
    -= LuKaS =-
    Level 2  
    A ja mam taki problem:
    Skorzystalem z przedstawionego tu programu, odbieram dane z mikrokontrolera przez przejsciowke USB<>RS232, komunikacja zachodzi wlasciwie prawidlowo z jednym wyatkiem. Gdy przesylam wartosci od 0 do 255, otrzymuje podwojnie dane jedynie z zakresu 128 do 255, tak jakby do wartosci ponizej 128 dopisywany byl znak minus na najstarszym bicie. Czy ktos sie z czyms takim spotkal?

    Pozdrawiam Łukasz