Witam!
Na poczatku troche ogolnikowo, bo moze problem jest dla kogos oczywisty, a ja po prostu pominalem jakas kwestie.
Wykorzystuje mikrokontroler jako uklad 'odbijajacy' znak, ktory odbierze, czyli zrobilem popularne 'echo'. Lacze sie oczywiscie przez COM`a. Odrazu mowie, ze korzystajac z hyperterminala wszystko jest w porzadku, zatem nie czepiam sie niczego co znajduje sie 'za COM`em'. Napisalem aplikacje, wykorzystujac znane z API funkcje. Skonfigurowalem, otworzylem port. Dziala to na zasadzie, ze pobiera od uzytkownika znak (char), wykorzystujac WriteFile() wysyla, ReadFile() - odbiera. I teraz problem.. chodzi o to, ze po jednorazowym wyslaniu dowolnego znaku, aplikacja odbiera go dwa razy (jak w zalaczonym screenshot`cie). Dzieje sie tak tylko jesli wysylam znak z poziomu aplikacji. Zaprogramowalem mikorkontroler aby wysylal znaki sam z siebie i te dochodza w pojedynczych kopiach, czyli tak jak nalezy. Podejrzewam, ze problem tkwi w buforach, ktore inicjalizuje system. Czytalem o funkcji FlushFileBuffers(), ktora zapobiega odczytaniu danych ktore chcemy wyslac (jesli korzystamy z tego samego buforu dla wejscia i wyjscia). Uzywa jej sie zaraz za funkcja wysylajaca, ale w moim przypadku nie pomaga. Pomaga wyczyszczenie bufora odbiornika - PurgeComm(com, PURGE_RXCLEAR) po kazdorazowym odebraniu znaku, ale podejrzewam ze chcac odczytac wiecej niz 1 znak z bufora metoda ta sie nie sprawdzi. Nie wiem jak sie zabrac za te bufory, jak stwierdzic czy jest on jeden wspolny dla we/wy itd.. Probowalem tez wielowatkowo, w osobnych watkach wysylanie i odbieranie, ale efekt ten sam. Moze ktos sie z tym spotkal, moze to standardowy problem? Programuje w Visual Studio 6.0 i korzystam z WinXP Prof. W razie czego oczywiscie sluze kodem i wszelkimi innymi informacjami. Z gory dziekuje za wszelka pomoc, pozdrawiam!
---------------------------------------------------------------------------------
Moze jednak dodam najwazniejsze czesci kodu..
HANDLE com;
bool com_open()
{
DCB dcb = {0};
com = CreateFile("\\\\.\\COM4", GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
GetCommState(com, &dcb);
dcb.DCBlength = sizeof(dcb);
dcb.BaudRate = CBR_115200;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.fParity = FALSE;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fTXContinueOnXoff = TRUE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fErrorChar = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fAbortOnError = FALSE;
SetCommState(com, &dcb);
return true;
}
bool Write_Comm(HANDLE hCommDev, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
DWORD NumberOfBytesWritten;
if(WriteFile(hCommDev, lpBuffer, nNumberOfBytesToWrite, &NumberOfBytesWritten, NULL) > 0) return TRUE;
else return FALSE;
}
bool Read_Comm(HANDLE hCommDev, LPVOID lpBuffer, LPDWORD lpNumberOfBytesRead, DWORD Buf_Size) {
COMSTAT Stat;
DWORD Errors, 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 main() {
com_open();
while(1) {
char cZnak;
unsigned long nNumberOfBytesRead = 0;
cout << "\nPodaj znak: ";
cin >> cZnak;
Write_Comm(com, &cZnak, 1);
FlushFileBuffers(com);
Sleep(100);
Read_Comm(com, cZnak, &nNumberOfBytesRead, 1);
if(nNumberOfBytesRead > 0) cout << "\nOtrzymano: " << cZnak;
}
com_close();
return 0;
}
Moze warto tez zaznaczyc, ze korzystam z wirtualnego COM`a, bo wszystko zrobione jest na TUSB3410 i podlaczone pod port usb...
Na poczatku troche ogolnikowo, bo moze problem jest dla kogos oczywisty, a ja po prostu pominalem jakas kwestie.
Wykorzystuje mikrokontroler jako uklad 'odbijajacy' znak, ktory odbierze, czyli zrobilem popularne 'echo'. Lacze sie oczywiscie przez COM`a. Odrazu mowie, ze korzystajac z hyperterminala wszystko jest w porzadku, zatem nie czepiam sie niczego co znajduje sie 'za COM`em'. Napisalem aplikacje, wykorzystujac znane z API funkcje. Skonfigurowalem, otworzylem port. Dziala to na zasadzie, ze pobiera od uzytkownika znak (char), wykorzystujac WriteFile() wysyla, ReadFile() - odbiera. I teraz problem.. chodzi o to, ze po jednorazowym wyslaniu dowolnego znaku, aplikacja odbiera go dwa razy (jak w zalaczonym screenshot`cie). Dzieje sie tak tylko jesli wysylam znak z poziomu aplikacji. Zaprogramowalem mikorkontroler aby wysylal znaki sam z siebie i te dochodza w pojedynczych kopiach, czyli tak jak nalezy. Podejrzewam, ze problem tkwi w buforach, ktore inicjalizuje system. Czytalem o funkcji FlushFileBuffers(), ktora zapobiega odczytaniu danych ktore chcemy wyslac (jesli korzystamy z tego samego buforu dla wejscia i wyjscia). Uzywa jej sie zaraz za funkcja wysylajaca, ale w moim przypadku nie pomaga. Pomaga wyczyszczenie bufora odbiornika - PurgeComm(com, PURGE_RXCLEAR) po kazdorazowym odebraniu znaku, ale podejrzewam ze chcac odczytac wiecej niz 1 znak z bufora metoda ta sie nie sprawdzi. Nie wiem jak sie zabrac za te bufory, jak stwierdzic czy jest on jeden wspolny dla we/wy itd.. Probowalem tez wielowatkowo, w osobnych watkach wysylanie i odbieranie, ale efekt ten sam. Moze ktos sie z tym spotkal, moze to standardowy problem? Programuje w Visual Studio 6.0 i korzystam z WinXP Prof. W razie czego oczywiscie sluze kodem i wszelkimi innymi informacjami. Z gory dziekuje za wszelka pomoc, pozdrawiam!
---------------------------------------------------------------------------------
Moze jednak dodam najwazniejsze czesci kodu..
HANDLE com;
bool com_open()
{
DCB dcb = {0};
com = CreateFile("\\\\.\\COM4", GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
GetCommState(com, &dcb);
dcb.DCBlength = sizeof(dcb);
dcb.BaudRate = CBR_115200;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.fParity = FALSE;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fTXContinueOnXoff = TRUE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fErrorChar = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fAbortOnError = FALSE;
SetCommState(com, &dcb);
return true;
}
bool Write_Comm(HANDLE hCommDev, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
DWORD NumberOfBytesWritten;
if(WriteFile(hCommDev, lpBuffer, nNumberOfBytesToWrite, &NumberOfBytesWritten, NULL) > 0) return TRUE;
else return FALSE;
}
bool Read_Comm(HANDLE hCommDev, LPVOID lpBuffer, LPDWORD lpNumberOfBytesRead, DWORD Buf_Size) {
COMSTAT Stat;
DWORD Errors, 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 main() {
com_open();
while(1) {
char cZnak;
unsigned long nNumberOfBytesRead = 0;
cout << "\nPodaj znak: ";
cin >> cZnak;
Write_Comm(com, &cZnak, 1);
FlushFileBuffers(com);
Sleep(100);
Read_Comm(com, cZnak, &nNumberOfBytesRead, 1);
if(nNumberOfBytesRead > 0) cout << "\nOtrzymano: " << cZnak;
}
com_close();
return 0;
}
Moze warto tez zaznaczyc, ze korzystam z wirtualnego COM`a, bo wszystko zrobione jest na TUSB3410 i podlaczone pod port usb...