Krzysztof Urbanski
Guest
Sat Nov 27, 2004 12:58 pm
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);
}
//---------------------------------------------------------
--
Pozdrawiam
Krzysztof Urbanski
krzysztof-u@[usun_to]wp.pl
Jurek Szczesiul
Guest
Sat Nov 27, 2004 4:20 pm
Sat, 27 Nov 2004 13:58:49 +0100, na pl.misc.elektronika, Krzysztof Urbanski
napisał(a):
Quote:
jednak program
przy dojsciu do :
return ReadFile(hCommDev, lpBuffer, nNumberOfBytesToRead,
lpNumberOfBytesRead, NULL);
Quote:
//-------------------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);
}
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.
--
Pozdrowienia
Jurek Szczesiul