Skocz do zawartości
Komentator

Kurs STM32 F4 - #11 - Komunikacja przez USB

Pomocna odpowiedź

html_mig_img
Standardem komunikacyjnym w świecie PC stał się interfejs USB. Można go znaleźć w ogromnej ilości urządzeń takich jak kamery, myszki, pamięci przenośne, czy klawiatury.Mikrokontrolery nie stanowią tutaj wyjątku i coraz częściej wyposażane są w kontroler USB, którego obsługą zajmiemy się w tym odcinku kursu

UWAGA, to tylko wstęp! Dalsza część artykułu dostępna jest na blogu.

Przeczytaj całość »

Poniżej znajdują się komentarze powiązane z tym wpisem.

Udostępnij ten post


Link to post
Share on other sites

Uruchamiałem ostatnio USB na STM32 (Mass Storage) i miałem trochę podobny problem z wykrywaniem urządzenia. Wyglądało to jak jakby przy wstrzymaniu programu albo reflashowaniu procka, kontroler wykrywał timeout i odłączał urządzenie. Zmieniłem więc podłączenie rezystora 1K5, zamiast na stałe do VCC jest teraz podłączony do jednego z GPIO i zaraz po resecie jest ustawiany na 0 i po około sekundzie, po przeprowadzeniu całej inicjalizacji jest ustawiany na 1. Kontroler wykrywa to jak odłączenie i podłączenie.

Powyższy screen pochodzi z STM32F4DISCOVERY z STLink-a, USB z procka nie ma wcale tego rezystora, więc może w tym problem.

Udostępnij ten post


Link to post
Share on other sites

W moich projektach używam też takiego rozwiązania ( 1.5k do gpio ) i urządzenie jest wykrywane bez problemu. Jedyny ew. błąd pojawia się jak się próbuje wykorzystać port com w momencie jego inicjalizacji / ładowanie drivera przez windows czy coś takiego. Wystarczy spokojnie poczekać 3 sekundy od wsadzenia urządzenia do podłączenia się aplikacją windowsa do coma i działa w 100%.

Udostępnij ten post


Link to post
Share on other sites

Witam, mam problem ponieważ Windows nie wykrywa w ogóle mojego stm32f429, nie wiem jak to zrobić, próbowałem również z innymi komputerami i to samo, nie wykrywa w ogóle mikrokontrolera jako urządzenia USB, co mam zrobić z tym fantem?

Udostępnij ten post


Link to post
Share on other sites

Ja dodam, że jeśli robimy coś z USB na własnych płytkach pcb należy zadbać o długość ścieżek - tzn. najlepiej jak są krótkie, a jeśli musimy je poprowadzić dłuższą drogą niezbędny będzie układ stosowany w zestawach Discovery który podłącza się równolegle do linii USB. Straciłem na tym dużo czasu, a okazało się ze problemem były właśnie niewiele za długie ścieżki.

Aha przejawia się to tym, że komputer wykrywa uszkodzone urządzenie ( unknown device ). A najłatwiej sprawdzić połączenie zwierając BOOT0 do +3,3v przy starcie ( tryb bootloadera).

Udostępnij ten post


Link to post
Share on other sites

karo212, w komentarzach do kursu rozmawiamy wyłącznie o platformie sprzętowej opisywanej w artykułach. Jeśli masz problem z inną płytką, to załóż osobny temat w odpowiednim dziale. Unikniemy wtedy nieporozumień i zbędnego zamieszania.

Udostępnij ten post


Link to post
Share on other sites

Po pierwsze: dzięki za kurs!

A teraz problem/zagadka: napisałem prosty programik w zasadzie bardzo podobny co przykład z przyciskiem ale z odbieraniem komendy. Główna pętla (wyczyszczona, żeby mniej miejsca zajmowała):

while (1)
 {
  if(ReceivedDataFlag == 1)
  {
	   ReceivedDataFlag = 0;

	   if( strcmp( (char *)ReceivedData, "Red") == 0 )
		   HAL_GPIO_TogglePin(LED_RED_GPIO_Port, LED_RED_Pin);
	   if( strcmp( (char *)ReceivedData, "Green") == 0 )
		   HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);

	   MessageLength = sprintf((char *)DataToSend, "Odebrano: %s\n\r", (char *)ReceivedData);
	   CDC_Transmit_FS(DataToSend, MessageLength);
  }
 }

... nie działa. uC w ogóle nie odpowiada nie reaguje. natomiast po dodaniu jednego nop'a wszystko śmiga aż miło (oczywiście delay robi to samo ale chodzi mi, że jedna instrukcja nop wystarczy):

while (1)
 {
  if(ReceivedDataFlag == 1)
  {
	   ReceivedDataFlag = 0;

	   if( strcmp( (char *)ReceivedData, "Red") == 0 )
		   HAL_GPIO_TogglePin(LED_RED_GPIO_Port, LED_RED_Pin);
	   if( strcmp( (char *)ReceivedData, "Green") == 0 )
		   HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);

	   MessageLength = sprintf((char *)DataToSend, "Odebrano: %s\n\r", (char *)ReceivedData);
	   CDC_Transmit_FS(DataToSend, MessageLength);
  }
  asm("nop");
 }

Moja pierwsza myśl to priorytety przerwania - jakby program nie mógł wyskoczyć z głównej pętli jeżeli ciągle sprawdza warunek?

Programy testuje na STM32F103.

Pozdrawiam

EDIT: wiem, że to inna platforma sprzętowa ale problem dotyczy chyba implementacji biblioteki HAL'a, więc wklepałem to tuaj.

