Ta strona używa ciasteczek (plików cookies), dzięki którym może działać lepiej. Dowiedz się więcejRozumiem i akceptuję

Kurs STM32 - #4 - Sterowanie portami GPIO w praktyce

Autor Wiadomość
avrkwiat 




Posty: 18
Skąd: kwidzyn
Programuję w:
C, Java
Wysłany: 19-06-2016, 22:02   

Elvis, Kod daje 200Hz na pinie15 czyli 5ms okres. Płytka Zl29ARM z STM32F107vct6 na zewnętrzny zegar podłączone jest 10MHz. Mi się właśnie skończył weekend, więc będę afk, ale dzięki za chęci ;)

Kod programu: Zaznacz cały
#include "stm32f10x.h"

void SysTick_Handler(void)  {
GPIO_WriteBit(GPIOE, GPIO_Pin_15, (BitAction) ((1-GPIO_ReadOutputDataBit(GPIOE, GPIO_Pin_15))));
}

int main (void)  {
uint32_t returnCode;
returnCode = SysTick_Config(SystemCoreClock / 1000);    //200 tyknieć na sekundę
  if (returnCode != 0)  {                                   /* Check return code for errors */
    // Error Handling
  }
  //konfigurowanie portow GPIO
  GPIO_InitTypeDef  GPIO_InitStructure;

  /*Tu nalezy umiescic kod zwiazany z konfiguracja sygnalow zegarowych potrzebnych w programie peryferiow*/
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);//wlacz taktowanie portu GPIO E
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//wlacz taktowanie portu GPIO C

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOE, &GPIO_InitStructure);

  while(1);
}
Polecany artykuł z FORBOT.PL:
Mechanika robota kroczącego

W moim artykule przedstawię krok po kroku jak zbudować korpus robota kroczącego typu hexapod (sześcionogi) z p... Czytaj całość


Postaw piwo autorowi tego posta
 
 
Elvis 



Posty: 1187
Pomógł: 83 razy
Otrzymał 216 piw(a)
Skąd: wawa
Programuję w:
C, asm
Wysłany: 19-06-2016, 22:07   

Zacznijmy od programu z kursu, czyli przykładu opisanego w akapicie "Opóźnienia w STM32 – SysTick". Po uruchomieniu na płytce Nucleo, oscylogram wygłąda następująco:

Tak długie czasy znacznie lepiej wyglądają dla ludzkiego oka, niż oscyloskopu, więc lepiej będzie zmniejszyć opóźnienia. Zamiast 400ms i 100ms wstawiamy 4ms i 1ms. Teraz nawet nieco wiekowy oscyloskop może podpowiedzieć jakie czasu uzyskaliśmy:

Jak widać jest prawie-idealnie. Zamist 1ms mamy 1.12ms, czyli 12% dłyższy impuls niż oczekiwany. W kursie była uwaga o zmiennejSystemCoreClock - w wersji biblioteki ST, która była dostępna podczas pisania kursu jej wartość wynosiła 72000000 zamiast 64000000. Jak podzielimy 72 przez 64, to znajdziemy nasze brakujące 12%.
Mam nadzieję, że aktualna wersja biblioteki nie ma już tego błędu, ale zawsze możemy zmienić wartość zmiennej. Wpiszmy przed wywołaniem SysTick_Config:
Kod programu: Zaznacz cały
SystemCoreClock = 64000000

Teraz oscylogram wygląda zgodnie z oczekiwaniami:

Na koniec można jeszcze zmienić program, zostawić pustą pętlę kodzie głównym, a przy każdym wywołaniu SysTick_Handler zmieniać stan wyjścia. Ponieważ timer jest konfigurowany instrukcjami:
Kod programu: Zaznacz cały
    SystemCoreClock = 64000000;
    SysTick_Config(SystemCoreClock / 1000);

Możemy oczekiwać przerwania co 1/1000s, co potwierdza oscylogram:


