Skocz do zawartości

Komunikacja PC - uC, problem z ReadFile()


Pomocna odpowiedź

Napisano

Witam,

Komunikacja w jedną stronę działa (PC -> robot), ale trzeba się rozwijać i przydałby się jakiś feedback od naszego podopiecznego.

Chciałbym odbierać ramkę danych robot -> PC. Korzystam z modułu BTM222 (czyli w zasadzie UART). Na PC wykorzystalem WINAPI, ale mam problem z funkcją ReadFile(). Odbiera mi tylko 2 znaki z 8. Z kolei Putty odbiera wszystko prawidłowo.

Przykładowa ramka wygląda tak:

$1010#/r/n

a ReadFile widzi tylko np. dwa pierwsze bajty albo jakieś w środku, reszta gdzieś leci w kosmos.

Funkcja inicjalizująca RS na PC:

void RS232Init(void)
{
DCB dcb;														// struktura kontroli portu

	hCommDev = CreateFile("COM3", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);	//otwiera port

if (hCommDev != INVALID_HANDLE_VALUE)							// sprawdza, czy port jest otwarty prawidłowo, jesli nie, to ma wartosć INVALID_HANDLE_VALUE
	{
		dcb.DCBlength = sizeof(dcb); 								// aktualny rozmiar struktury DCB
		GetCommState(hCommDev, &dcb); 								// udostępnienie aktualnych parametrów DCB
		dcb.BaudRate = CBR_19200; 									// prędkość transmisji
		dcb.fParity = TRUE; 										// sprawdzanie parzystości
		dcb.Parity = NOPARITY; 										// ustawienie parzystości
		dcb.StopBits = ONESTOPBIT; 									// bity stopu
		dcb.ByteSize = 8; 											// bity danych
		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;

	timeouts.ReadIntervalTimeout = 1;
  	timeouts.ReadTotalTimeoutMultiplier = 1;
  	timeouts.ReadTotalTimeoutConstant = 1;
  	timeouts.WriteTotalTimeoutMultiplier = 1;
  	timeouts.WriteTotalTimeoutConstant = 1;

  	SetCommTimeouts(hCommDev, &timeouts);

		SetCommState(hCommDev, &dcb); 								// reinicjalizacja DCB
		if(SetCommState(hCommDev, &dcb))
		{
			cout << "Polaczono" << endl;
		}
		else
		{
			cout << "Brak polaczenia" << endl;
		}
	}
	else
	{
		cout << "Nie mozna otworzyc portu" << endl;
	}
}

Fukcja z ReadFile():

void RS232(char* _bytes, unsigned char RW)
{
DWORD RS_ile;

	switch(RW) {

		case 'W': {

			WriteFile(hCommDev,_bytes,strlen(_bytes),&RS_ile,0);

	 	if(WriteFile(hCommDev,_bytes,strlen(_bytes),&RS_ile,0))			//jesli udalo sie wyslac, pokaz co wyslano
	 	{
	 		cout << "Wyslano: " << _bytes << endl;
	 	}
	 	else
	 	{
	 		cout << "Nie wyslano" << endl;
	 	}
			break;
		}

		case 'R': { 

			ReadFile(hCommDev,_bytes,strlen(_bytes),&RS_ile,0);

		if(ReadFile(hCommDev,_bytes,strlen(_bytes),&RS_ile,0))			//jesli udalo sie odebrac, pokaz co odebrano
	 	{
	 		cout << "Odebrano: " << _bytes << endl; //Tutaj chcę wyświetlić co odebrano i kiszka, dane gdzieś uciekają
	 	}
	 	else
	 	{
	 		cout << "Pusto" << endl;
	 	}
			break;
		}	
	}
}

Dodam, że wysyłanie danych działa wyśmienicie. Skończyły mi się pomysły co z tym fantem zrobić. Będę wdzięczny za wszelkie sugestie.

Pozdrawiam

Nigdy nie używałem do tego winapi w ten sposób, ale sprawdzałeś co robi kod:

timeouts.ReadIntervalTimeout = 1;

timeouts.ReadTotalTimeoutMultiplier = 1;

timeouts.ReadTotalTimeoutConstant = 1;

timeouts.WriteTotalTimeoutMultiplier = 1;

timeouts.WriteTotalTimeoutConstant = 1;

SetCommTimeouts(hCommDev, &timeouts);

???

Wg. http://msdn.microsoft.com/pl-pl/library/windows/desktop/aa363190(v=vs.85).aspx są to maksymalne czasy na odebranie kolejnych bajtów w ramce jak i całej ramki... 1ms może być ciut krótkim czasem.

Bez tego program się zawieszał na funkcji ReadFile(), bo cały czas czekał na jakieś dane. Próbowałem już z różnymi wartościami timeout. W akcie ostatecznej desperacji dałem czasy 1000 ms i nadal nie działało tak jakbym tego chciał.

Długo nie zaglądałem do kodu programu. Praca w systemie IV zmiennym potrafi wyrugować wszelki czas wolny, ale w końcu znalazłem w czym był problem.

Po pierwsze, aby komunikacja była nie zawodna oraz każda paczka danych kompletna i odpowiednio zinterpretowana, napisałem protokół (to chyba zbyt duże słowo 😋) coś na zasadzie ModBusa.

Po drugie, jeden z argumentów w funkcji ReadFile() musiałem podać dokładną ilość bajtów jaką chcę odebrać. Użycie strlen() powoduje, że funkcja się wiesza.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...