Skocz do zawartości

Wielozadaniowość w C


Krawi92

Pomocna odpowiedź

18 minut temu, Krawi92 napisał:

że nie mogę już wyjść z funkcji ? 

Alez wychodzisz z tej funkcji tylko ze odrazu do niej wchodzisz...😉 nigdzie nie masz zadnego opoznienia wiec z punktu widzenia (oka) wydaje sie ze caly czas jestes w tej funkcji...a zrob tak i zobacz czy cos sie zmienilo...

case 2:
   PORTD &=~LED1;
   migaj();
   licznik++;
   break;

 

Link do komentarza
Share on other sites

Robisz blad ktory juz robiles w innym watku...chxesz sprawdzac stan zmiennej...nawet nie wiem jak to nazwac...jezeli chcesz cos w kodzie zrobic to musisz to...zrobic...😉

Liczysz ze jak wcisniesz guzik to zmienna licznik w cudowny sposob zmieni swoj stan w czesci kodu ktory sie nie wykonuje...no nie da rady..😁 w tych for() licznik zachowuje sie jak stala...nie wazne ze "gdzies tam" prubujesz ja zmienic...nie uda Ci sie to bo obecnie jestes w.......for😉

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

Może napiszę jak to sobie wyobraziłem, bo domyślam się że pewnie nawaliłem bzdur w kodzie. Otóż wymyśliłem sobie, że wykorzystam instrukcje switch do przełączania się między czynnościami. Powołałem do tego zmienną licznik, która zwiększa swoją wartość o 1, dzięki czemu po każdym kliknięciu przeskakuje między instrukcjami. No i problem oczywiście powstaje, gdy zmienna = 2, a wykonuje się funkcja migania. I juz kolejna instrukcja z kolei nie chcę się wykonać bo wykonuje się w pętli ciągle miganie. Dlatego wymyśliłem dodatkowe warunki w tych pętlach break, że jesli zmienna licznik będzie miała wartość różną od 2 to ma opuścić pętle. Ale no nie działa. 

Link do komentarza
Share on other sites

  void migaj () {
		for (uint8_t i=0; i<255;i++){
		OCR1A = i;
		_delay_ms(10);
	if ( !(PINB & KEY)) {
	  return;
      }
	}
	for (uint8_t i=255; i>0;i--){
		OCR1A = i;
		_delay_ms(10);
	if ( !(PINB & KEY)) {
	  return;
      }
    }


	}

Moze sie nie pomylilem...😉

Ps..oczywiscie jak chcesz wyjsc z tej funkcji na twoje rzadanie i przejsc do kolejnego case to musisz inkrementowac ten licznik podczas wcisniecia w for

Edytowano przez farmaceuta
Link do komentarza
Share on other sites

(edytowany)

Ok, dziś na spokojnie usiadłem i skleiłem coś, co działa prawie tak jakbym chciał. Nie ma tu programowo wielozadaniowości, ale fizycznie mogę zmieniać prędkość silnika w trakcie obrotu servem itp. Wkleję kod, jak ja to sobie wymyśliłem.

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

#define SERVO_OFF (1<<PD7) // klawisz stop servo
#define SERVO_ON (1<<PB0) // klawisz start servo
#define PWM_SERVO (1<<PB1) // kanal pwm serva
#define PWM_MOTOR (1<<PB2) // kanal pwm do mostka H
#define WE_A (1<<PD5) // wejscie sterujace
#define WE_B (1<<PD6) // wejscie sterujace
#define DC_START PORTD |= WE_A; PORTD &=~WE_B // start silika
#define DC_STOP PORTD &=~WE_A; PORTD &=~WE_B // stop silnika
#define MOTOR_SLOW (1<<PB3) // niskie obroty
#define MOTOR_MEDIUM (1<<PB4) // srednie obroty
#define MOTOR_HIGH (1<<PB5) // maksymalne obroty
#define STOP (1<<PB7) // zatrzymanie pracy
void servo (); // deklaracja funkcji

uint8_t licznik; // zmienna pomocnicza do petli