[ Dodano: 19-06-2016, 22:09 ]
To co przysłałeś to tylko fragment kodu programu. Mnie interesuje całość. Co wywołuje funkcję main?

Postaw piwo autorowi tego posta
 
 
Więcej szczegółów
Wystawiono 1 piw(a):
avrkwiat
avrkwiat 




Posty: 18
Skąd: kwidzyn
Programuję w:
C, Java
Wysłany: 20-06-2016, 06:43   

Elvis, Jestem juz na 99% pewny, że kod jest ok tylko ustawienia standardowe u mnie są inne. Ja aby dostać takie same wykresy muszę wpisać:
Kod programu: Zaznacz cały
SystemCoreClock=28800000;
returnCode = SysTick_Config(SystemCoreClock / 1000);

Mam prośbę mógłbyś skompilować mi twój kod z twoimi ustawieniami pod STM32F107vct6 i przesłać mi elf, albo hex na maila makwiatkow@gmail.com? Bo może to wina tego mojego procka. Wtedy będę miał 100% pewności, albo nowe podejrzenia co do mojej IDE.

Postaw piwo autorowi tego posta
 
 
Elvis 



Posty: 1187
Pomógł: 83 razy
Otrzymał 216 piw(a)
Skąd: wawa
Programuję w:
C, asm
Wysłany: 20-06-2016, 08:26   

Nie do końca rozumiem co to są ustawienia standardowe. W każdym razie proste mikrokontrolery jak np. stm32 nie posiadają rozbudowanych systemów operacyjnych, nie mają też wiedzy o tym co jest podłączone do nich. Efekt jest taki, że programista musi wiedzieć i rozumieć na jakim sprzęcie pracuje. W przypadku kursu, programy były pisane na Nucleo z prockiem stm32f103rb i tylko w takiej konfiguracji działają bez zmian. Jeśli chcesz żeby program działał w innym srodowisku musisz go zmodyfikować. Nie znaczy to że program jest zły, nie znaczy również że IDE źle działa. Po prostu program musi być dopasowany do sprzętu, jeśli nie jest to nie będzie działał.

Doszliśmy do pierwszych wniosków, teraz możemy spróbować ustalić jaką konfigurację posiadasz i dlaczego uzyskujesz takie a nie inne rezultaty. Od razu podpowiem, że metodą na napisanie poprawnego programu jest zrozumienie jak działa sprzęt. Wtedy można policzyć odpowiednie parametry, a na koniec sprawdzić uzyskane wyniki np. oscyloskopem. Metoda prób i błędów, dobieranie parametrów na chybił-trafił to fajna zabawa, ale na pewno nie metoda której powinno się uczyć i polecać.

Na początek musimy ustalić jaki zegar wykorzystuje procesor. Piszesz że HSI, jednak coś tutaj się nie zgadza. Jak słusznie zauważyłeś wbudowany generator RC pracuje z częstotliwością 8MHz, więc gdyby to on był źródłem sygnału, cały system pracowałby 9 razy wolniej, a stała SystemCoreClock powinna mieć wartość 8000000.
Przy okazji - SystemCoreClock musi mieć wartość odpowiadającą częstotliowści pracy mikrokontrolera. Niestety kod od ST przyjmuje wartość 72000000, co jest typowe dla ich płytek ewaluacyjnych (Discovery). Jednak inne płytki jak np. Nucleo, czy Kamami mogą pracować z innymi częstotliwościami, co niestety nie jest automatycznie rozpoznawane.
Skoro Twoja płytka pracuje poprawnie z SystemCoreClock ustawionym na 28800000, zegar systemowy ma prawdopodobnie taką częstotliwość.

Ponieważ generator wewnętrzny ma 8MHz, zewnętrzny 10MHz, a my szukamy 28.8MHz, prawdopodobnie uruchomiona jest pętla PLL. Teraz wypadałoby sprawdzić, gdzie znajduje się kod, który ją uruchamia.
Używasz innego środowiska niż opisywane w kursie, więc prosiłem Cię o pełny kod źródłowy - pownieważ nie mam tego IDE, nie wiem gdzie zaczyna się program.
Przy okazji ważne pytanie testowe - jak w szkole: gdzie zaczyna się program?

