Skocz do zawartości

Kurs STM32 - #4 - Sterowanie portami GPIO w praktyce


Komentator

Pomocna odpowiedź

Treker, Ok, czyli mam rozumieć że GPIOx_SetBits(GPIOC ,1) ustawia pin zero portu x w stan wysoki, (GPIOx,"10") pin pierwszy, "100" pin drugi itd? Oczywiście jest to zapis binarny więc pewnie nie można go użyć w kompilatorze tak jak ja to zrobiłem czyli "10000" lub "10" stąd ta funkcja przesunięcia bitowego od "1" czyli jedynki na najmłodszym bicie. Z czego to wynika? Czy jest to odwołanie do rejestru? Kiedyś czytałem o rejestrze GPIOx_ODR. Czy on działa właśnie tak tzn jedynka na odpowiednim miejscu 16bitowego rejestru wyzwala stan wysoki w przypadku skonfigurowania portu wcześniej jako wyjście? Pytanie jeszcze o dokumentacje, gdzie najlpiej szukać opisu pinów i ich funkcji alternatywnych(który dokumnet ew. strona)? Czy w Eclipsie da się rozwinąć liste funkcji biblioteki na pasku po prawej lub lewej stronie? W Keilu była taka możliwość, w zakładce GPIO po rozwinięciu miałeś wszystkie funkcje dotyczące portów.

dzięki i pozdrawiam

Link do komentarza
Share on other sites

Oczywiście jest to zapis binarny więc pewnie nie można go użyć w kompilatorze tak jak ja to zrobiłem czyli "10000" lub "10" stąd ta funkcja przesunięcia bitowego od "1" czyli jedynki na najmłodszym bicie. Z czego to wynika?

Jeśli wpisujesz "10000" to jest to traktowane jako liczba dziesiętna. Zapis binarny musi być poprzedzony stosownym przedrostkiem. Najczęściej korzysta się jednak z przesunięć bitowych, ponieważ jest to najwygodniejsze 🙂

Link do komentarza
Share on other sites

Udało mi się zrobić licznik Johnsona.

	uint32_t counter = 0;

int setBits = 0b0000000001;
int resetBits = 0b0000000000;
while (1) {
	GPIO_SetBits(GPIOC, setBits << counter);
	GPIO_ResetBits(GPIOC, resetBits << counter);

	counter++;
	if (counter >= 10) {
		setBits = setBits ^ 0b0000000001;
		resetBits = resetBits ^ 0b0000000001;
		counter = 0;
	}
	delay_ms(1000);
}

Brakowało mi ustawiania pinów tak jak w AVR gdzie jeśli podałem 0 to zapisywał do rejestru 0 a jeśli 1 to zapisywał jeden. Dzięki temu mógłbym tylko negować zbiór bitów.

Ale tutaj mamy dwie procedury jedną do ustawiania 1 i jedną do ustawiania 0 więc musiałem zrobić dwa zbiory bitów.

Czy da się to zrobić jakoś lepiej?

[ Dodano: 14-02-2018, 17:34 ]

I mam jeszcze pytanie odnośnie przerwań.

Po co na początku konfigurować numer linii:

exti.EXTI_Line = EXTI_Line13;

Skoro później i tak muszę podać port i numer pinu?

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);

Rozumiem, że numer linii 13 jest dlatego że przycisk jest pod pinem 13 tak?

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

Cześć

Mam olbrzymią prośbę. Czy ktoś mógłby pomóc mi przerobić podany w kursie kod do komunikacji USART na STMF401RE ? 

Nie mogę sobie poradzić. Nie mogę znaleźć RCC_APB2Periph_AFIO, nie wiem czym to zastąpić.

Z góry bardzo dziękuję. 

Pozdrawiam

Edytowano przez Protektor28
Link do komentarza
Share on other sites

Nic dziwnego, że coś takiego nie istnieje - wklejasz do M4 kod napisany dla M3. Chociaż różnic nie ma znowu tak wiele, to jednak nie uda Ci się nic zdziałać bez zaglądania do datasheeta. Porównaj sobie chociażby sposób podłączenia RCC do GPIO:

M3 F1.thumb.jpg.4d05570db28899b08e0cce8444a2e73b.jpg

M4 F4.thumb.jpg.01f768012176b1675bfc1d278272389b.jpg

A tutaj masz poprawiony kod do nadawania:

#include "stm32f4xx.h"

void send_char(char c){
	while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
	USART_SendData(USART2, c);
}

void send_string(const char* s){
	while (*s)
	send_char(*s++);
}

int main(void){
	GPIO_InitTypeDef gpio;
	USART_InitTypeDef uart;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE);