Udostępnij ten post


Link to post
Share on other sites

Spróbuj zadeklarować zmienną ReceivedDataFlag jako volatile, to też powinno pomóc a przy okazji wyjaśnić zagadkę.

W kursie jest błąd - brakuje właśnie volatile w zmiennych modyfikowanych z poziomu przerwania. Poza tym używanie extern wewnątrz funkcji to baaardzo brzydka praktyka.

Udostępnij ten post


Link to post
Share on other sites

Też mi często w Realterm wyskakuje ten błąd z parametrem, natomiast gdy włączyłem inny terminal Tera Tera to nie napotkałem wcale na takie problemy, więc coś z konfiguracją terminala chyba musi byc 🙂

Udostępnij ten post


Link to post
Share on other sites

Witam! To moja pierwsza przygoda z USB. Próbowałem uruchomić zgodnie z kursem to USB. Niestety komputer nawet nie widział urządzenia. Podłączyłem więc 1k5 opornik do portu GPIO i na chwilę wyłączam, a po inicjacji włączam stan wysoki i komputer rozpoznaje podłączenie do komputera ale wyskakuje taki błąd:

A request for the USB device descriptor failed.

Ktoś wie czy to może być spowodowane? Uruchomiłem ten sam kod również na płytce z STM32f103 i również ten sam błąd.

Czy może ten identyfikator należy gdzieś ustawić?

EDIT:

Po wgraniu kodu jeszcze raz i kliknięciu przycisku Reset wykrywa płytkę discovery, ale pojawia się znowu błąd:

Nie można uruchomić tego urządzenia. (Kod 10).

Czy nikt nie zetknął się z takim problemem?

----

ROZWIĄZANIE:

Rozwiązałem problem. Problem tkwił w rozmiarze paczki. Pomógł mi ten link:

forumST

W nowszej wersji kodu w podanych miejscach z tego forum nie ma takich wartość, są podobne. U siebie zmieniłem następujące parametry z wartości 512 każdy na 64:

w pliku usbd_cdc.h

#define CDC_DATA_HS_MAX_PACKET_SIZE                 64  /* Endpoint IN & OUT Packet size */

oraz

w pliku

usbd_def.h

#define USB_HS_MAX_PACKET_SIZE                            64

Pomogło. Teraz system wykrywa poprawnie STM i łączy się bez problemu z RealTerm.

Mam nadzieje, że wątek komuś pomoże. Płytka z STM32F103 też działa na tym kodzie, ustawieniach i z użyciem rezostora 1k5. Serdeczne dzięki dla Autora! ➕

Jeśli chcecie uruchomić USB na STM32f7 disco Board to wstawiłem też instrukcję jak je uruchomić tutaj:

https://community.st.com/thread/14400

🙂

814724010_bladstm32f4discovery.thumb.png.9a1dd07874777b2a2c3345262360f660.png

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

przy debuggowaniu wysypywał sie na static

CDC_Transmit_FS()

na:

USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDevice_0->pClassData;

przed CDC_Transmit() dodałem

CDC_Init()

i gra

(na stm32f746g-discovery)

Udostępnij ten post


Link to post
Share on other sites

Cześć, jestem tu nowy i uczę się programowania Discovery razem z tym kursem. Mam pytanie czy istnieje możliwość przesyłania danych i zapisywania ich na pendrive podpięty pod gniazdo micro USB? Czy programem wyjściowym(do takiego zapisu), może być program z tego kursu? Jeśli jest to oczywista sprawa to przepraszam, dopiero się uczę, a wydaje mi się to ciekawym i potrzebnym zagadnieniem.

Udostępnij ten post


Link to post
Share on other sites

Witam.

Odnośnie obsługi USB/CDC mam takie pytanie.

Jeśli wysyłam stringi przy pomocy CDC_Transmit_FS(), np tak:

CDC_Transmit_FS(...);
CDC_Transmit_FS(...);
CDC_Transmit_FS(...);

to wysyła mi się tylko pierwszy na liście. Nie jest to jakiś problem, bo można po każdym dać HAL_Delay() i jest już dobrze, choć pewnie mało elegancko.

Rozwiązaniem niby jest sprawdzanie co funkcja zwraca np:

while (CDC_Transmit_FS(... , ...) != USBD_OK);

i to też działa, ale... dopóki po stronie PC jest otwarty ten port. Jeśli go zamknę to program staje na tej linii programu i czeka.

Jak wobec tego sprawdzić, czy po stronie PC port jest otwarty i czy jest sens wysyłać cokolwiek na USB? Niby można zrobić jakiś timeout i wyjść, ale czy nie ma lepszego rozwiązania?

Co do pytania z tekstu z otwieraniem portu, to nie wiem, czy to ten problem, bo używam Debiana, ale u mnie po każdym resecie lub wgraniu programu zmienia się uchwyt do portu

i na zmianę mam /dev/ttyACM0 i /dev/ttyACM1. Nic nie muszę rozpinać, ani restartować.

Udostępnij ten post


Link to post
Share on other sites

Witam Was, znowu muszę sie poradzić. próbuję nawiązać komunikację przez UART. Postępowałem jak w kursie, dioda miga tak jak powinna, zmieniłem port pod swoje urządzenie i w nic. Na ekranie nadal czarno, jakby połączenie nie zostało nawiązane.

Wiecie możę czym to może być spowodowane?

Posiadam trochę inną płytkę, ale wszystko pod nią zmieniłem.

Udostępnij ten post


Link to post
Share on other sites

Qwazi, _kursSprzet

Udostępnij ten post


Link to post
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...