Postaw piwo autorowi tego posta
 
 
avrkwiat 




Posty: 18
Skąd: kwidzyn
Programuję w:
C, Java
Wysłany: 20-06-2016, 21:37   

Elvis, Na wstępie chcę podziękować Tobie za te oscylogramy. Były bardzo pomocne już wiem gdzie tkwił mój problem i problem z tymi bibliotekami. Już wyjaśniam.

1) Zakładałem, że jak w kodzie nie skonfiguruje żadnego zegara, to on automatycznie przydzieli mi HSI, czyli 8Mhz. Co okazało się błędnym założeniem. Za każdym razem trzeba konfigurować zegar, bo inaczej liczymy na szczęście.
2) Skonfigurowałem zegar w taki sposób:
Przypisałem HSE zewnętrzny 10Mhz do mnożnika 7, czyli uzyskałem 70Mhz:
Kod programu: Zaznacz cały
// PLLCLK = 10MHz * 7 = 70MHz
RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_7);

Następnie przypisałem PLL do SysClk:
Kod programu: Zaznacz cały
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

W tym momencie jak wywołam:
Kod programu: Zaznacz cały
SysTick_Config(70000000/1000);

Dostałem idealnie 1ms.
Powtórzyłem to dla innych ustawień, czyli ustawiłem 40Mhz i przypisałem:
Kod programu: Zaznacz cały
SysTick_Config(40000000/1000);

Dalej dostałem 1ms, wszystko grało jak należy. Problem był tylko wtedy, gdy chciałem użyć:
Kod programu: Zaznacz cały
SysTick_Config(SystemCoreClock / 1000); 

Wtedy pod zmienną SystemCoreClock nie ma aktualnego zegara, tylko coś innego i tu tkwi problem.
Dziś jestem już nieźle wydymany tym problemem, bo nie daje mi to spać i muszę odpocząć. Nie wiem, czy to jest wina CooCox, ale jeszcze to będę testował.
W sumie to można zamknąć temat ;) , bo mi się wyjaśniło, a nad poprawą tych bibliotek i tak popracuję.
Dzięki za wszystkie posty, które były pomocne.

Postaw piwo autorowi tego posta
 
 
Elvis 



Posty: 1187
Pomógł: 83 razy
Otrzymał 216 piw(a)
Skąd: wawa
Programuję w:
C, asm
Wysłany: 20-06-2016, 22:22   

Wydaje mi się, że jesteś już blisko rozwiązania zagadki, ale jeszcze trochę brakuje
Cytat:
Za każdym razem trzeba konfigurować zegar, bo inaczej liczymy na szczęście

Nie udostępniłeś całego programu, więc wyjaśnię "w ciemno".

W przypadku mikrokontrolerów program wcale nie zaczyna się wykonywać od funkcji main(), przed nią całkiem sporo się dzieje. Gdy tworzymy projekt za pomocą odpowiedniego kreatora, dodaje on kilka plików. Jeden ma najczęściej "startup" w nazwie i jest napisany w assemblerze, chociaż zdarza się i kod w C. W każdym razie zawartość tego pliku jest uruchamiana przed funkcją main. Kod jest odpowiedzialny za ustalenie adresu stosu, wyzerowanie zmiennych (inaczej zmienne globalne wcale nie miałyby początkowej wartości zero), wywołanie niskopoziomowych funkcji inicjalizujących, a na koniec funkcji main.
Okazuje się, że większość projektów dla STM32 przed funkcją main wywołuje inicjalizację zegara. Zawartość tej funkcji ustala więc początkową konfigurację. Gdyby usunąć jej treść, mielibyśmy to co podaje dokumentacja procesora - czyli HSI i 8MHz jako źródło zegara. Jednak jeśli zostawimy domyślny kod, najczęściej dostaniemy 72MHz z pętli PLL zasilanej z zewnętrznego generatora 8MHz. W przypadku Nucleo, środowisko OpenSTM32 potrafiło samo przygotować odpowiednie pliki dla wbudowanego generatora RC 8MHz i pętli PLL 64Mhz - ponieważ na płytce nie zamontowano kwarca niestety.
Nie jest to więc kwestia szczęścia, ale raczej sprawdzenia, co wyprawia kod uruchamiany przed funkcją main.

