Skocz do zawartości

Wielozadaniowość w C


Krawi92

Pomocna odpowiedź

Witam, chciałbym aby ktoś podpowiedział, jak jako początkujący podejść do tego tematu, wykonywania kilku procesów w tle. Np: robię sobie prosty wiatrak,sterowany PWM, może kręcić się wolno,srednio,maksymalnie,wlaczyc,wylaczyc. Zrobiłem to na klawiszach i zwykłej instrukcji IF. Chciałem, żeby servo mi też go obracało. No i tu się zaczyna właśnie problem.  Wiem, że temat bardzo często wałkowany, czytam że takie rzeczy robi się w przerwaniach itp. Piszą też o maszynach stanu ale trochę ciężko mi przejść przez ten gąszcz informacji.  Pytanie, czy na tak poczatkowym etapie jestem w stanie to wg zrobić.

Link do komentarza
Share on other sites

Można to zrobić przy użyciu timera:

#include <avr/io.h>
#include <avr/interrupt.h>
  
  volatile uint8_t timer1;
  volatile uint8_t timer2;
  volatile uint8_t timer3;
  
int main(void){
 //konfiguracja timera
  TCCR0 |= (1<<WGM01);//ctc
  TCCR0 |= (1<<CS00)|(1<<CS00);// start t/1024
  OCR0 = 40;
  TIMSK |= (1<<OCIE0);
  
  sei();
  

  
for(;;){
  if(!timer1){
    //zadania
  timer1 = 100;
  }
  
  if(!timer2){
  //zadania
  timer2 = 50;
  }
  
  if(!timer3){
  
    timer3 = 10;
  }
  
}
}

// Przerwanie: zegar systemu

ISR(TIMER0_COMP_VECT){
if(timer1) timer1--;
if(timer2) timer2--;
if(timer3) timer3--;
}

Potem zależnie od interwałów wykonywać zadania, musisz pamiętać aby przy takim podejściu rozważnie używać funkcji _delay_

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

I tak np: aby coś zrobić gdy klawisz naciśnięty, potrzebujesz kolejnej zmiennej

uint8_t czasSW;

później już w pętli np dla timera3 sprawdzasz

  if(!timer3){
  
    if(!SWPIN && licznikSw < 6){
    	licznikSw ++;
      if(licznikSw == 4)
        // tu zadanie po naciśnięciu
    
    } else if(SWPIN) licznikSw = 0; // przygotowanie do nast naciśnięcia
     timer3 = 10;
  }   
    

Oczywiście musisz sobie przygotować funkcje przycisków itd... W ten sposób możesz dzielić sobie program na kolejne zadania, np wyświetlanie czegoś na lcd, czy kręcenie serwem. Następnym naturalnym krokiem jest wykorzystanie wskaźników na funkcje, dzięki czemu można je przechowywać w tablicach co drastycznie zmniejsza ilość if - ów w programie 😉 ale na to już potrzebowałbym nieco czasu aby przygotować przykład. Myślę że teraz byłby dobry moment abyś pokazał swój program, możemy spróbować coś z nim zrobić.

Edytowano przez _LM_
Link do komentarza
Share on other sites

2 godziny temu, Krawi92 napisał:

trochę ciężko mi przejść przez ten gąszcz informacji.

Wielki mi gąszcz, trzy krzaczki na krzyż i to bez kolców

Tutaj masz bardzo ładny przykład maszyny stanów - pewnie przypadkiem pominąłeś ucząc się z kursu Arduino, prawda?

 

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

Wstawiam wersję dla AtMegi328 - sprawdzoną działającą, możesz sprawdzić podłączając do portu C 1...3 diody led a do PB1 przycisk.

#include <avr/io.h>
#include <avr/interrupt.h>

volatile uint8_t timer1,timer2,timer3;

uint8_t swCount;

int main(void){

	DDRC|= (1<<PC1)|(1<<PC2)|(1<<PC3); // wyjscia
	PORTB|=(1<<PB1); // przycisk


	TCCR0A |= (1 << WGM01);					// tryb CTC
	TCCR0B |= (1 << CS02) | (1 << CS00);	// preskaler = 1024
	OCR0A = (F_CPU / 1024UL) / 100UL;		// 100ms - 100Hz
	TIMSK0 |= (1 << OCIE0A);				// przerwanie Compare Match
		// przerwanie Compare Match
sei();
	for(;;){

		if(!timer1){ // proces 1
			PORTC^= (1<<PC1);
			timer1 = 200;
		}



		
		
		if(!timer2){ // proces 2
			PORTC^= (1<<PC2);
			timer2 = 20;
		}

		
		
		if(!timer3){ // proces 3

			if(!(PINB & (1<<PB1)) && swCount < 30){

				if(++swCount == 5)PORTC^= (1<<PC3);

			}else if(PINB & (1 << PB1))swCount = 0;


			timer3 = 5;
		}


	}
}

ISR(TIMER0_COMPA_vect){

	if(timer1)timer1--;
	if(timer2)timer2--;
	if(timer3)timer3--;
}

 

Link do komentarza
Share on other sites

Jest taki temat na tym forum "Proste podświetlanie schodów na Arduino. Prośba o pomoc w stworzeniu programu".Jest tam mój program,w ramach pomocy, oraz załącznik a w nim genialna biblioteka Timers.Przeczytaj moje rozwiązanie i zastosuj.Poczytaj o bibliotece Timers a wszystko się stanie jasne.

Link do komentarza
Share on other sites

Albo jako tako spróbuj zrobić miganie 3 diodkami (każda w inny sposób) korzystając z _delay_ms(1) <to sugestia, bo z tego co pamiętam mówiłeś, że czytałeś książkę Kardasia, on nawet jakieś filmy na ten temat nagrywał i wspominał o takim ćwiczeniu>

Link do komentarza
Share on other sites

Jestem w trakcie czytania, narazie tak jednym tchem przeczytałem, żeby zobaczyc co i jak. Teraz od początku już na spokojnie czytam. Jeśli chodzi i miganie diodami to migalem 3 diodami niezależnie(1 w pętli głównej, dwie w oparciu o timery sprzętowe). 

Link do komentarza
Share on other sites

Jeszcze tylko dodam, że z jednego timera sprzętowego możesz zrobić (w przybliżeniu) dowolną liczbę timerów programowych czyt.
ustawiasz jakikolwiek timer na np. 1ms i w obsłudze przerwania:

if (timer1)
  timer1--;
if (timer2)
  timer2--;
...

a ile czasu mają odmierzać to ustawisz sobie już w pętli głównej zwykle

Edytowano przez BananWszyscy
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.