Skocz do zawartości

[C] Ustawienie portów, If-else i dość dziwna sprawa ;)


MasterFun

Pomocna odpowiedź

Witam!

Mam następujący problem o ile można to nazwać problemem. Ostatnio zająłem się diodowym kursem dotyczącym C, i mam kilka pytań gdyż nie bardzo rozumiem pewnych zagadnień. (uC oczywiście atmega8 kompilator winavr i avr dude do wrzucania)

Pierwsza rzecz to, wyobraźmy sobie sytuację: ustawiamy PORTC jako wejście czyli DDRC = 0x00; (do portu C będą podłączone przyciski - mikroswitche)

No i później należałoby ustawić stan poszczególnych bitów na porcie C, o ile dobrze rozumiem można ustawić PORTC = 0x00 i wtedy switch trzeba podłączyć do nóżki uC i do VCC lub ustawić PORTC = 0xff i należy podłączyć switch do nóżki uC i do GND, dobrze rozumiem?

Kolejna sprawa to funkcja if-else. W kursie wykonywanie warunku było pokazane w następujący sposób:

If(PINC & 0x01)

Powiedziane również było że funkcja & służy do „przysłonięcia pozostałych bitów” No ale w jaki sposób? Próbowałem sam do tego dojść podstawiając za 0x01 różne wartości i operując na poszczególnych bitach portu. Próbując różnych konfiguracji (tak jak opisałem to w problemie z portem C) raz działało dobrze a raz sprzecznie w odniesieniu do pierwszej próby… Jeśli mógłby ktoś mi to na bitach wytłumaczyć z różnymi przykładami tak aby 1 była w kilku miejscach.

Aha i ostatnia rzecz wydaje mi się dość dziwna, otóż pisząc program z funkcją if-else który działał w sposób następujący: jeśli switch nie wciśnięty diody świecą się w konfiguracji 01010101 a jeśli wciśnięty 10111101 niby proste, ale odłączając kabelek od portu gdzie miał być podłączony switch zmieniał się stan (?) Później ponownie chcąc dotknąć kabelkiem do portu ze switchem stan też się zmieniał, najlepsze jest to że druga strona kabelka wisiała w powietrzu .

Pozdrawiam i dziękuję za odpowiedź, jednocześnie przepraszam jeśli temat był poruszany na forum jednak nie znalazłem…

Link do komentarza
Share on other sites

1.Jak pin jest jako wejscie (odpowiedni bit DDRx ustawione na 0) to wtedy wartość analogicznego bitu PORTC oznacza czy podłączysz wewnętrzny pullup (jest to rezystor ok. 50k do VCC).

Czyli bez tego rezystora musiałbyć na zewnątrz procesora dać rezystor do VCC i do tego mikroswitch do GND, albo rezystor do GND i mikroswitch do VCC.

Korzystając z wewnętrznego pullupa (czyli odpowiedni bit PORTC na "1") nie musisz stosować rezystora do VCC, a tylko podłączasz microswitch do GND - mniej komponentów.

2.& to operacja AND. Jest to operacja, która ma taką tablicę stanów:

A,B,wynik

0,0,0

0,1,0

1,0,0

1,1,1

Czyli 1 będzie tylko wtedy, gdy odpowiedni bit w PINC będzie 1 i bit do którego porównujesz będzie 1.

Dla przypadku PINC&0x01 sprawdzasz pierwsze wejście portc i tylko jak na pinie PC0 jest "1" to warunek zwróci prawdę - wykona się część programu w warunku if.

Trudniejszy przykład: Powiedzmy, że chcemy coś wykonać gdy na wejściu PA2 i PA4 jest stan 1.

PA2 i PA4 to odpowiednio bit 3 i 5, binarnie możesz to zapisać jako 00010100b (z lewej najwyższy bit), w hexie jest to 0x14 (sprawdz kalkulatorem w windowsie - ustawienie programisty)

Czyli warunek to: if ((PINA & 0x14) == 0x14) ...

3.Z wejściami mikrokontrolera jest tak, że mogą wejść w tzw. stan nieustalony. Zazwyczaj masz napisane, że np do 0,3VCC jest stan niski "0", a od 0,7VCC jest stan wysoki "1". Pomiędzy tym jest stan nieokreślony.

Jak pinu nie podepniesz ani pod VCC, ani pod GND to on sobie swobodnie lata i robi różne dziwne rzeczy. JEST TO BARDZO ZŁA PRAKTYKA! Może to prowadzić do nadmiernego poboru prądu czy nawet zawieszania się procesora.

Jak piny są nieużywane należy albo je podpiąć zewnętrznym rezystorem pod GND, albo użyć wewnętrznego pullupa i podpiąć pod VCC.

PS. W zapisie liczb zazwyczaj jest tak:

