Skocz do zawartości

Jak pogodzić TIMER0 i delay()


pospiech

Pomocna odpowiedź

Dzień dobry.

Od czterech dni siedzę i kombinuję jak koń pod górę, a to wszystko przez to, że jestem w tym zielony jak pietruszka wiosną.

Ale nie o tym. Otóż Wymyśliłem sobie, że w pętli głównej będę sprawdzał dane przychodzące z terminala, przyciski itp.

Natomiast funkcje będą wywoływane w przerwaniu co określony czas. Problem mam z jedną funkcją w której są linie delay.

Gdy ta funkcja zostaje wywołana delay nie działa. A mi zależy żeby 'coś' na jakiś czas 'zatrzymało' działanie kodu.

Wiem, że delay nie powinno się używać z przerwaniami, ale wszystkie pomysły już chyba wyczerpałem dlatego proszę o pomoc.

Funkcja z którą mam problem ma za zadanie zmienić bieg pompy i dobrze byłoby w czasie zmiany biegu na chwilę zatrzymać pompę.

Przedstawię fragment kodu odpowiedzialny za konfigurację timera i funkcję przełączającą biegi

// Konfiguracja pobrana gdzieś z internetu
cli();
   EICRA |= (1 << ISC01);  // Ustaw zbocze opadające
   EIMSK |= (1 << INT0);   // Włącz przerwania zewnętrzne INT0
   TCCR1A = 0;
   TCCR1B = 0;
   TCNT1 = 0;
   OCR1A = TIMER_INTERVAL * 16; // Konwersja milisekund na liczbę impulsów zegarowych
   TCCR1B |= (1 << WGM12); // Tryb CTC
   TCCR1B |= (1 << CS12) | (1 << CS10); // Preskaler 1024
   TIMSK1 |= (1 << OCIE1A); // Włącz przerwania na porównanie
   sei(); // Włącz globalne przerwania
// Funkcja
void Pompa(byte Bieg){
  switch (Bieg) {
    case 0:
     digitalWrite(A1, HIGH);
     digitalWrite(A2, HIGH);
     digitalWrite(A3, HIGH);
     Tablica[3]=0;
    break;

    case 1:
      digitalWrite(A1, HIGH);
      digitalWrite(A2, HIGH);
      digitalWrite(A3, HIGH);
      delay(500);
      digitalWrite(A3, LOW);
      Tablica[3]=1;
    break;

    case 2:
      digitalWrite(A1, HIGH);
      digitalWrite(A2, HIGH);
      digitalWrite(A3, HIGH);
      //delay(500);
      digitalWrite(A1, LOW);
      //delay(500);
      digitalWrite(A3, LOW);
      Tablica[3]=2;
    break;

    case 3:
      digitalWrite(A1, HIGH);
      digitalWrite(A2, HIGH);
      digitalWrite(A3, HIGH);
      //delay(500);
      digitalWrite(A2, LOW);
      //delay(500);
      digitalWrite(A3, LOW);
      Tablica[3]=3;
    break;
  }

}

Dodam, że w programie jest też przewidziana inna funkcja, która zlicza impulsy generowane przez hallotron oraz funkcja odpowiedzialna za PWM. 

Funkcja z PWM działa dobrze, natomiast do licznika impulsów jeszcze nie doszedłem, ale zakładam, że nie będzie generowała problemów ponieważ w niej jest tylko

linia licznik++;

Serdeczne dziękuję za pomoc i poświęcony czas na rozwiązanie mojego problemu.

Gorąco pozdrawiam.

 

Link do komentarza
Share on other sites

czy ja dobrze rozumiem że funkcja 

void Pompa(byte Bieg)

jest wykonywana w przerwaniu od timera? Jeśli tak to ustaw w przerwaniu flagę że się ono wykonało np: 

volatile uint8_t isr_flag;

i później resztę kodu przenieś do maina, flagę musisz ręcznie kasować po wykonaniu swoich funkcji

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

@_LM_

Dnia 29.01.2024 o 15:41, _LM_ napisał:
volatile uint8_t isr_flag;

i później resztę kodu przenieś do maina, flagę musisz ręcznie kasować po wykonaniu swoich funkcji

Z ciekawości - dlaczego uint8_t a nie bool?

Link do komentarza
Share on other sites

Proponowane rozwiązanie przez LM jest prawidłowe. Polega ono na ustawieniu flagi w przerwaniu, która będzie sygnalizowała, że przerwanie zostało wykonane. Następnie, w pętli głównej, można sprawdzić stan flagi i wykonać odpowiednie działania.
 

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

Krócej się wykonuje ustawienie zmiennej na wartość niż ustawienie pojedynczego bitu, jest to związane z architekturą RISC. Można dać bool nie widzę przeszkód

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

Jest obejście, ale wolniejsze (sttuktura i zmienne określonej długości, w tym przypadku 1).

Coś w stylu 

struct {
  unsigned int zmienna1:1;
  unsigned int zmienna2:1;
  // i tak dalej
  } bulbul;
....
  bulbul.zmienna1 = true;

 Ew. Zawsze można testować/ustawiać konkretny bit (część procków ma instrukcje typu bset/bclr/btst).

Link do komentarza
Share on other sites

Ja miałem konieczność zmieszczenia wskaźnika, jakiejś wartości i paru flag w 32 bitach. Bez tego syntezator mowy na ESP32 w podstawowej wersji raczej by się w 4 MB nie zmieścił 🙂

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