Skocz do zawartości
Komentator

Kurs STM32 - #4 - Sterowanie portami GPIO w praktyce

Pomocna odpowiedź

A to nie działa tak że ustawiamy po ilu cyklach ma się zresetować timer?

Udostępnij ten post


Link to post
Share on other sites

Hej, mam pytanie z serii "nie bangla"

Posługuję się płytką z F411RE, dostosowałem przykład do niej zdaje się, i nadal nie działa. Oto kod:

int main(void)
{
GPIO_InitTypeDef gpio; // obiekt gpio z konfiguracja portow GPIO

RCC_APB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // uruchomienie zegara modulu GPIO
//problem solved - powinno byc RCC_AHB1PeriphClockCmd
GPIO_StructInit(&gpio); 			// domyslna konfiguracja
gpio.GPIO_Pin 	= GPIO_Pin_5; 		// konfigurujemy pin 5
gpio.GPIO_Mode = GPIO_Mode_OUT; 	// jako wyjscie
gpio.GPIO_OType = GPIO_OType_PP; 	// push pull
gpio.GPIO_Speed = GPIO_Fast_Speed;	// nfs
GPIO_Init(GPIOA, &gpio); 			// inicjalizacja modulu GPIOA

GPIO_SetBits(GPIOA, GPIO_Pin_5);

while(1);;;
}

dioda perfidnie nawet nie chce mrugnąć. Z góry dzięki za pomoc, i z dołu za kurs:)

Udostępnij ten post


Link to post
Share on other sites

Tak na szybko odpowiadając:

* Sok, kurs dotyczy STM32F103RB, jeśli masz problem z innym mikrokontrolerem, załóż proszę oddzielny temat. Nie sposób niestety napisać kursu dla wszystkich wersji STM32 na raz

* MacGyver, poprawną odpowiedź podał Chumanista - SysTick jest układem licznikowym, który z określoną częstotliwością zwiększa wbudowany rejestr. Gdy doliczy do zadanej wartości wywołuje przerwanie i zaczyna od nowa. Jeśli częstotliwość zegara systemowego wynosi 64MHz, to SysTick doliczy do 64000000 w 1 sekundę. Więc podając SystemCoreClock / 1000 dostajemy 1/1000s, czyli 1ms - bez szczególnej inteligencji ze strony funkcji SysTick_Config (jej inteligencja to odjęcie 1 od wyniku, więc nie musimy o tym pamiętać przekazując parametr)

* argens, - w zadaniu 4.2 używasz pętli while w procedurze obsługi przerwania. Nie należy tak robić! Przerwania należy obsługiwać jak najszybciej, ewentualne czasochłonne procedury przenosząc do programu głównego. Program 4.3 wygląda dużo lepiej (np. przesunięcie bitowe zamiast 10 razy tego samego w kolejnych if-ach). Natomiast program 4.4 jest straszny! Używanie kopiuj-wklej powinno być zakazane w konstytucji! Pomyśl czy nie da się tego napisać krócej (podpowiem - da się!).

Udostępnij ten post


Link to post
Share on other sites

Sok, obstawiam że Twój błąd tkwi tu:

RCC_APB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // uruchomienie zegara modulu GPIO

'APB1' i 'AHB1' to różne linie zegarowe.

Udostępnij ten post


Link to post
Share on other sites

Witam,

Mam problem ze zrozumieniem dość prostego fragmentu kodu a mianowicie początku fukcji

realizującej przerwanie:

olatile uint32_t timer_ms = 0; 

void SysTick_Handler()
{
if(timer_ms){				
	timer_ms--;
}

}

a mianowicie skoro zmiennej timer_ms zostało przypisane 0 to jak dochodzi do wejścia w pętlę

if(timer_ms). Wydaje się to niemożliwe gdyż wartość w nawiasie będzie 0 czyli False.

Pytanie nr 2 to zakładając, że weszliśmy do pętli if(timer_ms). Jaką wartość przyjmie zmienna timer_ms po odjęciu od 0 liczby 1. Czy przyjmuje ona górną wartość zakresu i zlicza w kolejnych dekrementacjach w dół?

Dzięki za wszelką pomoc.

Pozdrawiam,

Udostępnij ten post


Link to post
Share on other sites
a mianowicie skoro zmiennej timer_ms zostało przypisane 0 to jak dochodzi do wejścia w pętlę

if(timer_ms). Wydaje się to niemożliwe gdyż wartość w nawiasie będzie 0 czyli False.

W innym miejscu kodu (chyba funkcja delay...?) ustawiasz wartość zmiennej timer_ms na żądaną ilość milisekund, o ile dobrze pamiętam. 🙂

Pytanie nr 2 to zakładając, że weszliśmy do pętli if(timer_ms). Jaką wartość przyjmie zmienna timer_ms po odjęciu od 0 liczby 1. Czy przyjmuje ona górną wartość zakresu i zlicza w kolejnych dekrementacjach w dół?

Jeśli typ zmiennej określa, że zmienna ta przyjmuje wyłącznie wartości nieujemne, to kiedy od jej wartości zerowej odejmiemy jeden, otrzymujemy górną wartość zakresu, czyli dokładnie tak, jak mówisz. 🙂 Zauważ, że w tej funkcji to się nie stanie - dekrementujemy zmienną tylko wtedy, kiedy jest różna od zera. 😉