123 - system dziesiętny

00110010b - bin (binarny)

0xFF - hex (szesnastkowo)

Link do komentarza
Share on other sites

1.Jak pin jest jako wejscie (odpowiedni bit DDRx ustawione na 0) to wtedy wartość analogicznego bitu PORTC oznacza czy podłączysz wewnętrzny pullup (jest to rezystor ok. 50k do VCC).

Czyli bez tego rezystora musiałbyć na zewnątrz procesora dać rezystor do VCC i do tego mikroswitch do GND, albo rezystor do GND i mikroswitch do VCC.

Korzystając z wewnętrznego pullupa (czyli odpowiedni bit PORTC na "1") nie musisz stosować rezystora do VCC, a tylko podłączasz microswitch do GND - mniej komponentów.

Hmmm... bardzo ciekawe, otóż w żadnym kursie się z tym nie spotkałem i już chyba jasne jest dlaczego za każdym razem było połączenie do GND (wydawało mi się to dziwne bo gdyby było do VCC to program zawierałby mniej komplikacji a tak trzeba było używać negacji itd. )

2.& to operacja AND. Jest to operacja, która ma taką tablicę stanów:

A,B,wynik

0,0,0

0,1,0

1,0,0

1,1,1

Czyli 1 będzie tylko wtedy, gdy odpowiedni bit w PINC będzie 1 i bit do którego porównujesz będzie 1.

Dla przypadku PINC&0x01 sprawdzasz pierwsze wejście portc i tylko jak na pinie PC0 jest "1" to warunek zwróci prawdę - wykona się część programu w warunku if.

Trudniejszy przykład: Powiedzmy, że chcemy coś wykonać gdy na wejściu PA2 i PA4 jest stan 1.

PA2 i PA4 to odpowiednio bit 3 i 5, binarnie możesz to zapisać jako 00010100b (z lewej najwyższy bit), w hexie jest to 0x14 (sprawdz kalkulatorem w windowsie - ustawienie programisty)

Czyli warunek to: if (PINA & 0x14) ...

Chciałbym się odnieść do trudniejszego przykładu, załóżmy że:

PA2 ma stan 0

PA4 ma stan 1

i porównuje to do 00010100b (0x14)

Czy oba bity do których porównuje muszą być w stanie 1 żeby dla całego warunku była wartość logiczna PRAWDA, nie do końca wiem jak to analizować, poszczególne bity do których porównuje czy cały stan portu po operacji &?

3.Z wejściami mikrokontrolera jest tak, że mogą wejść w tzw. stan nieustalony. Zazwyczaj masz napisane, że np do 0,3VCC jest stan niski "0", a od 0,7VCC jest stan wysoki "1". Pomiędzy tym jest stan nieokreślony.

Jak pinu nie podepniesz ani pod VCC, ani pod GND to on sobie swobodnie lata i robi różne dziwne rzeczy. JEST TO BARDZO ZŁA PRAKTYKA! Może to prowadzić do nadmiernego poboru prądu czy nawet zawieszania się procesora.

Jak piny są nieużywane należy albo je podpiąć zewnętrznym rezystorem pod GND, albo użyć wewnętrznego pullupa i podpiąć pod VCC.

Rozumiem że rezystor jak w przypadku wyżej ma wartość ok 50k?

Link do komentarza
Share on other sites

2.& to operacja AND. Jest to operacja, która ma taką tablicę stanów:

A,B,wynik

0,0,0

0,1,0

1,0,0

1,1,1

Czyli 1 będzie tylko wtedy, gdy odpowiedni bit w PINC będzie 1 i bit do którego porównujesz będzie 1.

Dla przypadku PINC&0x01 sprawdzasz pierwsze wejście portc i tylko jak na pinie PC0 jest "1" to warunek zwróci prawdę - wykona się część programu w warunku if.

Trudniejszy przykład: Powiedzmy, że chcemy coś wykonać gdy na wejściu PA2 i PA4 jest stan 1.

PA2 i PA4 to odpowiednio bit 3 i 5, binarnie możesz to zapisać jako 00010100b (z lewej najwyższy bit), w hexie jest to 0x14 (sprawdz kalkulatorem w windowsie - ustawienie programisty)

Czyli warunek to: if (PINA & 0x14) ...

Chciałbym się odnieść do trudniejszego przykładu, załóżmy że:

PA2 ma stan 0

PA4 ma stan 1

i porównuje to do 00010100b (0x14)

Czy oba bity do których porównuje muszą być w stanie 1 żeby dla całego warunku była wartość logiczna PRAWDA, nie do końca wiem jak to analizować, poszczególne bity do których porównuje czy cały stan portu po operacji &?

Mój błąd, poprawiłem w poście powyżej. Każda wartość >0 zostanie przez if przyjęta jako prawda.

