Skocz do zawartości

Miganie diodami za pomoca UART


Pomocna odpowiedź

Napisano

Hej, bawię się teraz odbiorem danych, wrzuciłem funkcje odbierania pojedynczego znaku i za pomocą prostych instrukcji np: steruje stanem na pinach. Pomyślałem, że jak wcisne 1 to mam zgasić diode(bo domyslnie po wystartowaniu świeci) a jak wcisnę 2 to ma migać za pomocą operacji XOR. Problem teraz jest taki, że gdy właśnie ona miga cały czas, to program juz nie reaguje na inne dane. Widać, że konwenter pracuje, dane dopływają, jednak instrukcje się nie wykonują. Próbowałem coś zrobić za pomocą polecenia break; ale lipa. Juz probowalem kilka wariantów, ale ciągle utykam w pętli. Ktoś poradzi co robię źle ? Dodam, że działanie tego programu po prostu sobie sam wymyśliłem,ale nie sadziłem, że stworzy to taki problem dla mnie 😄 

 

#include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>
#include<avr/interrupt.h>
#include<avr/pgmspace.h>
#include "UART/uart.h"

typedef uint16_t u16; // Zmiana nazwy typu zmiennych
typedef uint8_t u8;

char dane; // Zmienna przechowywujaca dane odbioru

int main (){

	DDRB |= (1<<PB6);	// PB6 jako wyjscie
	PORTB |= (1<<PB6); // Stan wysoki na PB6
  
 //               inicjalizacja USART           //
	USART_Start(UBRR_Value); //wartosc UBRR
  while(1) {
	
	dane = USART_Receive(); // Dane odbioru do "dane"

	if (dane == '1') { // Jesli znak to 1
		PORTB &=~(1<<PB6);  // Zgas diode

		}else if (dane == '2') { // Jesli znak to 2
			while(dane == '2') { // wykonuj petle dopoki znak to 2
				PORTB ^= (1<<PB6); // migaj dioda co 250ms
				_delay_ms(250);
				if (!(dane == '2')) break; // Jesli znak bedzie inny opusc petle
	    }
		}


}
}

 

(edytowany)

Masz coś takiego: while (dane == '2').

Czy jest jakaś szansa na to, aby zmienna "dane" zmieniła wartość wewnątrz tej pętli? Jeśli uważasz że tak, to napisz w jaki sposób.

Edytowano przez ethanak

No trochę zastanawiało mnie to, ale tłumaczyłem sobie to tym, że zmienna zmieni wartość jak do terminala wprowadzę inny znak niż 2. Przecież zmienna dane to:

 dane = USART_Receive();

Wyobraź sobie taką sytuację.

Jesteś operatorem wyłącznika. Podchodzisz do szefa, szef ci daje karteczkę. Na karteczce jest napisane "włącz". Podchodzisz do wyłącznika i właczasz, a potem znowu idziesz do szefa po kartkę.

Teraz dostałeś kartkę "migaj". Podchodzisz do wyłącznika, przełączasz, czekasz chwilę, sprawdzasz jaką masz kartkę. Oczywiście "migaj". Przełączasz, odczekujesz, sprawdzasz... no dalej masz "migaj", bo przecież cały czas masz tę samą kartkę... i tak w kółko.

A szef sam nie przyjdzie żeby dać ci w łeb i zabrać kartkę...

Rozumiesz?

Fajnie że masz linijkę typu "dane = cośtam", ale przecież ta linijka sama z siebie się nie wykona. Tak samo jak kartka sama się magicznie nie zmieni na inną.

Hmmm jak to teraz rozwiązać ? Przerwaniem sprzętowym od odebrania danych ? Szczerze mówiąc nie mam pomysłu jak z czegoś takiego wybrnąć, pozornie prosta sprawa 😕 

Wyobraź sobie dalej operatora wyłącznika.

Dostał kartkę "migaj". Poszedł, przełaczył, odczekał i wraca do szefa.

- Masz pan coś dla mnie?

- Nie.

- To idę jeszcze raz mignę.

W którymś momencie szef powie "tak" - i wtedy wykonuje następne polecenie.

Może być?

Bo przerwanie to takie wymaganie od szefa, żeby podlazł i kartkę podmienił...

