Elektroda.pl
Elektroda.pl
X
PCBwayPCBway
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

STM32 - Programowanie "po rejestrach" bez SPL

27 Wrz 2015 17:07 2865 19
  • Poziom 13  
    Witam.
    Zaczynam zabawę z mikrokontrolerami STM32 a dokładniej ze rdzeniem Cortex-M3. Posiadam płytkę z mikrokontroler STM32F103VBT6. Nie chcę się bawić w gotowe biblioteki tylko programować "po rejestrach" i tutaj pojawia się pierwszy problem - które środowisko wybrać.
    Próbowałem Atollic TrueSTUDIO wybrałem sobie Embedded C Project naładował mi tyle syfu, że kompilacja trwała dość długo, ale wiedział co znaczy GPIOA->CLR a nawet podpowiadał, co było bardzo wygodne. Wybierając Empty C Project, tworzyłem sobie swoje pliki bez żadnych dodatków, ale program już nie rozumiał co znaczy: GPIOA->CLR. Jak się z tym poradzić - gdzie znajdę plik który ma zdefiniowane adresy rejestrów, przerwań itp. lub tak jak w dokumentacji GPIOA_CLR?
    Jeśli już środowisko zrozumiała co znaczy:
    Napisałem GPIOA->CLR = 0xFFFF i było dobrze, ale miało problem zrozumieć zapis: GPIOA->CLR ^= 1<<MODE2 - czy na prawdę nie ma jakiegoś porządnego środowiska, które by nie wkładało do programu całego dobra bibliotecznego i rozumiało taki zapis?
  • PCBwayPCBway
  • Pomocny post
    Poziom 25  
    K.G. napisał:
    gdzie znajdę plik który ma zdefiniowane adresy rejestrów, przerwań itp.

    Masz w środowisku: stm32f10x.h

    K.G. napisał:
    ale miało problem zrozumieć zapis: GPIOA->CLR ^= 1<<MODE2

    Ja także mam problem :)

    W pliku stm32f10x.h masz definicje:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Jak to się ma do Twojej konstrukcji?

    K.G. napisał:
    Próbowałem Atollic TrueSTUDIO wybrałem sobie Embedded C Project naładował mi tyle syfu, że kompilacja trwała dość długo, ale wiedział co znaczy GPIOA->CLR a nawet podpowiadał, co było bardzo wygodne.

    Kompilacja trwa długo tylko za pierwszym razem, poza tym nie widzę sensu wybierać Empty C Project.
  • PCBwayPCBway
  • Pomocny post
    Poziom 27  
    Plik nagłówkowy mikrokontrolera można wyłuskać np. z paczki SPL pobranej ze strony ST. Dla Twojego STM32F103VBT6: link (przycisk download na dole strony).
    Po rozpakowaniu archiwum: Libraries -> CMSIS -> CM3 -> DeviceSupport -> ST -> STM32F10x -> stm32f10x.h

    Obawiam się, że to nie środowisko, a jednak Ty nie rozumiesz zapisu 1<<MODE2 :) MODE2 ma wartość 0x300 ;) Czyli do 32bitowego rejestru próbujesz wpisać jedynkę przesuniętą w lewo o 768 pozycji... Chyba nie o to chodziło.

    Co do środowiska. Może Eclipse? Kolega Freddie Chopin napisał fajny poradnik jak ogarnąć Eclipse'a i STMy.
  • Poziom 13  
    Dziękuję Wam za podpowiedzi. :)

    Oczywiście nie o to chodziło, ale na pewno wiedzieliście co miałem na myśli, co wynikało z Waszej odpowiedzi.

    Ustawiam GPIOA.0 i GPIOA.1 jako wyjścia push-pull:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Wtedy zmieniam niepotrzebnie stan pozostałych, czyli powinno być:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Trochę mało czytelnie, więc może:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dobrze kombinuję? Jeśli musiałbym ustawić więcej bitów to trochę by mogło wyjść długie. Czy jest na to jakiś inny sposób? Nazwy bitów są strasznie długie.
  • Pomocny post
    Poziom 38  
    Długie? Nie. Są odpowiedniej długości by zawierać odpowiednią informację czego dotyczy.
    Rozwiązanie? Napisać właściwe makro lub funkcję.
  • Pomocny post
    Specjalista - Mikrokontrolery
    GPIOA->CLR = 0x44444411;

    Jest bardzo czytelne, bo dokładnie wiesz, co po takiej instrukcji masz w rejestrze. Jeszcze bardziej czytełnie byłoby, gdybyś zamiast wartości liczbowej w instrukcji podstawienia użył stałych symbolicznych.

    Użycie operacji logicznych na rejestrach ma tę wadę, że czytając jedną instrukcję nie wiesz, co jest na pozostałych bitach pozostałej części rejestru - tych, których instrukcja nie modyfikuje.
  • Poziom 13  
    Napisałem już obsługę wyświetlacza LCD na ARMa po rejestrach, ale robiłem to na „gotowcu” z bibliotek z ksiązki pana Galewskiego. Niestety mam problem ze zrobieniem tego od zera. W Keilu 5 tworzę goły projekt, który zawiera tylko wbudowany plik z deklaracjami stosu itp i dopisuję swój program np. migający diodą. W ogóle nic nie rusza. Czy to jest problem że nie zdefiniowałem taktowania ARMa itp.? Bo z tego co widzę wydaje mi się, że powinien ruszyć na jakiś domyślnych ustawieniach.
    Jak taki projekt typowo po rejestrach zrobić „po Bożemu”. Czy może macie jakiś projekt stworzony od zera z wszystkimi ustawieniami ARMa? Byłoby to dla mnie bardzo cenne.
    Pozdrawiam
  • Pomocny post
    Specjalista - Mikrokontrolery
    Masz serię artykułów w EP z ostatnich 2 lat o programowaniu bez SPL w Keilu - wystarczy poczytać, archiwalne numery są dostępne za darmo.

    Marudzisz, że nie działa, ale ani nie pokazałeś kodu, ani nie napisałeś, co to znaczy że "nic nie rusza", więc jak niby mamy Ci pomóc, hę?
  • Poziom 13  
    Musiałem je przeoczyć. Już wszystko udało mi się zrobić i napisać pierwsze programy. Pracuję w Keil 4.7 i nie muszę dołączać oddzielnie pliku z definicjami adresów rejestrów.
    Tworząc projekt wybieram mikrokontroler zgadzam się na dodanie pliku startowego i tworzę główny plik. Bez konfiguracji zegara wszystko rusza na wewnętrznym i jest dobrze. Problem jest z Keil 5 w którym dodano te paskudne pakiety. Nie wiem, dlaczego, ale nie mam możliwości stworzenia pustego projektu z plikiem startowym tylko od razu te pakiety z paskudnym i ciężkim SPL. Tutaj przydałaby mi się porada co z tym zrobić.

    Zastanawia mnie też jedna sprawa. Napisałem bibliotekę dla wyświetlacza LCD teraz dodaję obsługę flagi zajętości. Muszę zmieniać konfigurację linii sygnałowych. Po resecie jest 0100 ustawiam na wyjście 0001 następnie chcę zamienić na wejście bez podciągania 0100. Czyli muszę jednocześnie jeden bit ustawić jeden skasować nie dotykając przy tym reszty rejestru.
    Pomyślałem, aby zmienić GPIOB.12 z wyjścia na wejście napisać:

    GPIOC->CRH ^= 5<<16;

    Xor w miejscu, w których chcę zmienić, czyli pierwszy i trzeci bit z półbajt, czyli 5 przesunięte o 16 miejsc by wejść na półbajt od wyprowadzenia 12-tego. Wygląda to nieco nieczytelnie – jest na to jakiś lepszy sposób?

    PS. Nie wiem, po co komu SPL pisałem w tym przez jakiś czas i po prostu jest to beznadziejne, dużo klepania bezmyślnego a tak ustawiam sobie, co zechcę w rejestrach.
  • Poziom 38  
    K.G. napisał:
    GPIOC->CRH ^= 5<<16;


    Gorzej być nie może.

    Najpierw wyzeruj całe pole. Potem OR z wartością docelową. W pliku z rejestrami masz odpowiednie makra. Warto sobie z biegiem czasu tworzyć dodatkowe opisujące pola wielobitowe.

    Konfiguracja portów jest pod tym względem najgorsza.
  • Poziom 13  
    Co do Keila poszukaj paczki legacy
  • Specjalista - Mikrokontrolery
    W Keil 5.x do projektu dołącza się dokładnie to, co chcesz. Należy zaznaczyć CMSIS-CORE i Device-Startup, i otrzymujesz projekt z modułem startowym i bez bibliotek.

    Pakiety w 5.x są b. zgrabne i pożyteczne.

    Nie czytaj znacznika BUSY z wyświetlacza - tracisz w ten sposób czas procesora, a odczyt zera nie oznacza, że wyświetlacz jest gotowy.
  • Poziom 13  
    tadzik85 napisał:
    K.G. napisał:
    GPIOC->CRH ^= 5<<16;


    Gorzej być nie może.

    Najpierw wyzeruj całe pole. Potem OR z wartością docelową. W pliku z rejestrami masz odpowiednie makra. Warto sobie z biegiem czasu tworzyć dodatkowe opisujące pola wielobitowe.

    Konfiguracja portów jest pod tym względem najgorsza.

    W jakim sensie gorzej być nie może? Nieczytelności? To byłoby dobre pod warunkiem, że znam co w tym rejestrze jest na etapie pisania programu.

    GPIOC->CRH = (GPIOC->CRH & 0xFFF0FFFF) | (1<<18);

    Wygląda jeszcze straszniej, czy coś takiego miałeś na myśli? :D

    Możesz napisać przykładową nazwę tego makra?

    Co do gotowców z pliku nagłówkowego to napisałem wczoraj taki kawałek kodu:

    #define Set_E GPIOC->BSRR = 1<<10;
    #define Reset_E GPIOC->BRR = 1<<10;

    Zamiast tej 10 chciałem napisać GPIO_BSRR_BS10 i niestety nie działało. Jak popatrzyłem mam pod tym 0x400 czyli jedenasty.

    BlueDraco Programujesz pod SPL czy po rejestrach? Zastanawia mnie czy SPL jest wykorzystywany w projektach profesjonalnych tzn. firmach programistycznych, bo obecnie ciężko gdziekolwiek znaleźć coś pisanego po rejestrach.

    Dodano po 5 [minuty]:

    BlueDraco napisał:
    Nie czytaj znacznika BUSY z wyświetlacza - tracisz w ten sposób czas procesora, a odczyt zera nie oznacza, że wyświetlacz jest gotowy.


    Nie wykorzystując BF też muszę czekać trochę µs. Wiadomo w wolnych LCD nic się nie przyśpieszy a w jakiś OLEDach?

    Mam jeszcze jedno pytanie. Pisząc sobie biblioteczkę dla LCD robiłem opróżnienia na pętli for pierwsze mierząc ile trwa sekunda i przeliczając to z proporcji. Wiem, że nie da się tego dokładnie obliczyć, a jeszcze gorsza sprawa, że jest to dla konkretnej częstotliwości taktowania. Dobrze można zdefiniować sobie tą częstotliwość i przeliczać dynamicznie, ale chyba lepiej na przerwaniu. Pomyślałem, aby napisać sobie raz i później wykorzystywać procedurę Delay opartą na SysTick. Jest to dobry pomysł czy lepiej zostawić go sobie do innych celów?
  • Poziom 38  
    K.G. napisał:
    GPIOC->CRH = (GPIOC->CRH & 0xFFF0FFFF) | (1<<18);


    wole to

    GPIOC->CRH = (GPIOC->CRH & ~(GPIO_CRH_MODE4)) | (1<<(PIN_NR * 4));

    Choć od lat tego zapisu nie stosuję. Są lepsze rozwiązania. Choćby funkcja Freddiego.

    A XOR na rejestrze to zupełnie nie wiadomo co będzie wynikiem.
  • Poziom 13  
    tadzik85 napisał:
    K.G. napisał:
    GPIOC->CRH = (GPIOC->CRH & 0xFFF0FFFF) | (1<<18);


    wole to

    GPIOC->CRH = (GPIOC->CRH & ~(GPIO_CRH_MODE4)) | (1<<(PIN_NR * 4));

    Choć od lat tego zapisu nie stosuję. Są lepsze rozwiązania. Choćby funkcja Freddiego.

    A XOR na rejestrze to zupełnie nie wiadomo co będzie wynikiem.


    Tutaj zerujesz tylko dwa bity MODE4 a nie tykasz CNF4 a to je chciałem też wyzerować. Oczywiście można to zrobić w drugiej kolejności, ale ja to zrobiłem o ile się nie mylę za jednym razem. Fakt, że w mało przejrzysty sposób.
  • Poziom 13  
    BlueDraco napisał:


    Oczywiście takie rozwiązanie jest jak najlepsze, ale póki co tworzę dość prymitywny program w którym nie ma potrzeby robienia wszystkiego w przerwaniach.

    Stworzyłem tak jak mi poradziłeś projekt w Keil 5.x i owszem udało mi się go wreszcie stworzyć i skompilować, ale ten sam kod zajmuje prawie dwa razy tyle pamięci. Zastanawia mnie gdzie w tym momencie pojawia się procedura SystemInit()? Myślałem, że w piątce jest lepsze podpowiadanie składni, ale jest tak samo kiepskie jak w 4.7 więc nie widzę sensu migracji. Brak porównania do środowisk Visual Studio.
  • Specjalista - Mikrokontrolery
    SystemInit jest w dołączonym do projektu pliku ...system...c, a to, co w niej jest, zależy od tego, ile miesięcy temu wyszedł pakiet do danej serii. Nowsze wersje SystemInit nie robią prawie nic, starsze dość sporo. Zawsze możesz zmienić nazwę oryginalnej prcedur i napisać własną SystemInit();

    Obsługa LCD w przerwaniu timera ma m.in. tę zaletę, że jest krótsza, a nie tylko szybsza od "klasycznej".

    Przy szybkim mikrokontrolerze po wykryciu BUSY=0 trzeba jeszcze programowo odczekać kilka uS.
  • Poziom 33  
    Autor tej biblioteki z EP chyba zapomniał, że istnieje standardowa biblioteka. Jest tam też kilka innych "ciekawych" konstrukcji.
  • Specjalista - Mikrokontrolery
    GrzegorzKostka napisał:
    Autor toj biblioteki z EP

    Przecież autorem jest chyba BlueDraco, no nie?