Skocz do zawartości

Problem z zadaniem 4.1 kursu stm32 F1 HAL (lekcja #4)


Pomocna odpowiedź

Hej, próbuję przerobić kurs STM32 F1 HAL i na samym początku pojawiły się problemy, a mianowicie od kilku dni próbuję zrobić zadanie 4.1, jednak wszystkie próby kończą się niepowodzeniem. Ma może ktoś zrobione to zadanie i chciałby się nim podzielić oraz sposobem jego rozwiązania? Poniżej mój kod.

Z góry dziękuję!

#include "stm32f1xx.h"

int main(void)
{
SystemCoreClock = 8000000; // taktowanie 8Mhz

HAL_Init();

__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();


GPIO_InitTypeDef gpio; // obiekt gpio będący konfiguracją portów 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.Mode = GPIO_MODE_IT_RISING;
gpio.Pull = GPIO_PULLUP; // rezystory podciągające są wyłączone
gpio.Speed = GPIO_SPEED_FREQ_LOW; // wystarczą nieskie częstotliwości przełączania
HAL_GPIO_Init(GPIOC, &gpio); // inicjalizacja modułu GPIOC

gpio.Pin = GPIO_PIN_13; 	// konfigurujemy pin 13
gpio.Mode = GPIO_MODE_INPUT; 	// jako wejście
gpio.Pull = GPIO_PULLUP;		// włączamy rezystor podciągający
HAL_GPIO_Init(GPIOC, &gpio);	// port GPIOC

while (1) {
   if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET)
   {
	   uint32_t led = 0;
		  HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_SET); //włącz diode
		  HAL_Delay(150);
		  HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_RESET); //wyłącz diode
		  if (++led >= 10)
		  { // przejdz do nastepnej
			 led = 0;
		  }
		  else
		  {
			  uint32_t led = 10;
						  HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_SET); //włącz diode
						  HAL_Delay(150);
						  HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_RESET); //wyłącz diode
						  if (--led >= 10)
						  { // przejdz do nastepnej
							 led = 10;
		  }

  }
}
}
}
Edytowano przez Lay-Z
Zapomniałem dodać kodu
Link to post
Share on other sites

Zakładam, że konfiguracja jest poprawna. Z tego co rozumiem to po wciśnięciu przycisku czyli zwarciu pinu do masy zaczyna się w ogóle coś dziać. A jak nic nie wciskamy to wszystko ma być zgaszone tak? Przedstawiony kod działa w taki sposób, że zapalasz diodę o numerze 0 na porcie C, po 150ms ją gasisz, sprawdzasz czy led jest 10 lub więcej. Ale nie jest więc wykonuje się ten dziwny else i wtedy ustawia od razu led na 10 czyli 1010 (pewnie miga 2 i 4 dioda) a potem od razu spełniany jest kolejny warunek i led ustawia się na 10 i wraca na początek.

Coś mi się wydaje, że jest dość mocno namieszane i chyba trzeba to wszystko stworzyć od początku 🙂

Treść zadania:

"Przygotuj program, który zmienia kolejność zapalania diod w linijce LED po naciśnięciu przycisku."

 

Zacznij od zapalania diody od 0 do 7 co np. 300ms. Jak będzie chciał przejść na 8 to znów zacznij od 0. Jak to zadziała to odczytaj gdzieś sobie stan przycisku. Jak poprawnie wykrywa to zrób sobie zmienną, że każde naciśnięcie przycisku zmienia jej stan z 0 na 1 i odwrotnie z 1 na 0 (taki prosty automat stanów). Gdy to Ci będzie działać to w warunku if else dla tej zmiennej skopiuj sobie te zapalanie tyle, że w drugą stronę i to wszystko.

 

//czytaj stan przycisku - na kazde wcisniecie ma sie zmieniac z kierunek_prawo na kierunek_lewo i odwrotnie

if(kierunek_prawo)

{

//zapalaj w prawo

}
else

{

//zapalaj w lewo

}

 

Edytowano przez eldesigner
Link to post
Share on other sites

Przepraszam za tak długą zwłokę, ale pomimo wielu prób podejmowanych w kolejnych dniach mój kod nadal nie działa, i nie mogę wymyślić co dalej robić. 😞 

Link to post
Share on other sites

Napisałem wszystko od nowa i jakoś ruszyło, tylko żeby zapętlało w drugą stronę strzelam że trzeba użyć swego rodzaju switcha który przełącza stany zamiast definiować na sucho stan niski czy wysoki (1 i 0), tylko tutaj rodzi się kolejny problem, bo nie wiem jak miało by to wyglądać 😞. Byłbym bardzo wdzięczy za pomoc. Z góry dziękuję za wszelkie chęci!

#include "stm32f1xx.h"

int main(void)
{
    SystemCoreClock = 8000000; // taktowanie 8Mhz

    HAL_Init();

    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();

   GPIO_InitTypeDef gpio; // obiekt gpio będący konfiguracją portów 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.Mode = GPIO_MODE_OUTPUT_PP; // jako wyjście
   gpio.Pull = GPIO_NOPULL; // rezystory podciągające są wyłączone
   gpio.Speed = GPIO_SPEED_FREQ_LOW; // wystarczą nieskie częstotliwości przełączania
   HAL_GPIO_Init(GPIOC, &gpio); // inicjalizacja modułu GPIOC

    uint32_t led = 10;
   while (1) {
	   if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == 0)
	   {
      HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_SET); //włącz diode
      HAL_Delay(150);
      HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_RESET); //wyłącz diode
      if (--led >= 10) { // przejdz do nastepnej
         led = 10;
      }
	   }
	   else
	   {
		   HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_SET); //włącz diode
		         HAL_Delay(150);
		         HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_RESET); //wyłącz diode
		         if (++led >= 10) { // przejdz do nastepnej
		            led = 0;
		         }
	   }
   }
}

 

