RS232 i program na PC w C++Buiderze

Nov 27, 2004 5 Replies

Witam Zrobilem sobie i oprogramowalem urzadzenie na atmedze ktore ma sie komunikowac przez RSa z PCtem. Na terminalu wszystko dziala dobrze. Postanowilem napisac sobie aplikacje w C++ Builerze 6 pod WinXP. Wzrouje sie na ksiazce Andrzeja Daniluka "RS232C Praktyczne programowanie". Wysylanie czegos z PC do uC dziala idealnie. Niestety nie chce mi dzialac odbior znakow. Czy sa z tym jakies problemy pod XP czy problem tkwi tylko w tym ze ja nie umiem tego wlasciwie oprogramowac ? :) Robie to praktycznie tak samo jak w przykladach z tej ksiazki jednak program przy dojsciu do :



return ReadFile(hCommDev, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, NULL);



w funkcji Read_Comm, przestaje odpowiadac. Moze ktos wie o co chodzi ?



//---------------------------------------------------------- #define cbOutQueue 64 //rozmiar bufora danych wyjściowych #define cbInQueue 64 //rozmiar bufora danych wejściowych



TForm1 *Form1;



char Buffer_I[cbInQueue]; // bufor danych wejściowych DWORD Number_Bytes_Read; // Number Bytes to Read - liczba // bajtów do czytania HANDLE hCommDev; // identyfikator portu DWORD fdwEvtMask; // informacja o aktualnym stanie transmisji COMSTAT Stat; // dodatkowa informacja o zasobach portu DWORD Errors; // reprezentuje typ ewentualnego błędu



LPCTSTR sbuffer1 = "Niewłaściwa nazwa portu lub port jest" " aktywny."; LPCTSTR sbuffer2 = "Błąd"; LPCTSTR sbuffer3 = "Port nie został otwarty do transmisji.";



//----------------zamyka port------------------------------ BOOL __fastcall Close_Comm(HANDLE hCommDev) { return Win32Check(CloseHandle(hCommDev)); } //---------zamyka port i aplikację------------------------- void __fastcall TForm1::ZamknijClick(TObject *Sender) { Close_Comm(hCommDev); Application->Terminate(); } //-------------------odczyt danych------------------------- BOOL __fastcall Read_Comm(HANDLE hCommDev, LPVOID lpBuffer, LPDWORD lpNumberOfBytesRead, DWORD Buf_Size) { DWORD nNumberOfBytesToRead; ClearCommError(hCommDev, &Errors, &Stat); *lpNumberOfBytesRead = 0; if (Stat.cbInQue > 0) { if (Stat.cbInQue > Buf_Size) nNumberOfBytesToRead = Buf_Size; else nNumberOfBytesToRead = Stat.cbInQue; } return ReadFile(hCommDev, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, NULL); } //---------otwarcie portu do transmisji-------------------- void __fastcall TForm1::OtworzClick(TObject *Sender) { LPCTSTR lpFileName; // wskaźnik do nazwy portu DCB dcb; // struktura kontroli portu szeregowego



lpFileName="COM2";



hCommDev = CreateFile(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);



if (hCommDev != INVALID_HANDLE_VALUE) // sprawdza, czy port jest otwarty prawidłowo { SetupComm(hCommDev, cbInQueue, cbOutQueue); dcb.DCBlength = sizeof(dcb); // aktualny rozmiar // struktury DCB GetCommState(hCommDev, &dcb); dcb.BaudRate=CBR_9600; dcb.Parity = NOPARITY; // ustawienie parzystości dcb.StopBits = ONESTOPBIT; // bity stopu dcb.ByteSize = 8; // bity danych dcb.fParity = FALSE; // sprawdzanie parzystości 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); } else { switch ((int)hCommDev) { case IE_BADID: MessageBox(NULL,sbuffer1,sbuffer2, MB_OK); break; }; } } //--------------------------------------------------------- void __fastcall TForm1::OdbierzClick(TObject *Sender) {



if ((hCommDev != INVALID_HANDLE_VALUE) && (hCommDev > 0)) // powtórnie sprawdza czy port jest otwarty { FlushFileBuffers(hCommDev); Read_Comm(hCommDev, &Buffer_I[0], &Number_Bytes_Read, sizeof(Buffer_I));



if (Number_Bytes_Read > 0) // jeżeli odebrano jakieś bajty { Edit1->Text = &Buffer_I[0]; } } else MessageBox(NULL, sbuffer3, sbuffer2, MB_OK); } //---------------------------------------------------------



Olej win API i wykorzystaj gotowy komponent do Buidera:

formatting link
ustawiania opcji UARTa jest gotowy dialog, zapis/odczyt to proste wywołanie metody klasy: uart->write(), odczyt jako callback itp. Jest nawet sterowanie RTS do RS485.

Sat, 27 Nov 2004 13:58:49 +0100, na pl.misc.elektronika, Krzysztof Urbanski napisał(a):

Tak na pierwszy rzut oka : Wywołujesz synchronicznie ReadFile poza warunkiem sprawdzającym czy jest cos do odczytu. Jeśli nic nie ma to funkcja czeka na transmisję a ponieważ jest wołana w głównym wątku programu - tym samym wiesza go. Na ogół przy obsłudze synchronicznej upycha się pętlę sprawdzania transmisji przychodzącej oraz odczyt bufora w potomnym wątku. To działa sprawnie ale ma wadę - ciągłe obciążenie procesora. Dlatego lepiej używać wywołań asynchronicznych i oczekiwac na ich rezultat także w oddzielnym wątku funkcją WaitForxxx.

Po pierwsze uzyj funkcji SetCommTimeouts(hPort,&tout); to cie zabezpieczy przed zwisem programu przy odczycie

Dzieki wszystkim. Pomeczylm sie i teraz juz zaczyna mi to jakos dzilac.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required