logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Atmega8][C] - porty IO - ustawianie

yaroray 23 Gru 2009 12:31 8326 12
REKLAMA
  • #1 7426365
    yaroray
    Poziom 10  
    Mam problem z portami Atmegi8. Mianowicie, gdy ustawiam na nich "1" to wartości napięć na różnych portach są losowe, na niektórych jest normalnie 5V, a na innych 4,3V, 1,3V, 0,4V albo inne. Za to jak wystawiam "0" to jest ładne 0V. Nie wiem w czym może tkwić problem. Kupiłem nową Atmegę, bo myślałem, że może padła, ale druga zachowuje się tak samo. Przez dłuższy czas dolutowywałem różne elementy do układu i wszystko działało dobrze i nagle padło. Teraz kiedy je z powrotem wylutowałem nie działa poprawnie.
  • REKLAMA
  • #2 7426421
    gonzalo
    Poziom 31  
    Jakie elementy dolutowywałeś? Bezpośrednio pod porty?
  • REKLAMA
  • #3 7426444
    Mari@@@n
    Poziom 19  
    Może masz port ustawiony jako wejście i tylko podciągasz do 5V. Musisz ustawić kierunek portu (wejście/wyjście) a potem ustawić wartość.
  • #4 7426605
    yaroray
    Poziom 10  
    Elementy to diody z rezystorami 200ohm (bezpośrednio pod porty), tranzystory (bazy przez rezystory 10kohm pod porty) i przyciski (podłączone do portów i masy). Kierunki portów mam ustawione w rejestrach DDR ("1" - wyjścia), po tym ustawiam porty na "1".
  • REKLAMA
  • Pomocny post
    #5 7427812
    Fredy
    Poziom 27  
    Nie masz podciągnięcia pod zasilanie. Podłącz na próbę rezystor 1k między wejście portu a zasilanie i wtedy sprawdz czy jest ok.

    Inna przyczyna to być może pomyliłeś rejestry PIN i PORT - częsty błąd.
  • #6 7427918
    yaroray
    Poziom 10  
    Zrobiłem jeden port (PC6) wejściem, mam tam podpięty cały czas rezystor 10k od zasilania. O to chodziło? Nadal tak samo. Poniżej załączyłem kod.

    #define F_CPU 16000000UL
    #include <avr/io.h>
    #include <util/delay.h>    
    
    
    
    int main(void) 
    {
    
    	DDRD|=_BV(5);
    	DDRD|=_BV(6);
    	DDRD|=_BV(7);
    	DDRB|=_BV(0);
    	DDRC|=_BV(0);
    
    	DDRC &=~_BV(6);
    
    	while(1)
    	{
    	PORTD = _BV(5);
    	PORTD = _BV(6);
    	PORTD = _BV(7);
    	PORTB = _BV(0);
    
    	PORTC &= ~_BV(0);
    	}
    }
  • Pomocny post
    #7 7429770
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #8 7430062
    BoskiDialer
    Poziom 34  
       while(1) 
       { 
       PORTD = _BV(5); 
       PORTD = _BV(6); 
       PORTD = _BV(7); 
       PORTB = _BV(0); 
    
       PORTC &= ~_BV(0); 
       }

    W ten sposób przez przypadek powstanie coś na wzór pwm na pinach. PortB będzie trzymał wartość, podobnie PortC, ale do PortD są 3 przypisania (nie ustawienia bitu), pierwsze przypisanie ustawi jedynkę na pinie 5 kasując inne, drugie ustawi na 6 kasując inne, trzecie na 7 kasując inne. Przy dobrej optymalizacji pętla będzie miała 8 cykli, wtedy na PD5 i PD6 pojawi się 0,62V, na PD7 pojawi się 3,75V średnie. Przy słabszej optymalizacji pętla będzie miała 12 cykli, na PD5 i PD6 będzie 0,83V, na PD7 3,33V średnio.
  • #9 7430236
    yaroray
    Poziom 10  
    emarcus napisał:

    W Atmega8 pin 1(PC6) normalnie jest RESET i dopoki nie zmienisz odpowiedniego fusebit (patrz str. 223; tabela 87 bit#7), ten pin nie spelnia roli GIO (PC6), wiec processr go nie "widzi". Nie doradzam jednak tej zmiany!


    W moim układzie (chcę zrobić zegar binarny) ten pin ma działać jako reset, więc tak jest podłączony. Ale czy podłączam reset do zasilania czy odłączam to nie widzę różnicy w działaniu układu. Rozumiem, że podanie "0" na reset, resetuje układ, tak? Więc w sumie po co tam jest potrzebna "1" cały czas skoro to i tak nie robi różnicy?

    emarcus napisał:

    Jezeli wczesniej podlaczales do masy porty skonfigurowane jako wyjscia (przez wlaczniki, chocby tylko na krotki czas) to jest teoretyczna szansa ze te porty moga byc uszkodzone. Jezeli na wyjsciu pojawil sie programowo stan wysoki i w tym czasie przycisk byl zwarty do masy to skutek jest oczywisty.

    e marcus


    Mam nadzieję, że tak się nie stało :P

    BoskiDialer napisał:

    W ten sposób przez przypadek powstanie coś na wzór pwm na pinach. PortB będzie trzymał wartość, podobnie PortC, ale do PortD są 3 przypisania (nie ustawienia bitu), pierwsze przypisanie ustawi jedynkę na pinie 5 kasując inne, drugie ustawi na 6 kasując inne, trzecie na 7 kasując inne. Przy dobrej optymalizacji pętla będzie miała 8 cykli, wtedy na PD5 i PD6 pojawi się 0,62V, na PD7 pojawi się 3,75V średnie. Przy słabszej optymalizacji pętla będzie miała 12 cykli, na PD5 i PD6 będzie 0,83V, na PD7 3,33V średnio.


    Dzięki za wyjaśnienie, właśnie w tym tkwił problem. Myślałem, że nie ma różnicy pomiędzy instrukcjami PORTB |= _BV(0); i PORTB = _BV(0);.
    Dopiero zaczynam zabawę z Atmegą i w ogóle z programowaniem mikrokontrolerów, a nie mogłem znaleźć żadnego dobrego tutoriala z ich programowania, tylko na różnych stronach jakieś drobiazgi.
    Czyli teraz rozumiem tak:
    PORTB |= _BV(0); //przypisanie tylko na PB0 "1"
    PORTB &= ~_BV(0); //przypisanie tylko na PB0 "0"
    PORTB = _BV(0); //przypisanie na PB0 "1", na resztę PORTB "0"
    PORTB = ~_BV(0); //przypisanie na PB0 "0", na resztę PORTB "1"
    Możecie potwierdzić?

    Jeszcze jedno pytanie, czy oprócz resetu i wejścia na kwarc, mogę korzystać ze wszystkich innych portów I/O bez ustawiania żadnych fuse bitów i nie będzie dziwnych wartości?
  • Pomocny post
    #10 7430323
    BoskiDialer
    Poziom 34  
    yaroray napisał:
    PORTB |= _BV(0); //przypisanie tylko na PB0 "1"
    PORTB &= ~_BV(0); //przypisanie tylko na PB0 "0"
    PORTB = _BV(0); //przypisanie na PB0 "1", na resztę PORTB "0"
    PORTB = ~_BV(0); //przypisanie na PB0 "0", na resztę PORTB "1"

    Tak właśnie jest. Aby zrozumieć działania na bitach można sobie to rozpisać w ten sposób:
    PORTB |= _BV(0); // na:
    PORTB = PORTB | _BV(0);
    
    PORTB &= ~_BV(0); // na:
    PORTB = PORTB & ~_BV(0)
    
    PORTB = _BV(0); // do celów porównawczych
    PORTB = ~_BV(0);

    Ustawianie "|=" można zapisać jako przypisanie aktualnego stanu, suma bitowa pewna wartość. Pojawienie się aktualnego stanu w zapisie oznacza, że w jakimś stopniu będzie on zachowany w tych miejscach, gdzie suma bitowa nie zmienia wartości - tylko bit o masce _BV(0) zostanie ustawiony. Podobnie jest z drugim, "&" nie kasuje bitów, dla których w masce ~_BV(0) pojawiają się jedynki (czyli wszędzie oprócz bitu 0). Przypisanie samej wartości ignoruje poprzedni stan innych pinów, co oznacza że wszystkie piny zostaną zmienione - albo na 1 albo na 0.

    Bez zmieniania fusebitów wejście Reset będzie służyć do - co oczywiste - resetowania procesora, ten pin nie będzie dawał się zmieniać programowo. Zewnętrzny pull-up zmniejsza wrażliwość na zakłócenia.
    Jednak w domyślnych ustawieniach fusebitów procesor pracuje na wewnętrznym zegarze RC, a więc piny PB6/7 (xtal1/2) będą pracować jak normalne piny IO. Jeśli procesor ma być taktowany z kwarcu 16MHz, wymagana jest ingerencja w fusebity aby zmienić źródło zegara.
  • REKLAMA
  • #11 7430342
    yaroray
    Poziom 10  
    BoskiDialer napisał:
    yaroray napisał:
    PORTB |= _BV(0); //przypisanie tylko na PB0 "1"
    PORTB &= ~_BV(0); //przypisanie tylko na PB0 "0"
    PORTB = _BV(0); //przypisanie na PB0 "1", na resztę PORTB "0"
    PORTB = ~_BV(0); //przypisanie na PB0 "0", na resztę PORTB "1"

    Tak właśnie jest. Aby zrozumieć działania na bitach można sobie to rozpisać w ten sposób:
    PORTB |= _BV(0); // na:
    PORTB = PORTB | _BV(0);
    
    PORTB &= ~_BV(0); // na:
    PORTB = PORTB & ~_BV(0)
    
    PORTB = _BV(0); // do celów porównawczych
    PORTB = ~_BV(0);

    Ustawianie "|=" można zapisać jako przypisanie aktualnego stanu, suma bitowa pewna wartość. Pojawienie się aktualnego stanu w zapisie oznacza, że w jakimś stopniu będzie on zachowany w tych miejscach, gdzie suma bitowa nie zmienia wartości - tylko bit o masce _BV(0) zostanie ustawiony. Podobnie jest z drugim, "&" nie kasuje bitów, dla których w masce ~_BV(0) pojawiają się jedynki (czyli wszędzie oprócz bitu 0). Przypisanie samej wartości ignoruje poprzedni stan innych pinów, co oznacza że wszystkie piny zostaną zmienione - albo na 1 albo na 0.

    Bez zmieniania fusebitów wejście Reset będzie służyć do - co oczywiste - resetowania procesora, ten pin nie będzie dawał się zmieniać programowo. Zewnętrzny pull-up zmniejsza wrażliwość na zakłócenia.
    Jednak w domyślnych ustawieniach fusebitów procesor pracuje na wewnętrznym zegarze RC, a więc piny PB6/7 (xtal1/2) będą pracować jak normalne piny IO. Jeśli procesor ma być taktowany z kwarcu 16MHz, wymagana jest ingerencja w fusebity aby zmienić źródło zegara.


    Mam podłączony kwarc do Atmegi i do tego co przestawić w fuse bitach już doszedłem, więc ładnie działa. Super i wszystko jasne, dzięki wielkie jeszcze raz.
  • #12 7430428
    BoskiDialer
    Poziom 34  
    webmortiz napisał:
    PC6 - reset, PB6 PB7 - kwarc, PB3 PB4 PB5 - miso/mosi/sck - zlaczka programatora te sa z gory zarezerwowane na ich funkcjonalnosc, chociaz nie wiem czy jak ustawi sie wewnetrzny kwarc czy PB6 i PB7 bedzie mozna traktowac jako zwykle IO. PC6, PB3, PB4 i PB5 jesli nie znasz sie za dobrze na avrach bym nie ruszal
    webmortiz: Owszem, piny PB3-5 służą do programowania w systemie, ale aby te piny mogły być przejęte przez ISP, koniecznym jest aby na pinie reset pojawił się stan niski, co natychmiastowo eliminuje ten problem - w taki przypadku program się nie wykonuje więc i tak nie było by możliwości sterowania nimi. Przy normalnym działaniu piny te są zwykłymi pinami IO.

    Inaczej wygląda to w przypadku JTAG, gdyż tam istnieje możliwość skanowania wejść i wyjść w trakcie działania procesora przez co piny te muszą być odseparowane. W takim przypadku trzeba wyłączyć JTAG za pomocą fusebitów. Jakkolwiek, atmega8 nie ma JTAG'a, więc ten problem tutaj nie występuje.

    -- edit: widzę, że wiadomość poprzednika została usunięta zanim wysłałem post, jakkolwiek mój post zostawiam.
  • #13 8239224
    yaroray
    Poziom 10  
    Więc wszystko jasne. Odpowiednie pisanie komend, to:
    PORTB |= _BV(0); //przypisanie tylko na PB0 "1"
    PORTB &= ~_BV(0); //przypisanie tylko na PB0 "0"
    PORTB = _BV(0); //przypisanie na PB0 "1", na resztę PORTB "0"
    PORTB = ~_BV(0); //przypisanie na PB0 "0", na resztę PORTB "1"
REKLAMA