AND zwróci wartość 0x10 i w tym momencie zwykły if (PINC&0x14) zwróciłby prawdę. Poprawny kod to if ((PINC&0x14)==0x14)

Zewnętrzny rezystor podciągający może mieć dowolną rozsądną wartość. Może to być 100k, 10k, 1k. Nie ma to większego znaczenia jak chcesz tylko ustalić stan wejściowy pina.

  • Lubię! 1
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

O taką odpowiedź mi chodziło 😉 Dzięki i oczywiście "pomógł"

edit:\\ jeszcze takie pytanko wykonując negacje tak jak w przykładzie:

PORTA = 0x03

if(!(PINA & 0x07))

otrzymam negacje tych bitów które porównuje do 0x07 czyli: 0000 0100b czy może cały port i będzie to wyglądać tak: 1111 1100b (inaczej mówiąc brane są pod uwagę tylko te bity gdzie w "masce" (0x07) mam wartość 1 czy może neguje cały wynik po operacji &? )

a i jeszcze jedno, tak dla pewności, zakładając że mam:

DDRA = 0x00; //port a jest wejsciem

PORTA = 0xff; // stan bitów na P. A to 1111 1111

(do portu A na linii 3 mam połączony mikro switch) po naciśnięciu go otrzymam: 1111 1011b, zgadza się?

Link do komentarza
Share on other sites

Ad1. Zgodnie z nawiasami skoro najpierw masz (PINA & 0x07) a dopiero przed tym ! to najpierw zrobi AND, a potem wynik zmieni na przeciwny (prawda na fałsz i odwrotnie, gdzie prawda to wszystko różne od 0).

Natomiast negacja bitów to inny symbol "~". Różnica taka, że np !0xF0 da 0x00, a ~0xF0 da 0x0F.

Przejrzyj stronę http://pl.wikibooks.org/wiki/C/Operatory

Ad2. Tak

Link do komentarza
Share on other sites

Ok, przejrzałem dalszą część kursu i była wytłumaczona różnica między negacją na bitach a logiczną 😉 Twój link też się przydał...

Generalnie zaczynam rozumieć istotę funkcji if z kilkoma różnymi bitami, po próbie zrozumienia przystąpiłem do testów, rozpisałem sobie bity na kartce i było tak jak się spodziewałem... 😉

No i miałem okazję sprawdzić to o co pytałem tzn:

[...]

Czy oba bity do których porównuje muszą być w stanie 1 żeby dla całego warunku była wartość logiczna PRAWDA, nie do końca wiem jak to analizować, poszczególne bity do których porównuje czy cały stan portu po operacji &?

Niestety jednak nie wszyło tak jak mówiłeś:

Każda wartość >0 zostanie przez if przyjęta jako prawda.

AND zwróci wartość 0x10 i w tym momencie zwykły if (PINC&0x14) zwróciłby prawdę.

Jeśli porównuję do dwóch różnych bitów to te dwa bity muszą zwrócić prawdę żeby wykonała się dalsza część programu po if.

Pozdrawiam

Link do komentarza
Share on other sites

#define F_CPU 1000000L
#include <avr/io.h>

int main(void)
{

DDRB = 0xff;
PORTB = 0x00;

DDRC = 0x00;
PORTC= 0x07;




for(;;)
{

if(!(PINC & 0x05))
	{
	PORTB=0xaa;
	}
else
{
PORTB=0x00;
}
}

}

PORT C0 i C2 to mikro switche

PORT B0...B7 to Ledy

Działa to w ten sposób że jeśli nacisnę 1 przycisk nic się nie dzieje, jeśli 2 to diody świecą tak jak było powiedziane w programie po if czyli AA hex

Link do komentarza
Share on other sites

Masz negację w złym miejscu. Powinno być:

if(~(PINC) & 0x05) 

Pamiętaj, że stanem aktywnym switcha u Ciebie jest 0. Kiedy miałeś wciśnięty tylko jeden przycisk iloczyn PINC & 0x05 był 0x01 lub 0x04, czyli różny od 0, zatem po negacji warunek nie jest spełniony.

Nie wiem czy jasno wytłumaczyłem, ale zaraz spać idę, więc... 😋

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

Twój kod (dla uproszczenia tylko cztery bity):

Jeden przycisk wciśnięty
PINC x0x1
&    0101
  !(0001)=0

Dwa przyciski:
PINC x0x0
&    0101
  !(0000)=1

U mnie, jeden przycisk:
~PINC x1x0
&     0101
     0100 (różne od 0, zatem warunek if'a spełniony)
Dwa przyciski:
~PINC x1x1
&     0101
     0101

Proponuję, żebyś się zapoznał z działaniami na bitach np na tej stronie:link

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