Skocz do zawartości

Kurs STM32 F1 HAL - #4 - sterowanie GPIO w praktyce


Komentator

Pomocna odpowiedź

W poprzednim kursie STM32 z biblioteką StdPeriph funkcja delay

void delay(int time)
{
   int i;
   for (i = 0; i < time * 4000; i++) {}
}

faktycznie miała tę 1 milisekundę co przekładeło się, że procesor działał z taktowaniem 64MHz.

 while (1) {
       GPIO_SetBits(GPIOA, GPIO_Pin_5); // zapalenie diody
       delay(1000);
       GPIO_ResetBits(GPIOA, GPIO_Pin_5); // zgaszenie diody
       delay(1000);
   }

dejmieno, twój kod wraz z tą samom funkcją działa 8x wolniej.

while (1){
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
	delay(1000);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
	delay(1000);
}

Oby dwa testowałem przez 4-8 cykli aby być pewnym czasów.

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

#include "stm32f1xx.h"

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
 HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
}

int main(void){
 SystemCoreClock = 8000000;
 HAL_Init();

 __HAL_RCC_GPIOA_CLK_ENABLE();
 __HAL_RCC_GPIOC_CLK_ENABLE();

 GPIO_InitTypeDef gpio;
 gpio.Pin = GPIO_PIN_5;
 gpio.Mode = GPIO_MODE_OUTPUT_PP;
 gpio.Pull = GPIO_NOPULL;
 gpio.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(GPIOA, &gpio);
 gpio.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
 gpio.Mode = GPIO_MODE_OUTPUT_PP;
 gpio.Pull = GPIO_NOPULL;
 gpio.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(GPIOC, &gpio);

 gpio.Pin = GPIO_PIN_13;
 gpio.Mode = GPIO_MODE_IT_RISING;
 gpio.Pull = GPIO_PULLUP;
 HAL_GPIO_Init(GPIOC, &gpio);

 HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

 uint32_t led = 0;
 while(1){
	if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == GPIO_PIN_RESET){
           HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_SET);
           HAL_Delay(150);
           HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_RESET);
           if(++led >= 4) led = 0;
       } else{
           HAL_GPIO_WritePin(GPIOC, 8 >> led, GPIO_PIN_SET);
           HAL_Delay(150);
           HAL_GPIO_WritePin(GPIOC, 8 >> led, GPIO_PIN_RESET);
           if(++led >= 4) led = 0;
       }
 }
}

Moje rozwiązanie zadanie 4.1. Stan diody PA5 zmieniany jest poprzez interwencję. Czy da się w jakiś sposób utworzyć zmienną w funkcji HAL_GPIO_EXTI_Callback() i przesłać ją do funkcji main()? 

Edytowano przez Emerid
Link do komentarza
Share on other sites

@Emerid możesz do typu zmiennej będącej licznikiem pętli dodać volatile, wtedy optymalizator nie będzie mógł całkiem wyrzucić tej pętli.

Natomiast co do drugiego pytania, to chyba chodzi Ci po prostu o zmienną globalną, wtedy zarówno callback, jak i funkcja main będą miały do niej dostęp. Tutaj podobnie jak w przypadku pętli użycie volatile może być potrzebne.

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

Panowie, mam problem z zadaniem 4.2.

Nie widzę żadnego sensownego rozwiązania; próbowałem lecieć na

while (1) {

    	if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET) {
    		for(i=1;i<=5;i++) {
    			switch(i){
    			case 1:
    				 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET);
    				 i++;
    				 HAL_Delay(200);
    				 break;

i tak dalej ale skutkuje to natychmiastowym wykonaniem kodu.

Link do komentarza
Share on other sites

Dnia 12.10.2020 o 17:16, Treker napisał:

@drawix a na czym dokładnie utknąłeś? Nie wiesz jak rozwiązać to zadanie czy chodzi o kwestie typowo programistyczne?

poradziłem sobie, kwestia programistyczna i braku obycia z C.

Pętla była wykonywana cała przez "for", wyrzuciłem fora i ledy zapalały się po kolei 🙂

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

Skąd wiadomo że procesor jest traktowany z 8MHz? Bardzo proszę o wskazanie fragmentu z dokumentacji gdzie można to odczytać. Znalazłem na samym początku datasheetu że f103rb ma kilka wewnętrznych oscylatorów, m.in 8MHz. Lecz to raczej nie wystarczy żeby myśleć że jest z niego domyślnie taktowany, gdyż mam też STM32 L476RG i ten mikrokontroler jest taktowany z 4MHz a w datasheet jest napisane że ma wewnętrzny oscylator 16MHz.

Bardzo proszę o wyjaśnienie, gdyż często mam problem ze znalezieniem informacji o domyślnej częstotliwości taktowania.

Link do komentarza
Share on other sites

@Pawpob, ponieważ w tej części kursu nie były nigdzie konfigurowane zegary, na początku programu zatem taktowanie jest takie jak domyślne- takie jak po resecie. A jaki oscylator jest włączony i z czego taktowany jest zegar systemowy SYSCLK? To możesz znaleźć w Reference Manualu (link był podany w kursie, to ten najdłuższy dokument niestety 😄 ).

Na początku działu RCC pewnie jest to gdzieś w tekście, ale na szybko Ci odpiszę, że możesz zerknąć w opis rejestrów RCC_CR oraz RCC_CFGR (str. 99 i str. 101). Zwróć uwagę zwłaszcza na ich końcówkę i napisaną nad nimi "Reset value". W tym pierwszym rejestrze ostatni bit to domyślnie 1 (oznacza włączony HSI). W tym drugim rejestrze ostatnie 2 bity to wybrany zegar systemowy- domyślne 00 oznacza HSI wybrany jako źródło. A oscylator HSI ma 8 MHz 🙂

Podaję, bo znalazłem na szybko link:
https://www.st.com/resource/en/reference_manual/cd00171190-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf

  • Lubię! 1
  • Pomogłeś! 1
Link do komentarza
Share on other sites

Cześć 🙂

Mam chyba oczywiste pytanie, ale nie mogę tego rozgryźć, jak dokładnie działą instrukcja z poniższej linijki: 1 << led ?

 HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_SET); //włącz diode

Z góry dzięki za odpowiedź! 

Edytowano przez Justyna1101
Link do komentarza
Share on other sites

@Justyna1101 jest to operacja przesunięcia bitowego. Sprzętowo wykonuje się bardzo szybko. LEDy w tym zadaniu są tak dobrane aby były kolejno ponumerowane i w rejestrze ich adresy są kolejnymi pozycjami binarnymi. Czyli aby je ustawić LED można skorzystać z przesunięcia bitowego <<, wtedy binarnie wartość powędruje o ileś pozycji w lewo.

Ogólnie to co masz po lewej to wartość którą wpisujesz do zmiennej, a następnie przesuwasz ją w lewo.

Jeżeli chodzi o wartość to są to potęgi liczby 2 (jak cały system binarny). Tu masz przykład wartości w Pythonie (bo szybko się odpala konsola):

image.thumb.png.987b0fc66f5bacf46b8e793f84df2250.png

Edytowano przez Gieneq
  • Lubię! 1
  • Pomogłeś! 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.