EDIT: "zakładając, że weszliśmy do pętli if(timer_ms)" - to nie jest pętla, tylko warunek. 🙂

Pozdrawiam.

Udostępnij ten post


Link to post
Share on other sites

Widzę, że draghan mnie wyręczył w odpowiedzi 🙂

Dodam tylko, że if to nie pętla.

Udostępnij ten post


Link to post
Share on other sites

Elvis, przynajmniej mamy z saper152 potwierdzenie, że się nigdzie nie pomyliłem. 🙂

Wybacz za lekki offtop, ale ciekawy jestem. Kiedy piszesz posta i ktoś w międzyczasie doda odpowiedź, zostajesz o tym poinformowany? Wiem, że na niektórych forach tak to działa.

Udostępnij ten post


Link to post
Share on other sites
Wybacz za lekki offtop, ale ciekawy jestem. Kiedy piszesz posta i ktoś w międzyczasie doda odpowiedź, zostajesz o tym poinformowany? Wiem, że na niektórych forach tak to działa.

Niestety u nas jeszcze tego nie ma 🙁

Udostępnij ten post


Link to post
Share on other sites

Dzięki serdeczne za pomoc, teraz jest to już wszystko jasne. Co do pytania owszem:

dostałem na skrzynkę powiadomienie o odpowiedzi.

Pozdrawiam,

Udostępnij ten post


Link to post
Share on other sites

moj sposób na licznik Johnona,

/**

******************************************************************************

* @file main.c

* @author Ac6

* @version V1.0

* @date 01-December-2013

* @brief Default main function.

******************************************************************************

*/

#include "stm32f10x.h"

volatile uint32_t timer_ms = 0;

volatile uint32_t i = 0;

void SysTick_Handler()

{

if (timer_ms) {

timer_ms--;

}

}

void delay_ms(int time)

{

timer_ms = time;

while (timer_ms) {};

}

int main(void)

{

GPIO_InitTypeDef gpio;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

GPIO_StructInit(&gpio);

gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2| GPIO_Pin_3| GPIO_Pin_4| GPIO_Pin_5| GPIO_Pin_6| GPIO_Pin_7| GPIO_Pin_8| GPIO_Pin_9;

gpio.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOC, &gpio);

SysTick_Config(SystemCoreClock / 1000);

uint32_t x = 0b0000111000;

while (1)

{

GPIO_SetBits(GPIOC, x);

delay_ms(500);

GPIO_ResetBits(GPIOC , x);

delay_ms(500);

if((x << 1) > 0b1111111111)

{

x = (x << 1) & 0b1111111110;

}

else

{

x = (x << 1) | 0b0000000001;

}

}

}

__________

Komentarz dodany przez: Treker

Kody programów, dla lepszej czytelności, należy umieszczać w tagach .

Popraw to proszę 🙂

Udostępnij ten post


Link to post
Share on other sites

Wybaczcie, że pytam, ale jakoś nie umiem znaleźć informacji, albo jestem ślepy. Które konkretnie piny to port C? A które to port B i port A? Jakoś nie umiem dostrzec tego szczegółu w datasheecie ,a podejrzewam , że dowolnie sobie nie można podłączyć kabelków do pinów i założyć "tu jest właśnie pin 10 portu C". Ktoś mógłby pomóc?

EDIT:

Nie było pytania, jestem ślepy, wszystko jest na karteczce z pudełka z płytką.

Post zostawię, może komuś się przyda 😋

Mam natomiast inne pytanie, gdzie w takim razie można taki opis znaleźć, jakby tak się zgubiła ta kartka z pudełka?

Udostępnij ten post


Link to post
Share on other sites
 GPIO_SetBits(GPIOC, 1 << led); //włącz diode

Ktoś byłby tak miły w przystępny sposób wyjaśnić co dzieję się w tej linijce?

Wiem, że to jest przesunięcie bitowe (a tak przynajmniej mi się wydaje), ale nie bardzo rozumiem jak to działa w tym przykładzie.

Udostępnij ten post


Link to post
Share on other sites

W przypadku AVR popularne jest makro _BV(), które działa dokładnie jak ten przykład.

Napierw popatrzmy jak są zdefinowane stałe odpowiedzialne za odwoływanie do dopowiednich pinów:

#define 	GPIO_Pin_0   ((uint16_t)0x0001)
#define 	GPIO_Pin_1   ((uint16_t)0x0002)
#define 	GPIO_Pin_2   ((uint16_t)0x0004)
#define 	GPIO_Pin_3   ((uint16_t)0x0008)

Jest ich 16, ale mam nadzieję że ten fragment pokazuje jaki jest schemat: i-ty pin odpowiada wartości 2^i. Najłatwiej 2^i policzyć właśnie przez przesunięcie bitowe. Czyli 1 << i.

Możmy to łatwo sprawdzić:

1 << 0 = 1 ( = 2 ^ 0)

1 << 1 = 2 ( = 2 ^ 1)

1 << 2 = 4 ( = 2 ^ 2)

1 << 3 = 8 ( = 2 ^ 3)

1 << 4 = 16 ( = 2 ^ 4)

itd.

  • Lubię! 1

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ść
Napisz odpowiedź...

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