[ Dodano: 20-06-2016, 22:52 ]
Jako ciekawostkę poniżej możemy zobaczyć fragment pliku startup_stm32f10x_ms.S, który jest dodawany przez OpenSTM32 podczas tworzenia projektu (zgodnie z instrukcją z kursu):
Kod programu: Zaznacz cały
/* Call the clock system intitialization function.*/
    bl  SystemInit
/* Call static constructors */
    bl __libc_init_array
/* Call the application's entry point.*/
    bl    main
    bx    lr

Jak widać najpierw wywoływana jest funkcja SystemInit. To w niej konfigurowana jest pętla PLL i procesor zaczyna pracować na 64MHz. Dalej inicjalizowana jest biblioteka standardowa C. Instrukcja "bl main" powoduje skok do funkcji main, czyli miejsca gdzie większość programistów C zaczyna programowanie :)
Widzimy też co stanie się jeśli funkcja main zostanie zakończona - bx lr oznacza skok do funkcji, której adres jest w rejestrze lr. Jest to niestety błąd, który spowoduje dość dziwne zachowanie programu. Wniosek jest taki, że nie należy wychodzić z funkcji main, ani ufać dostawcom bibliotek.

Ostatnio zmieniony przez Elvis 20-06-2016, 22:54, w całości zmieniany 2 razy  
Postaw piwo autorowi tego posta
 
 
Więcej szczegółów
Wystawiono 1 piw(a):
avrkwiat
avrkwiat 




Posty: 18
Skąd: kwidzyn
Programuję w:
C, Java
Wysłany: 21-06-2016, 06:43   

Elvis, Dzięki za ten ostatni post, to wiele zmienia. Ja zawsze deklarowałem zegary i nawet tego nie zauważałem. Tu chciałem, aby kod był jak najkrótszy, żeby się zmieścił na 1 slajdzie prezentacji i to mnie zgubiło. Złe założenia, dobre chęci :P .
Ale dobrze posłuchać kogoś kto wie więcej na ten tema.
Co do bibliotek standardowych, to ja nigdy im nie ufałem i radziłem sobie w inny sposób widoczny na filmie (czyli doświadczalnie). Niestety nie jest to dobry sposób jak się chce, to wytłumaczyć w technikum ^^, bo za każdą zmianą zegara trzeba było podłączać oscyloskop i konfigurować go na nowo, albo liczyć z proporcji do nowych ustawień.
Dobrze, że dziś będę mógł już spać :D

Postaw piwo autorowi tego posta
 
 
patsos95 



Posty: 1
Wysłany: 22-09-2016, 13:02   

Witam. Mam problem ze zdebugowaniem pierwszego programu. Projekt założyłem dokładnie według poradnika ale wyskakuje mi błąd jak na obrazku:


błąd.png
Plik ściągnięto 20 raz(y) 152.82 KB

Ostatnio zmieniony przez patsos95 22-09-2016, 13:02, w całości zmieniany 1 raz  
Postaw piwo autorowi tego posta
 
 
Treker 




Posty: 7601
Pomógł: 114 razy
Otrzymał 491 piw(a)
Skąd: Gdynia
Programuję w:
C, Arduino
Moje roboty:
Spectrum, Fuzzy

Wysłany: 22-09-2016, 19:55   

patsos95, czy kompilacja i samo wgrywanie przebiega bez problemu? Wgrałeś wymagane sterowniki? Sprawdź też, czy nic innego nie korzysta z tego portu COM (np. terminal).


