Skocz do zawartości

Kurs STM32L4 – #7 – przerwania sprzętowe, obsługa błędów


Pomocna odpowiedź

Wyjaśnij jeszcze Co to znaczy że nie działa? Czy debugger wchodzi do tej funkcji czy widzisz zmieniające się wartości old value I value?

Kot może szaleć ponieważ uard nie jest szybkim peryferium jak za szybko będziesz wysyłał do niego dane to albo będziesz miał krzaki albo będziesz miał overrun i póki nie skasujesz flagi błędu To nic nie dostaniesz chyba że masz włączone nadpisywanie danych.

Generalnie wstawianie printf do przerwania to nie jest dobra praktyka i najczęściej służy celom dydaktycznym w ramach debugowania. Co do pytania odnośnie realizacji zadania trzeciego to wydaje mi się że o wrapowanie print efa jakoś funkcja nie miałoby już sensu bo i tak print jest realizowany przez wcześniejszą modyfikację putchar i tam siedzi Twój kod od uarta

Link do komentarza
Share on other sites

Witam. Mam problem z odbieraniem danych przez UART. Gdy dodaje breakpoint na funkcji funkcji HAL_UART_RxCpltCallback nic się nie dzieje. Nie mogę również wpisać w konsoli on/off. Czy to wina ustawienia konsoli? Używam PuTTy do komunikacji, ponieważ do programowania korzystam z Ubuntu.

/* USER CODE BEGIN 0 */
#define LINE_MAX_LENGTH 80

static char line_buffer[LINE_MAX_LENGTH + 1];
static uint32_t line_length;

void line_append(uint8_t value)
{
  if (value == '\r' || value == '\n') {
    // odebraliśmy znak końca linii
    if (line_length > 0) {
      // dodajemy 0 na końcu linii
      line_buffer[line_length] = '\0';
      // przetwarzamy dane
      if (strcmp(line_buffer, "on") == 0) {
        HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
      } else if (strcmp(line_buffer, "off") == 0) {
        HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
      }

      // zaczynamy zbieranie danych od nowa
      line_length = 0;
    }
  }
  else {
    if (line_length >= LINE_MAX_LENGTH) {
      // za dużo danych, usuwamy wszystko co odebraliśmy dotychczas
      line_length = 0;
    }
    // dopisujemy wartość do bufora
    line_buffer[line_length++] = value;
  }
}

uint8_t uart_rx_buffer;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if (huart == &huart2) {
    line_append(uart_rx_buffer);
    HAL_UART_Receive_IT(&huart2, &uart_rx_buffer, 1);
  }
}

int message_number = 0;

void send_next_message(void)
{
  static char message[] = "Hello World!\r\n";
  static char message2[] = "Forbot jest super!\r\n";

  switch (message_number)
  {
  case 0:
    HAL_UART_Transmit_IT(&huart2, (uint8_t*)message, strlen(message));
    message_number = 1;
    break;
  case 1:
    HAL_UART_Transmit_IT(&huart2, (uint8_t*)message2, strlen(message2));
    message_number = 2;
    break;
  default:
    break;
  }
}


void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart == &huart2) {
    	send_next_message();
    }
}

volatile uint32_t push_counter;

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if (GPIO_Pin == USER_BUTTON_Pin) {
	  push_counter++;
  }
}

int __io_putchar(int ch)
{
  if (ch == '\n') {
    __io_putchar('\r');
  }

  HAL_UART_Transmit(&huart2, (uint8_t*)&ch, 1, HAL_MAX_DELAY);

  return 1;
}


/* USER CODE END 0 */

Główna funkcja

nt main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */

  	  send_next_message();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	  uint32_t old_push_counter = push_counter;
  while (1)
  {
	  if(old_push_counter != push_counter) {
		  old_push_counter = push_counter;
		  printf("counter: %lu\n", old_push_counter);
	  }
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

Ustawienia NVIC obraz.thumb.png.ccae564700c51c98b1aadf683f6a5fa6.png

Dziękuję za pomoc! Pozdrawiam

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ść i czołem.

Jak zwykle świetny materiał. Widzę, że nikt wcześniej o to nie zapytał, więc sam postanowiłem zagaić temat odnośnie fragmentu ze "śmieciami" w miejscu byłej zmiennej. Jak to jest, że zmienna x utworzona w funkcji test trafiła akurat do tego konkretnego miejsca w pamięci? Spodziewałem się, że dysponowanie pamięcią na stosie przez program to bardziej kwestia przypadku, a okazuje się, że twórcy kursu byli w stanie na 100% przewidzieć, że u każdego czytelnika zmienna x pojawi się na miejscu zmiennej message. Jak to działa?

Przy okazji chciałem przypomnieć, że w komentarzach do tej części kursu jeden z autorów zadeklarował się, że wrzuci adnotację odnośnie zmiany przez ST domyślnego priorytetu dla przerwania System Tick Timer. Taka informacja byłaby cenna. Sam dopiero po czasie zauważyłem, że widnieje liczba 15 zamiast 0, ale mimo zdziwienia uznałem, że chyba przypadkowo sam to zmieniłem 😄

Pozdrawiam

Link do komentarza
Share on other sites

@masi23x Bardzo dobre pytanie, stos faktycznie wydaje się nieco magicznym i bardzo losowym zjawiskiem, chociaż w rzeczywistości wcale taki nie jest.

Zacznijmy jednak od wyjaśnienia czegoś innego - celem tego przykładu nie było pokazanie komunikatu jakie zobaczy użytkownik, ale zwrócenie uwagi, że wartości zmiennej lokalnej zostaną nadpisane i w rezultacie wysłany komunikat może być niepoprawny. Faktycznie, dokładna treść komunikatu może być różna w zależności od wersji i ustawień kompilatora. Okazuje się jednak, że skoro użytkownicy kursu używają mniej-więcej tej samej wersji środowiska CubeIDE, czyli bibliotek i kompilatora, więc uruchamiane programy działają bardzo podobnie.

Pojawia się więc kolejne, może nawet ciekawsze pytanie - jak to jest z tym stosem i czy wartości na nim są losowe? Okazuje się, że nie - procesory działają w sposób deterministyczny, więc i zawartość stosu jest przewidywalna. Więc jeśli jedna funkcja tworzy na stosie zmienne lokalne, a następnie kolejna funkcja będzie używała stosu, to nastąpi nadpisanie wartości - i o ile nie wystąpią przerwania używające tego samego stosu, to każde uruchomienie będzie dawało identyczne efekty.

 

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