Skocz do zawartości

Komunikacja PC - uC, problem z ReadFile()


AE

Pomocna odpowiedź

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

Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.