Zachęcam do korzystania z forum - nie pomagam indywidualnie przez PW/maila.
Sprawdź » Kurs ARDUINOKurs podstaw elektronikiZbuduj swojego robota - kurs!
Postaw piwo autorowi tego posta
 
 
darkmiki 



Posty: 2
Wysłany: 27-10-2016, 16:28   Migracja z F1 na F3

Hej, jak ktoś robi ten kurs na STM32F3, to znalazłem pdfa, który opisuje migrację z F1 na F3: KLIK

Postaw piwo autorowi tego posta
 
 
Qwerty123 



Posty: 2
Wysłany: 27-02-2017, 21:16   

Moze mi ktos powiedziec co jest zle w tym kodzie ze dioda nie chce migac? Stm32 L152re

Kod programu: Zaznacz cały

#include "stm32l1xx.h"
#include "stm32l1xx_nucleo.h"
           
void delay(int time)
{
    int i;
    for (i = 0; i < time * 4000; i++) {}
}

int main(void)
{
    GPIO_InitTypeDef gpio;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    GPIO_StructInit(&gpio);
         gpio.GPIO_Pin = GPIO_Pin_5;
         gpio.GPIO_Mode =  GPIO_Mode_OUT;
         gpio.GPIO_OType =  GPIO_OType_PP;
         GPIO_Init(GPIOA, &gpio);

         while (1) {
                     GPIO_SetBits(GPIOA, GPIO_Pin_5);
                     delay(50);
                     GPIO_ResetBits(GPIOA, GPIO_Pin_5);
                     delay(100);
                 }
         }

Postaw piwo autorowi tego posta
 
 
Treker 




Posty: 7601
Pomógł: 114 razy
Otrzymał 491 piw(a)
Skąd: Gdynia
Programuję w:
C, Arduino
Moje roboty:
Spectrum, Fuzzy

Wysłany: 01-03-2017, 20:16   

Qwerty123, w komentarzach do kursów staramy się rozmawiać tylko o sprzęcie omawianym w artykułach. Pisanie o rzeczach niezwiązanych bezpośrednio z kursem prowadzi do powstawania zamieszania i może zmylić innych czytelników w przyszłości. Jeśli masz problem z innymi elementami, to załóż proszę osobny temat na forum w odpowiednim dziale. Z góry dziękuję za zrozumienie i pomoc w utrzymaniu porządku :)


Zachęcam do korzystania z forum - nie pomagam indywidualnie przez PW/maila.
Sprawdź » Kurs ARDUINOKurs podstaw elektronikiZbuduj swojego robota - kurs!
Postaw piwo autorowi tego posta
 
 
niezly_patyk 



Posty: 5
Wysłany: 11-07-2017, 22:42   

Hej, jestem zakopany w dokumentacjach modułu i nie mogę doszukać rozwiązania.

Uruchamiam płytkę STM32f070BR.
Szukając w bibliotekach doszedłem do wniosku że GPIO są na szynie AHB - niestety nie mogę tej informacji znaleźć w datasheet'ach.
W której z dokumentacji mogę znaleźć rozpiskę jakie interfejsy podłączone są do jakiej szyny?

Proszę o pomoc.

Postaw piwo autorowi tego posta
 
 
Wyświetl posty z ostatnich:   
Odpowiedz do tematu
Nie możesz pisać nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Nie możesz załączać plików na tym forum
Możesz ściągać załączniki na tym forum
Wersja do druku

Skocz do:  

Nie rozwiązałeś swojego problemu? Zobacz podobne tematy: Kurs STM32 - #2 - Po... Kurs STM32 - #1 - Za... Kurs STM32 - #3 - Pł... Kurs STM32 - #5 - Ko...
lub przeszukaj forum po wybranych tagach: artykuly, elektronika, majsterkowanie, robotyka, wiadomosci


Powered by phpBB modified by Przemo © 2003 phpBB Group
Popularne kursy: Arduinopodstawy elektroniki