Link to post
Share on other sites

@Lay-Z inicjalizacja GPIO wygląda dobrze, użycie punkcji HAL też, ale zastanawiam się czy wybór pinu jest poprawny. W IDE możesz podejrzeć co oznacza np. GPIO_PIN_0 (u mnie jest to wartość: ((uint16_t)0x0001) i każdy kolejny to 2, 4, itd... czyli operacja 1<<n jest ok, ale może podmień to uint32_t?

Mniejsza o to skoro działa. Z tym przełączaniem potrzebujesz albo przerwanie zewnętrzne od przycisku - tu polecam zaznajomić się z CubeIDE fajnie to działa. Albo przy pollingu jak teraz dodaj dodatkową zmienną stanu która pamięta to co było ostatnio - dodaj coś w stylu lastState = state na końcu pętli i sprawdzaj w kolejnym obiegu czy:

state = HAL_GPIO_ReadPin....

if (lastState != state ....

oznacza to że coś się zmieniło czyli wystąpiło zbocze.

Wszystko to możesz też załatwić przerwaniem od GPIO 😉 

image.thumb.png.4f894ca80654a865514364fcf323fd24.png

Nie sugeruje się listą peryferiów, to jest na F4. Następnie w kodzie nadpisujesz funkcję:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
	HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);
}

W mainie generator dodaje obsługę przerwania, jak widać na zborze rosnące, ale możesz zmienić:

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOG_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOG, LED_GREEN_Pin|LED_RED_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : PA0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : LED_GREEN_Pin LED_RED_Pin */
  GPIO_InitStruct.Pin = LED_GREEN_Pin|LED_RED_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI0_IRQn);

}

 

Edytowano przez Gieneq
Link to post
Share on other sites

@Gieneq niestety pomimo wielu prób nie potrafię tego zrobić. Próbowałem użyć  HAL_GPIO_EXTI_Callback jednaj mój program nadal nie działał 😞. Nie mam już na to pomysłu 😞

Link to post
Share on other sites

@Gieneq Pokażę cały kod. Wymyśliłem coś takiego ale jak zaczynam sobie while'a to w kolejnej linijce :

if (HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13)) //tutaj mi błąd wywala

mam błąd. Nie wiem jak ten program ma wyglądać, próbuję wszystkiego po kolei i nic.  Dodałem jeszcze do pliku stm32f1xx_it.c taki kawałek: 

void SysTick_Handler(void)
{
	HAL_IncTick();
	HAL_SYSTICK_IRQHandler();
#ifdef USE_RTOS_SYSTICK
	osSystickHandler();
#endif
}

a oto końcowy kod:

#include "stm32f1xx.h"

void EXTI15_10_IRQHandler(void)
{
	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
}

int main(void)
{
	SystemCoreClock = 8000000; // taktowanie 8Mhz

	HAL_Init();

	__HAL_RCC_GPIOC_CLK_ENABLE();
	__HAL_RCC_GPIOA_CLK_ENABLE();

	GPIO_InitTypeDef gpio; // obiekt gpio będący konfiguracją portów 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.Pin = GPIO_PIN_13;
	gpio.Mode = GPIO_MODE_OUTPUT_PP;; // jako wyjście
	gpio.Pull = GPIO_PULLUP; // rezystory podciągające są wyłączone
	gpio.Speed = GPIO_SPEED_FREQ_LOW; // wystarczą nieskie częstotliwości przełączania
	HAL_GPIO_Init(GPIOC, &gpio); // inicjalizacja modułu GPIOC

	HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

uint16_t led = 10;
	while (1) {

		if (HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13))
		{
		HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_SET); //włącz diode
		HAL_Delay(150);
		HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_RESET); //wyłącz diode
			if (--led >= 10) { // przejdz do nastepnej
			 led = 10;
			}
		}
			else
			{
				HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_SET); //włącz diode
				 HAL_Delay(150);
				 HAL_GPIO_WritePin(GPIOC, 1 << led, GPIO_PIN_RESET); //wyłącz diode
					 if (++led >= 10) { // przejdz do nastepnej
						led = 0;
						 }
			}


	}
}

 

Link to post
Share on other sites

Można by też sięgnąć do dokumentacji i skonfigurować odpowiednie rejestry na piechotę. Poniżej przykład dla stm8L.

// config PORTB
PB_DDR = 0xff; // all output
PB_CR1 = 0xff; // all push_pull
// buton pin : input floating with interrupt
PC1_CR2 = ENABLE;

procedura przerwania

@far @interrupt void buttonPress (void)
{ 
	static char pin;
	EXTI_P1IS1 = SET; 
	PB_ODR = ((unsigned char)(1<<pin));
	if(pin<8) ++pin; else pin=0;
	EXTI_P1F = CLEAR_W1; 
}

 

Link to post
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

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.