//	RCC_APB1PeriphClockCmd(RCC_APB1Periph_AFIO, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);


	GPIO_StructInit(&gpio);
	gpio.GPIO_Pin = GPIO_Pin_2;
	gpio.GPIO_Mode = GPIO_Mode_AF;
	GPIO_Init(GPIOA, &gpio);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);

	gpio.GPIO_Pin = GPIO_Pin_3;
	gpio.GPIO_Mode = GPIO_Mode_AF;
	GPIO_Init(GPIOA, &gpio);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);

	USART_StructInit(&uart);
	uart.USART_BaudRate = 115200;
	USART_Init(USART2, &uart);
	USART_Cmd(USART2, ENABLE);

	while (1) {
		send_string("Hello world!\r\n");
	}
}

i odbierania danych:

#include "stm32f4xx.h"

void send_char(char c){
	while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
	USART_SendData(USART2, c);
}

void send_string(const char* s){
	while (*s)
	send_char(*s++);
}

int main(void){
	GPIO_InitTypeDef gpio;
	USART_InitTypeDef uart;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE);
//	RCC_APB1PeriphClockCmd(RCC_APB1Periph_AFIO, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);


	GPIO_StructInit(&gpio);
	gpio.GPIO_Pin = GPIO_Pin_2;
	gpio.GPIO_Mode = GPIO_Mode_AF;
	GPIO_Init(GPIOA, &gpio);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);

	gpio.GPIO_Pin = GPIO_Pin_3;
	gpio.GPIO_Mode = GPIO_Mode_AF;
	GPIO_Init(GPIOA, &gpio);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);

	USART_StructInit(&uart);
	uart.USART_BaudRate = 115200;
	USART_Init(USART2, &uart);
	USART_Cmd(USART2, ENABLE);

	while (1) {
		 if (USART_GetFlagStatus(USART2, USART_FLAG_RXNE)) {
		     char c = USART_ReceiveData(USART2);
		     switch (c)
		     {
		         case 'a':
		             send_string("Odebrano komunikat A!\r\n");
		             break;
		         case 'b':
		             send_string("Odebrano komunikat B!\r\n");
		             break;
		         default:
		             send_string("Nieznany komunikat:(\r\n");
		             break;
		     }
		 }
	}
}

Nie sprawdzałem, ale powinno działać.

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

Bardzo dziękuję Nawyk !

Program działa. Jedyną rzecz (czego nie rozumiem) jaką należy zmienić to USART_BaudRate . Jeśli chcę by nadawał z wartością 115200 to muszę wpisać (przynajmniej w moim wypadku) wartość trzy razy większą: USART_BaudRate = 345600. Doszedłem do tego sprawdzając po kolei wszystkie możliwe prędkości po stronie komputera, bo pojawiały się "krzaczki". 

Jestem ogromnie wdzięczny i jeszcze raz bardzo dziękuję.

Pozdrawiam :)))

Link do komentarza
Share on other sites

Luzik 🙂 Pewnie masz domyślne ustawienia w PLL (dla 25 MHz zamiast dla kwarcu 8 MHz). Na APB1 (od USART2) powinieneś mieć 42 MHz

#define PLL_M      8
#define PLL_N      336
#define PLL_P      2
#define PLL_Q      7

A tak to wygląda w całej okazałości (swoją drogą - polecam CubeMX):

pll.thumb.jpg.80249ae47c0eacc597e195b610061ed9.jpg

edit:

Właśnie przyjrzałem się Twojej płytce i widzę, że tam w ogóle nie ma wlutowanego HSE 😄 W każdym razie masz coś namieszane w ustawieniach zegarka, a objawy 25/8 akurat zgadzałyby się z Twoim problemem 🙂

Edytowano przez Nawyk
  • Lubię! 1
Link do komentarza
Share on other sites

Cześć.

Wyglądałoby to tak: 

gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;

Stan wysokiej impedancji zwany jest właśnie jako floating. Jeżeli piszesz kod to warto użyć skrótu "lewy_ctrl+spacja", pozwoli on na uzyskanie podpowiedzi o możliwych opcjach w danej funkcji itd.

Szybka odpowiedź, ale jestem nowy na forum. 😉

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

@MaciejZyskowski, witam na forum 😉 Widzę, że to Twoje pierwsze kroki na Forbocie, oto najważniejsze informacje na start:

  • Chcesz przywitać się z innymi członkami naszej społeczności? Skorzystaj z tematu powitania użytkowników.
  • Opis najciekawszych funkcji, które ułatwiają korzystanie z forum znajdziesz w temacie instrukcja korzystania z forum - co warto wiedzieć?
  • Poszczególne posty możesz oceniać (pozytywnie i negatywnie) za pomocą reakcji - ikona serca w prawym dolnym rogu każdej wiadomości.
12 godzin temu, MaciejZyskowski napisał:

Szybka odpowiedź, ale jestem nowy na forum.

Witamy - miło, że od razu zaczynasz od pomocy innym 😉

  • Lubię! 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.