int main() {

		DDRD |= WE_A|WE_B; // wyjscie wyjsc sterujacych
		DDRB |= PWM_SERVO|PWM_MOTOR; // wyjscie kanalow pwm

		PORTD |= SERVO_OFF; // podciagniecie klawisza do vcc
		PORTB |= SERVO_ON|MOTOR_SLOW|MOTOR_MEDIUM|MOTOR_HIGH|STOP; // podciagniecie klawiszy do vcc

	/*       INICJALIZACJA PWM */
	TCCR1A |= (1<<WGM10)|(1<<COM1B1)|(1<<COM1A1); // tryb 8 bit i kanaly
	TCCR1B |= (1<<WGM12)|(1<<CS12); // prescaler 256

	    while (1){

  if (!(PINB & MOTOR_SLOW)){
	  OCR1B = 85;
	  DC_START;
  }else if(!(PINB & MOTOR_MEDIUM)){
	  OCR1B = 180;
  }else if(!(PINB & MOTOR_HIGH)){
	  OCR1B = 255;
  }else if(!(PINB & STOP)) {
	  DC_STOP;

  }


  if (!(PINB & SERVO_ON)){ // jesli wcisniety klawisz wlacz servo
	   licznik=1;
	   while(licznik)servo();
  }


}
}
void servo () { // definicja funkcji serva

	for (uint8_t i=0;i<90;i++){
		if (!(PIND & SERVO_OFF)){  // jesli wcisniety klawisz zakoncz dzialanie funkcji
		licznik=0;
		return;
		}
			if (!(PINB & MOTOR_SLOW)){       // Zmiana prędkości motoru w trakcie obrotu serva
			  OCR1B = 85;
			  DC_START;
			}else if(!(PINB & MOTOR_MEDIUM)){
			  OCR1B = 180;
			}else if(!(PINB & MOTOR_HIGH)){
			  OCR1B = 255;
			}else if (!(PINB & STOP)){
			  licznik=0;
			  DC_STOP;
			  return;
			}
			  OCR1A = i;
	  _delay_ms(120);
	 }

	for (uint8_t i=90;i>0;i--)	{
		if (!(PIND & SERVO_OFF)){
		licznik=0;
		return;
		}
			if (!(PINB & MOTOR_SLOW)){
			  OCR1B = 85;
			  DC_START;
		    }else if(!(PINB & MOTOR_MEDIUM)){
			  OCR1B = 180;
		    }else if(!(PINB & MOTOR_HIGH)){
			  OCR1B = 255;
		    }else if (!(PINB & STOP)){
		    	licznik=0;
		    	DC_STOP;
		    	return;
		    }
	OCR1A = i;
	_delay_ms(120);
   	}


}

Jest tu dużo microswitchy, ale na razie nie chciałem się bawić w obsługę kilku instrukcji za pomocą jednego klawisza, ale będę starał się to poprawić. Jednak jest problem, za który nie bardzo wiem, jak się zabrać. Po wcisnieciu klawisza servo_on następuje obrót,raz w jedną raz w drugą. Gdy wciskamy servo_off to servo zatrzymuje się w danej pozycji i to jest OK, tak to ma wyglądać. Jednak gdy znowu wcisnę servo_on servo szybko się skręca do pozycji 0 i zaczyna się pętla od nowa. Nie jest to pożądany dla mnie efekt, ale rozumiem czemu tak się dzieje, bo pętla w funkcji liczy od 0 więc nic dziwnego, że się tak dzieje. Tylko teraz pytanie jak to zrobić, żeby po zatrzymaniu serva, pętla zaczeła liczyć od momentu zatrzymania? Tą wartość trzeba by zapamiętać i podstawić do pętli for. Nie bardzo wiem jak tu zakombinować.

Ps. Przepraszam użytkownika @_LM_ , że wczoraj zacząłem wysyłać jakieś swoje bzdurne kody i odszedłem od tematu, gdy on się napracował i próbował mi na swoich przykładach wytłumaczyć pewne rzeczy 😕 

Edytowano przez Krawi92
Link do komentarza
Share on other sites

Twoja strata. Tyle mogę powiedzieć że jak chcesz dobrze wykorzystać małe mikrokontrolery to od przerwań nie uciekniesz, a opracowanie programu wielozadaniowego, czy tam wielowątkowego zaczyna się od poznania timerów programowych bo niestety w AVR sprzętowych zbyt wielu niema, później dobrze jest ogarnąć wskaźniki na funkcje co nie jest zagadnieniem aż tak trudnym jak go się przedstawia. 

  • Lubię! 1
  • Pomogłeś! 1
Link do komentarza
Share on other sites

46 minut temu, Krawi92 napisał:

Tą wartość trzeba by zapamiętać i podstawić do pętli for. Nie bardzo wiem jak tu zakombinować.

Moze zmienna globalna?😉

48 minut temu, Krawi92 napisał:

Ps. Przepraszam użytkownika @_LM_ 

Za pozno...juz sie obrazil i mowil ze nigdy sie do Ciebie nie odezwie...😉(zarciki...😅)

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

3 minuty temu, Krawi92 napisał:

Tak, pomyślałem o dodatkowej zmiennej globalnej i potem jakoś w funkcji przypisać jej wartość do zmiennej iteracyjnej. 

Nic nie musisz przepisywac...robisz 2 zmienne dla dwoch petli i przypisujesz im odpowiednia wartosc na starcie czyli 0/90...po tych dwoch wykonanych petlach dodajesz jeden warunek ze jesli te zmienne sie "przekrecily" to ustaw startowe wartosci zeby cykl sie powtorzyl...dwie zmienne zapobiegna zlemu dzialaniu serwa w takiej postaci ze gdyby sie juz wykonywala druga petla for to po wyjsciu i ponownym wejsciu serwo bedzie kontynuowac ruch a nie zaczynac od nowa...

Link do komentarza
Share on other sites

10 minut temu, Krawi92 napisał:

Ok, wrócę do Twoich przykładów i postaram się to ogarnąć

To są tylko przykłady tak jak ja podszedłbym do problemu, nie mówię że najlepsze i jedynie słuszne 

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.