Zastanów się przede wszystkim, czy pętla while jest tam w ogóle potrzebna.

 

Zapętliłem, bo chciałem uzyskać efekt migania, dopóki nie zmieni się znak odbioru, dlatego wykorzystałem pętle. Nie przychodzi mi na razie inny pomysł do głowy jak wykonywać jakieś polecenie bez przerwy dopóki nie zmieni sie znak

Ale przecież masz jedną pętlę while(1) - po co ta druga?

Porównaj dwa moje posty o operatorze wyłącznika - czy w drugim jest jakaś wewnętrzna pętla do machania wyłącznikiem?

Poza tym - nie obraź się, ale robisz podstawowy błąd: chcesz programować "na rejestrach", ale nie masz pojęcia o programowaniu. Moja rada: wróć do Arduino IDE, na tym się naucz, a potem - jeśli będziesz chciał - będziesz mógł zostać specjalistą od jednego przestarzałego mikrokontrolera. 

Bo na razie chcesz ustawić zawory w Syrence nie mając prawa jazdy i nie wiedząc jak się skręca na skrzyżowaniu. I nawet nie wiedząc, że dwusuw nie ma zaworów 😉

No dobrze, na spokojnie przemyśle te posty i zostawię na razie ten temat i wrócę do nauki C. Nie skorzystam z Twojej rady o powrocie do arduino, tak łatwo się nie poddaje 😛 

  • Lubię! 1
(edytowany)

To nie jest żadne poddawanie się. Nie zostaniesz kierowcą F1 mając kartę rowerową - trzeba przejść przez kilka etapów.

Może myślisz, że Arduino IDE to dla cieniasów jest, a prawdziwi twardziele piszą hexy z palca? Mam jakieś 40 lat doświadczenia w programowaniu, od zupełnego cieniasa do profesjonalisty, a jakoś Arduino IDE używam z powodzeniem (chociaż przyznam, że nie jest to co najbardziej lubię).

Przemyśl to sobie.

Aha, etap pisania hexów z palca mam już za sobą (Spectrum i inne takie na Z80 czy 6502). Tyle że wtedy nie było innej możliwości...

Edytowano przez ethanak
  • Lubię! 2
(edytowany)

 

1 godzinę temu, Krawi92 napisał:

Hmmm jak to teraz rozwiązać ? Przerwaniem sprzętowym od odebrania danych ?

Tak można, moduł USART generuje odpowiednie przerwanie, ale póki co, zastanów się jak można rozwiązać problem inaczej, tak jak sugerował @ethanak ten drugi while nie jest potrzebny. Zapoznaj się z jego artykułem nt maszyny stanów, możesz też spróbować jakoś schematycznie rozrysować przepływ programu.

Poza tym rozpisanie warunków: w tym wypadku zamiast

if (!(dane == '2')) break; // Jesli znak bedzie inny opusc petle

lepiej wygląda

if (dane != '2') break; // Jesli znak bedzie inny opusc petle

 

Edytowano przez _LM_
  • Lubię! 1
4 godziny temu, Krawi92 napisał:

Przecież zmienna dane to:

 dane = USART_Receive();

Tak..ale zeby zmienic zawartosc tej zmiennej musisz wykonac ta linijke...w przeciwnym razie juz na zawsze utkwisz w while bo nie masz wewnatrz tej petli modyfikacji tej zmiennej, czyli dane zawsze bedzie sie rownac juz '2'...inaczej by sprawa wygladala gdyby modyfikowanie tej zmiennej zachodzilo w przerwaniu...

 

4 godziny temu, Krawi92 napisał:

Nie przychodzi mi na razie inny pomysł do głowy jak wykonywać jakieś polecenie bez przerwy dopóki nie zmieni sie znak

Maszyna stanow lub jeden warunek if wiecej...czyli wywalasz while...w drugim if sprawdzasz czy dane=='2'...jesli tak to ustawiasz jakas "flage" na true...i robisz trzeci if z warunkiem (flaga == true) i w nim umieszczasz swoje miganie...oczywiscie musisz ustawic ta flage na false jesli inny znak przylazl...(to tak tylko dla przykladu)

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