Skocz do zawartości

Kurs STM32 F1 HAL - #5 - komunikacja z komputerem, UART


Pomocna odpowiedź

Wydaje mi się, że ten post powinien być wydzielony z tematu, bo nie bardzo ma związek z kursem.

Natomiast jak chodzi o podpowiedź, to proponowałbym zacząć od podstaw języka C, to co napisałeś jest straszne.

Dnia 12.01.2019 o 13:09, wierczewski napisał:

char *wybor="";

Tutaj tworzysz wskaźnik do pustego napisu, czyli bajtu o wartości zero - bo tak w języku C są przechowywane napisy.

Dnia 12.01.2019 o 13:09, wierczewski napisał:

strcat(*wybor,value);

W tym miejscu dla odmiany starasz się dopisać coś do napisu, ale nie zarezerwowałeś tam miejsca więc w optymistycznej wersji zamazujesz przypadkowe dane w pamięci RAM.

Dnia 12.01.2019 o 13:09, wierczewski napisał:

if(*wybor=='aaa')

Tutaj jest tyle błędów ile znaków w linii... Pojedynczy apostrof to znak, nie napis. Napisów się nie porównuje za pomocą ==. No i ten wybor nieszczesny nadal wskazuje na pusty napis - chociaż może już nie bo kasując losowe dane strcat może i coś zapisał. Jeszcze ta dereferencja zmiennej wybor - jest znakiem, a nie napisem.

W każdym razie radziłbym kurs podstaw C zamiast takiego lepienia kodu metodą "a może zadziała".

 

Edytowano przez Elvis
  • Pomogłeś! 1
Link do komentarza
Share on other sites

Prawie mi się udało... Został mi jedynie warunek porównania warunku z tym co wpisuje. Robiąc krok po kroku w debuggerze wszystko jest okej. Warunek i Value są identyczne a mimo to funkcja strcmp nie zwraca 0 tylko -18. Przepraszam, że wykorzystuje tu HAL, lecz odkryłem ten kurs na nowszych bibliotekach i stwierdziłem, że lepiej będzie się uczyć na tych nowszych.

int licznik=0;
	while (1)
	{
		if (__HAL_UART_GET_FLAG(&uart, UART_FLAG_RXNE) == SET)
		{
			char value[3];   // powinno być [4] zarówno w buforze jak i warunku, ponieważ dochodzi jeszcze znak końca tekstu '/0'
			char warunek[3]="on1";
			HAL_UART_Receive(&uart, &value[licznik], 1, 100);
			licznik++;
			if(licznik==3)
				{
				licznik=0;
				int a=strcmp(value,warunek);
				if(a==0)
					send_string("on1\r\n");
				else if(strcmp(value,"of2")==0)
					send_string("of2\r\n");
				}

		}
	}

 

Edytowano przez wierczewski
tablica char za krótka - brakuje miejsca dla znaku końca tekstu
  • Lubię! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Witam,

Mam problem z którym ciężko poradzić mi sobie samemu otóż w terminalu pojawia się wiadomość która nie odpowiada temu co powinno być napisane, podanemu w kursie "Hello world!" odpowiada (Ascii):

Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®
Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®
Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®Ľ­ř®
Ľ­ř®Ľ­

Real Term pozwala mi odtworzyć to w innych formatach oto kilka z nich:

 -Hex + Ascii

 BC  AD  F8  AE  1D  BC  AD  F8  AE  1D  BC  AD  F8  AE  1D  BC  AD  F8  AE  1D 
 BC  AD  F8  AE  1D  BC  AD  F8  AE  1D  BC  AD  F8  AE  1D  BC  AD  F8  AE  1D 
 BC  AD  F8  AE  1D  BC  AD  F8  AE  1D  BC  AD  F8  AE  1D  BC  AD  F8  AE  1D 

-unit8

173 248 174 29 188 173 248 174 29 188 173 248 174 29 188 173 248 174 29 188 173 
248 174 29 188 173 248 174 29 188 173 248 174 29 188 173 248 174 29 188 173 248 
174 29 188 173 248 174 29 188 173 248 174 29 188 173 248 174 29 188 173 248 174 
29 188 173 248 174 29 188 173 248 174 29 188 173 248 174 29 188 173 248 174 29 1
88 173 248 174 29 188 173 248 174 29 188 173 248 174 29 188 173 248 174 29 188 1
73 248 174 29 188 173 248 174 29 188 173 248 174 29 188 173 248 174 29 188 173

Dla testu skróciłem wiadomość do samego "a" oto wyniki:

Asci: ţ

Hex+Ascii: FE

unit8: 254

Samemu trudno zauważyć mi tu jakąś zależność, pytam więc czy ktoś może wie na czym może polegać błąd?  (dodam że problem występuje również w Teraterm) 

Link do komentarza
Share on other sites

@Gumek witam na forum 🙂

Czy na pewno wybrałeś w terminalu odpowiednią prędkość komunikacji (musi być taka sama jak w programie)? Jej błędne ustawienie jest częstym powodem takich błędów.

Link do komentarza
Share on other sites

Witam

Niestety również mam problem z zadaniem #5.2. Na pewno mam zbyt małą wiedze nt. programowania w C, a szczególnie nt. STM32, ale dotychczas wszystkie zadania wykonywałem bez problemu.

1) Po pierwsze nurtuje mnie jedna rzecz - w instrukcji HAL w opisie funkcji HAL_UART_Receive podane są takie instrukcje.

(UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size, uint32_t Timeout)

Wychodzi na to, że w przykładzie zmienna value musi być typu uint8_t i tak rzeczywiście jest. Zastanawia mnie, jak to jest, że w instrukcji switch oczekiwany jest znak (char), a w funkcji deklarowany jest int (uint8_t). Czy jest to rzutowanie? To w takim razie dlaczego jeśli próbuję odczytać z value łańcuch znaków, kompilator pokazuje type mismatch jeszcze przed próbą kompilacji? Zastosowanie strcmp(value, moja_zmienna_tablicowa_typu_char) również jest dla kompilatora błędna, bo traktuje value jako uint8_t.

Kod napisany przez kolegę Wierczewskiego nie powinien się skompilować (nie sprawdzałem), bo zadeklarował value jako char, podczas gdy HAL_UART_Receive oczekiwało w tym miejscu zmiennej typu uint8_t.

2) To jak w końcu napisać tę funkcję tak, żeby zadziałała? Czy ilość danych do odbioru (uint16_t Size w dokumentacji HAL) powinna być ustawiona na 3 (lub 4) zamiast 1, jeśli chcę odebrać łańcuch o długości 4 znaków?

Nie oczekuję gotowego rozwiązania, ale liczę na "ciekawą" podpowiedź 😉

Link do komentarza
Share on other sites

uint8_t to najzwyklejszy, w dodatku 8-bitowy bajt. W języku C odpowiada dokładnie unsigned char. Zarówno signed char i unsigned char zajmują 8-bitów, różnica polega na interpretacji najwyższego bitu, czyli liczby ze znakiem lub bez. Sam typ char niestety nie wiadomo czy jest signed, czy unsigned - ale ew. pomyłka nie jest krytyczna. Kompilator ostrzega że typ jest inny, ale nic złego się nie dzieje.

Biblioteka HAL jest delikatnie mówiąc przeciętna, używanie uint8_t jako typu bufora jest marnym pomysłem, ale ST potrafi produkować dobre mikorokontrolery, z programowaniem u nich gorzej. Nie pozostaje więc nic innego jak rzutować typ wskaźnika (rzutowany jest typ wskaźnika, nie same dane).

Odbieranie po jednym bajcie jest oczywiście mało wydajne, ale nie jest błędem. Tym co było najgorsze w programie to brak miejsca na znak końca napisu, czyli '\0' - trzeba o tym pamiętać, że w języku C napisy są przechowywane z zerem na końcu. Czyli żeby zapisać łańcuch o długości 4 znaków potrzebna jest tablica o długości 5.

  • Lubię! 1
Link do komentarza
Share on other sites

22 minuty temu, Elvis napisał:

Sam typ char niestety nie wiadomo czy jest signed, czy unsigned - ale ew. pomyłka nie jest krytyczna. Kompilator ostrzega że typ jest inny, ale nic złego się nie dzieje.

Powiedz to komuś, kto trzy dni szukał błędu w programie, który osiem lat działał na pececie a na raspberrym się wykładał 😉

Link do komentarza
Share on other sites

Trzy dni to krótko, wręcz standardowy czas na znalezienie błędu 🙂 Oczywiście nie zawsze można pomijać czy zmienna jest ze znakiem, czy bez - chodziło mi o ten konkretny przypadek i napisy w 7-bitowym ASCII.

A wyjaśniając - właśnie dlatego wprowadzono typy w rodzaju int8_t, uint8_t i podobne, żeby uniknąć różnic wynikających z wersji, czy parametrów kompilatora. Stare typy w C mają niestety taką cechę, że mogą mieć różną reprezentację w zależności od środowiska - przykładowo int może mieć 16, albo 32 bity, char może być ze znakiem lub bez itd.

  • Lubię! 1
Link do komentarza
Share on other sites

1 godzinę temu, Elvis napisał:

używanie uint8_t jako typu bufora jest marnym pomysłem, ale ST potrafi produkować dobre mikorokontrolery, z programowaniem u nich gorzej. Nie pozostaje więc nic innego jak rzutować typ wskaźnika (rzutowany jest typ wskaźnika, nie same dane).

W takim razie jaki to ma być typ zmiennej?

char odpada, tak wnioskuję, po innych wpisach w wątku,  bo jest typem archaicznym.

Osobiście nie korzystam z char, właśnie z tego powodu. Trochę szukałem informacji na ten temat, ale zdania są zwykle podzielone. Natomiast wniosek wyciągnąłem taki, że należy wybierać typy zmiennych zgodnie z ich przeznaczenie, zatem znak ascii nie ma "znaku" to trzeba zapomnieć o char.

Z chęcią dowiem się coś więcej na ten temat, choć czuję podskórnie, że po to wymyślono inne języki, żeby nie doktoryzować się przy tych już wiekowych 🙂

 

Link do komentarza
Share on other sites

Największym problemem HAL nie jest uint8_t jako taki, ale  brak const przy wysyłaniu. Natomiast w C lepszym rozwiązaniem byłoby użycie void* nawet jeśli to nieco archaiczne - ale oszczędziłoby używania konwersji tam gdzie nie jest to konieczne. Tym bardziej że wysyłane dane nie zawsze są w 8-bitowych bajtach.

Natomiast czy trzeba zmieniać język programowania to bym polemizował. Wystarczy nauczyć się używać tego co się ma.

  • Lubię! 1
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!

Anonim
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.