Skocz do zawartości

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


Pomocna odpowiedź

Podczas obsługi przerwania blokowane jest przyjmowanie kolejnych o priorytecie niżym lub równym aktualnemu. Więc nic się złego nie stanie, jeśli kolejne zostanie zgłoszone podczas wykonywania procedury obsługi poprzedniego.

Link do komentarza
Share on other sites

Gratuluję autorowi kursu, posiada on "talent" do przekazywania wiedzy. Fajnie że potrafi on również zaciekawić czytelników szczególnymi przypadkami, pobudza to umysł.

 

Osobiście nie podoba mi się funkcja 'HAL_UART_Transmit_IT'. W tekście jest przedstawiona jako konkurent dla "bez_IT", wykorzystująca przerwania. Jednakże zgodnie z ideą przerwania, przerwanie zaczyna i kończy się w tym samym miejscu. Program główny nie ma prawa "ruszyć" się teraz nawet o 1 krok. Dlaczego więc możemy powiedzieć że 'HAL_UART_Transmit_IT' wysyła "dane w tle" wykorzystując przerwania ?  

Przecież gdy przerwanie trwa, jednostka zostawia program. Potem wykonuje przerwanie i wraca do głównej pracy. Dlaczego więc musimy się martwić co się dzieje za funkcją "przerwaniową" ?

Czy na pewno możemy w tym przypadku powiedzieć że dane od 'HAL_UART_Transmit_IT' są wysyłane przy wykorzystaniu przerwań ? Czy nie są to mechanizmy o innej nazwie ?

 

 

Link do komentarza
Share on other sites

Dziękuję za miłe słowa, przygotowanie tego kursu wymagało mnóstwa pracy od całego zespołu, tym milej jest słyszeć, albo raczej czytać, że praca nie poszła na marne 🙂

Natomiast co do przerwań i funkcji HAL_UART_Transmit_IT to chyba zaszło pewne nieporozumienie. Ta funkcja nie wysyła wszystkich danych natychmiast. Zamiast tego wstawia do rejestrów modułu UART pierwszy fragment danych i kończy działanie. Przerwanie zostanie wywołane gdy moduł UART wyśle dane i będzie oczekiwał na kolejne. W międzyczasie program główny będzie dalej wykonywany, więc dane będą przesyłane niejako w tle. Program będzie na chwilę zatrzymywany kiedy kolejne fragmenty danych będą przesyłane z bufora nadawczego do rejestrów układu, ale poza tym będzie działał normalnie.

Warto też wspomnieć, że po obsłudze przerwania nie zawsze program jest wznawiany w miejscu gdzie przerwanie się pojawiło. Tak jest najczęściej i jest to najprostszy przypadek, ale jeśli używamy FreeRTOS-a, albo piszemy program w bardzo nietypowy sposób, to wcale tak być nie musi.

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

Nie wiem co robię nie tak, ale nie działa u mnie HAL_UART_Receive_IT. Wykonuje się 2 razy i później już nic się nie dzieje.

Próbowałem na innym przykładzie i to samo. Po drugim razie nic się nie dzieje.

Czy ktoś miał podobny problem?

Edytowano przez heniu79
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ść, Gieneq to jest to co wpisałem w maina:

/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#define LINE_MAX_LENGHT 80

static char line_buffer[LINE_MAX_LENGHT +1];

/* USER CODE END PTD */





/* USER CODE BEGIN PV */

uint8_t uart_rx_buffer;

static uint32_t line_length;
/* USER CODE END PV */





/* USER CODE BEGIN 0 */
int __io_putchar(int ch)
{
    if(ch == '\n'){
        __io_putchar('\r');
    }

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

void line_append(uint8_t value)
{
    if(value=='\r' || value=='\n')
    {
        if(line_length > 0){
            line_buffer[line_length] = '\0';

            HAL_UART_Transmit_IT(&huart2, (uint8_t*)line_buffer, strlen(line_buffer));

        line_length = 0;
        }
    }
    else
    {
        if(line_length >= LINE_MAX_LENGHT)
        {
            line_length = 0;
        }

        line_buffer[line_length++] = value;
    }
}

/* USER CODE END 0 */





/* USER CODE BEGIN 2 */

  HAL_UART_Receive_IT(&huart2, &uart_rx_buffer, 1);

  /* USER CODE END 2 */





/* USER CODE BEGIN 4 */

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart == &huart2)
    {
        line_append(uart_rx_buffer);
        HAL_UART_Receive_IT(&huart2, &uart_rx_buffer, 1);
    }
}
/* USER CODE END 4 */

 

 

Chciałbym żeby wyświetliło to co wpisałem w terminal. Teraz czyta tylko 2 pierwsze znaki ale pozniej juz nic sie nie dzieje.

Z góry dziękuję za pomoc

 

Edytowano przez Gieneq
Zachęcam do korzystania z bloku kodu programu
Link do komentarza
Share on other sites

@heniu79 przepraszam że późno odpisuję, ale nie miałem okazji usiąść do L4. Nie wiem czy wiele to pomoże, ale u mnie działa...

Sprawdź czy masz ustawione przerwanie i dodaną diodę pod nazwą LD2.

image.thumb.png.be812ff695918568e08e9caf7b651cc1.pngimage.thumb.png.9b9028b1751d94b07d5e8c1016d48587.png

Mam wgraną najnowszą wersję IDE, ST-link i nowy projekt. Kod programu to 3 miejsca:

/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */

tu:

/* USER CODE BEGIN PV */
uint8_t uart_rx_buffer;
int __io_putchar(int ch)
{
  if (ch == '\n') {
    __io_putchar('\r');
  }

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

  return 1;
}

#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;
  }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if (huart == &huart2) {
    line_append(uart_rx_buffer);
    HAL_UART_Receive_IT(&huart2, &uart_rx_buffer, 1);
  }
}
/* USER CODE END PV */

i to z pustą pętlą główną:

  /* USER CODE BEGIN WHILE */
  HAL_UART_Receive_IT(&huart2, &uart_rx_buffer, 1);

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

i to u mnie działa. W Tera term piszesz (bez echa czyli bez widocznych znaków) i dioda się świeci lub gaśnie. Możesz też skorzystać z menu-edit i użyć wklejenia (paste):

image.thumb.png.0ac26be1f6eadf1c6717906bd279d323.png

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

@atm320 chyba najlepszą literaturą (jeżeli tak można to określić...) są dokumentacje. Masz tam opisane wszystko - sprzęt, dostępne funkcje, składnię jeżyka. Tylko przebrnięcie przez nie to spore wyzwanie, bo to nawet kilka tyś stron. Autor kursu tego dokonał, więc da się 🙂 

Link do komentarza
Share on other sites

Jestem początkujący i mam takie pytanie co mogę robić źle jeśli po kolei wykonuje wszystko z opisów ale gdy doszedłem do podrozdziału odbieranie danych z uart przez przerwania i chce przetestować funkcję przerwaniową void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) ustawiam breakpoint na ta funkcję jednak jak wprowadzam jakiś znak z terminala to tak naprawde nic się nie dzieje i mikrokontroler nie reaguje. Dodam , że reszta programu działa poprawnie oraz komunikacja z teraterm również jest poprawna.

Pomożcie 

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • 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.