Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[ATMega8][C]Błędne działanie programu po resecie uC

felekfala 19 Nov 2010 18:52 2681 23
Tespol
  • #1
    felekfala
    Level 19  
    Witam,
    problem jest następujący:
    Programuje atmege przez isp wszystko działa, niestety po odłączeniu zasilania i po ponownym jego włączeniu program wykonuje się tylko częściowo np nie działa odczyt temperatury, lub nie wyświetla się część napisów na alfanumerycznym lcd.
    Korzystam z atmegi 8 środowisko programujące Winavr 2008.
    Próbowałem na 3 atmegach8.
    Proszę o pomoc.
  • Tespol
  • #2
    MirekCz
    Level 35  
    Schemat? Kod?
    Prawdopodobnie masz gdzieś zakłócenia, albo błąd w kodzie (np. nie czekasz chwilę na ustabilizowanie napięcia i inicjalizujesz komponenty, które jeszcze nie mają poprawnego napięcia co powoduje, że nie działają poprawnie).
  • #3
    felekfala
    Level 19  
    Precyzuje problem:
    Otóż chodzi o to, że ustawiam przerwanie od zbocza opadającego na końcówce INT1, przerwanie wywoływane jest przyciskiem. W tym przerwaniu chciałem mierzyć temperaturę, a sprawdzałem nawet wyświetlenie napisu jednak zawsze jest to samo układ działa ale po wyłączeniu i ponownym włączeniu zasilania całość chodzi ale po przyciśnięciu przycisku na końcówce INT1 układ nie reaguje albo nawet się resetuje.

    inicjalizacja przerwania

    Code:
    void ster_init (void) 
    
    {

       // Piny podłaczone do przycisków ustawione jako wejścia
       // z R wew. podciągającym
       // Funkcją przycisków
       // jest wybór czasu załączenie triaka z tablicy
       PORT(STER_PORT) |= _BV(STER_P) | _BV(STER_M) | _BV(STER_OK);
       DDR(STER_PORT) &= ~(_BV(STER_P) | _BV(STER_M) | _BV(STER_OK));
       

       // Ustawienie wyjścia OC1A (sterowanie triakiem)
       // jako wyjście. Stan początkowy '1' (triak wyłaczony)
       // Właczanie triaka odbywa sie przez gdy OC1A jest w stanie '0;
       PORT(STER_TRIAC_PORT) |= _BV(STER_TRIAC);
       DDR(STER_TRIAC_PORT) |= _BV(STER_TRIAC);
       
       // INTO podłączone do układu detkecji przejścia napiecia przez zero
       
       
       // INT0 w trybie wejściowym podciągnięte
       // rezystorem wew. do Vcc
       PORT(STER_DET_0_PORT) |= _BV(STER_DET_0);
       DDR(STER_DET_0_PORT) &= ~_BV(STER_DET_0);
       
       // Przerwanie od koncówki INT0
       // aktywowane zboczem narastającym
       // Od koncówki INT1 zboczem opadającym
       MCUCR |= _BV(ISC01)|_BV(ISC00)|_BV(ISC11);
       
       // Ukatywnienie przerwania od INT0 i INT1
       GICR |= _BV(INT0)|_BV(INT1);
       
       
       // Wybranie trybu pracy licnzika
       //CTC z zerowaniem od wartość wpisanej
       // do ICR1
       TCCR1B |= _BV(WGM13) | _BV(WGM12) ;
       
     
        // Sprawdzam znacznik żadania przerwania
       //od przechwycenia jesli ustawiony zeruje go.
       //Ta sekwencja jest konieczna ponieważ przy
       //włączeniu przerwań od przechwycenia TIMSK |= _BV(ICF1);
       //uC wchodził odrazu w przerwanie od przechwycenia
       //Baranowski str 95
       if ( TIFR & _BV(ICF1))
       {
          // Jeśli znacznik żadania przerwania
          // ustawiony nastepuje załadowanie go
          // wysoka wartością logiczną co spowoduje
          // anulowanie wcześniejszych rządań
          TIFR |= _BV(ICF1);
       }
       
       // Uaktywnienie przerwania od przechwycenia (w tym wypadku
       TIMSK |= _BV(TICIE1);
       
       sei();
       
    }


    Code:
    fragment main i funkcji przerwania
    

    int main(void)
    {
       

       g_ster_n =0;
       g_ster_ocr = pgm_read_word(&tablica[g_ster_n]);
       g_ster_icr = pgm_read_word(&tablica[g_ster_n]) + 10;
       
       
          ster_init();
       
       //_delay_ms(1000);
       lcd_init();   // inicjalizacja wyświetlacza
       //_delay_ms(1000);
       wys_lcd();      // wyświetl rządaną sekwencje
       //_delay_ms(1000);
       
       lcd_int(g_ster_n); // wyświetl zmienną opóżnienia
       //_delay_ms(1000);
       
       ds18b20_init(); // ustawienie DS18B20 w rozdzielczośći 0.25
       _delay_ms(1000);

       while(1)
       {
          
          
          if(!(PIN(STER_PORT)&_BV(STER_P) ))
          {
             g_ster_n=(g_ster_n+1) % 100;
             cli();
             g_ster_icr = pgm_read_word(&tablica[g_ster_n]) + 10;
             g_ster_ocr = pgm_read_word(&tablica[g_ster_n]);
             sei();
             lcd_clr();   
             lcd_int(g_ster_n);
             _delay_ms(100);
             LCD_GOTOXY(LCD_LINE1+5);
             while(!(PIN(STER_PORT)&_BV(STER_P) )) {}
             ds18b20_write_lcd_temp();
             //lcd_puts("plus");
             
          }
          
          if(!(PIN(STER_PORT)&_BV(STER_M) ))
          {   
             
             g_ster_n=(g_ster_n+99)% 100;
             cli();
             g_ster_ocr= pgm_read_word(&tablica[g_ster_n]);
             g_ster_icr = pgm_read_word(&tablica[g_ster_n])+10;
             sei();
             lcd_clr();   
             lcd_int(g_ster_n);
             _delay_ms(100);
             while(!(PIN(STER_PORT)&_BV(STER_M) )) {}
             lcd_puts("minus");
             
             
          }
       

          
          
       }
       return 0;
    }

    void wys_lcd(void)
    {
     LCD_GOTOXY(LCD_LINE1+3);   
       lcd_nputs("regulator",-1);
       LCD_GOTOXY(LCD_LINE2+0);   
       lcd_nputs("ci",-1);
       lcd_putc(0x03);
       lcd_nputs("nienia V.1.0",-1);
       _delay_ms(2000);
       lcd_clr();
       LCD_GOTOXY(LCD_LINE1+1);
       lcd_nputs("Wersja pr",-1);
       lcd_putc(0x07);
       lcd_nputs("bna",-1);
       _delay_ms(2000);
       lcd_clr();   
    }

    ISR(INT1_vect)//,ISR_NOBLOCK)
    {
    //sei();

       while(!PIN(STER_PORT)&_BV(STER_OK))
       {}
       
       
       lcd_clrline(LCD_LINE2);
       LCD_GOTOXY(LCD_LINE2);
       //ds18b20_write_lcd_temp();
       lcd_puts("przerwanie");
             
             
    }
  • #4
    hotdog
    Level 26  
    Jak programujesz to zasilasz urządzenie z programatora? Jeżeli tak to masz prawdopodobnie problem z zasilaniem.
  • Tespol
  • #5
    mirekk36
    Level 42  
    Twój program jest niestety totalnie źle napisany a sposób w jaki chcesz wykorzystywać przerwania to już niestety masakra :(

    Ma to prawo działać tak jak opisujesz i to niezależnie czy jest podłączony ISP czy nie. On za każdym razem może się zachowywać inaczej i to widać na pierwszy rzut oka. A na zawieszanie się jest wręcz SKAZANY.

    Proponuję pouczyć się od początku o samych przerwaniach. Bo widać, że ich na razie w ogóle nie rozumiesz.

    Twoja pętla oczekująca na wciśnięcie klawisza w przerwaniu INT1 to pierwszy gwóźdź do trumny

    kolejny papiak to wyświetlanie czegoś na LCD z wewnątrz procedury obsługi przerwania

    Tak nie można. Wystarczyłoby ustawić w tym przerwaniu jedną flagę(zmienną), której stan mógłbyś sprawdzać cyklicznie w pętli głównej zakładając jednak że piszesz funkcje i obsługę w sposób nieblokujący - czyli nie korzystasz z takich delay'ów okrutnych. Można posiłkować się jakimś timerem, żeby odliczać cyklicznie czas potrzebny do wykonywania poszczególnych operacji w pętli głównej.

    No a już w tym wszystkim to globalne włączanie i wyłączanie przerwań - prowadzi do dalszych lawinowych efektów totalnej destrukcji programu. Uwierz mi, że jeśli piszesz iż program ci jakoś tam działa przy podłączonym ISP to tylko przypadek.
  • #6
    felekfala
    Level 19  
    Kolego mirekk36 to program próbny. Wiem, że w przerwaniu należy umieszczać jak najmniej kodu a na pewno już nie jakieś skomplikowane procedury. Kod w tym przerwaniu umieszczony został już po prostu z braku innych pomysłów i ciekawości. Docelowo przyciśnięcie tego przycisku ma zatrzymać prace całego układu, i w nim mam zmienić pewne parametry i powrócić do normalnej pracy ( mam nadzieje że stosu starczy).
    Zrobiłem jak mówiłeś w przerwaniu INT1 zwiększam zmienną "przerwanie" a wyświetlam ją dopiero po przyciśnięciu przycisku w pętli głównej (tego kodu ze sprawdzaniem przycisków też nie będzie w pętli głównej a docelowo miałby być właśnie w przerwaniu od INT1) niestety dalej to samo zaraz po zaprogramowaniu wszystko działa przerwanie od INT1 zwiększa zmienną potem se ja wyświetlam jest ok. Niestety po zdjęciu zasilania układ nie reaguje już na to przerwanie. Przerwanie od INT0 działa poprawnie.

    Programator nie zasila mego podczas programowania urządzenia(wyciągnąłem zworkę).

    Zauważyłem że nie chodzi to tylko o przerwanie od INT1 ale w ogóle część kodu się programuje a części jakby nie było po zresetowaniu przez zdjęcie zasilania.
    Programatory podmieniałem wyjmowałem też procka i programowałem na innej płytce zawsze to samo, nie tylko w tym programie. Część kodu się wykonuje a część nie.

    Dodano po 4 [godziny] 33 [minuty]:

    Po zdjęciu zasilania i ponownym jego włączeniu jako że nie mam przycisku reset a końcówka ta jest podciągnięta do zasilania przez rezystor 10k. Zwarłem przewodzikiem reset do masy. Układ się zresetował i cały kod działa poprawnie. Winą prawdopodobnie jest za wolne narastanie napięcia zasilającego mikrokontroler, ale w avrstudio w fusebitach ustawiłem najdłuższy czas startu 65 ms. Całość ustawienia to: Ext. Crystal/Resonator Medium Freq. : Star-up time 16K CK + 64 ms.
    Nie wiem co oznacza 16K CK bo mam do wyboru 256/1k/16k?
    Czy zastosować układ RC podtrzymujący reset przez dłuższy czas?
  • #11
    hotdog
    Level 26  
    A co jeżeli zaprogramujesz, odłączysz zasilanie i zresetujesz procesor przewodem reset do masy?

    Chodzi mi o to czy program uszkadza się "na stałe" czy tylko nie może sobie poradzić przy starcie?

    Dodano po 4 [minuty]:

    Chyba doczytałem że masz problem tylko "przy starcie". Dziwny problem ja po objawach bym obstawiał, że tutaj wina leży właśnie po stronie BOD'a. Czym to zasilasz w ogóle? Jakieś pewne źródło?
  • #13
    hotdog
    Level 26  
    Zasil układ z pominięciem transformatora ze stab. 5V. Jeżeli problem w wtedy nie występuje to coś masz nie tak w tym zasilaczu.

    Poza tym trochę duże te kondensatory, zmniejsz je daj np może ok. 220uF przed stab. i 47uF za stabilizatorem. Wtedy czas narastania napięcia powinien się poprawić. Sprawdź go na oscyloskopie i czy napięcie jest stabilne. Ogólnie dla LCD, procka i optotriaków takie kondensatory powinny wystarczyć. Poza tym atmel zaleca dodanie kondenstora 100nF na nóżce resetu (między reset i GND) - chociaż to chyba Tobie tutaj za dużo nie da.

    Ja miałem kiedyś podobny przypadek. Układ miał bootloader i ogólnie działał poprawnie. Złożyłem 20 sztuk urządzeń i okazało się że w około 7 występuje problem z przeprogramowaniem urządzenia (bo bootloader zawierał funkcje sprawdzania integralności oprogramowania). Problem występował przy włączaniu urządzenia. W przeprogramowanych układach zawsze były skasowane jakieś strony we flashu (same FF przez całą stronę). Prawdopodobnie licznik PC się przestawiał i wykonywała się instrukcja kasowania strony. Byłem pewien że mam BOD włączony, ale okazało się że tylko byłem tego pewien. Po włączeniu problem jak rękom odjął.

    IMO Bod lub zewnętrzny układ resetu to konieczność w każdym urządzeniu z uC. Procesor zachowuje się nieprzesiadywanie jeżeli jest zasilany z napięcia np 2,0-2,7V. Wtedy może się np stać to o czym piszesz, czyli nie wykonanie jakichś instrukcji, lub złe ich wykonanie, zła inicjalizacja zmiennych itd. Wiem że napisałeś że sprawdzałeś z BOD, ale wszystko mi wskazuje na to że problem leży właśnie tutaj.

    Może jeszcze spróbuj taki workaround. Możesz dodać taki reset warunkowy. Czyli piszesz warunek na początku i sprawdzasz czy reset pochodził od watchdoga. Jeżeli tak to wykonujesz program, jeżeli nie to włączasz watchdoga na ok. 1s i wchodzisz do nieskończonej pętli i czekasz aż się zresetuje.

    Oczywiście nie twierdze że to jest rozwiązania problemu to tylko możliwości jego obejścia.
  • #14
    mirekk36
    Level 42  
    No tak, tu kolega ma rację, bo rzeczywiście jak ktoś przy stabilizatorze napięcia +5V daje na wejściu kilka tys uF a na wyjściu też podobnie to jasna sprawa, że procek bez włączonego BOD'a może wariować na maxa.

    Wystarczy dać jak kolega wyżej poradził na wejściu ze 220uF max a na wyjściu 47uF

    tyle że ja jeszcze bym koniecznie dodał 100nF na wejściu stabilizatora no i przypomniał, że te pary kondensatorów filtrujących to zawsze jak najbliżej nóg scalaków w tym stabilizatora.
  • #15
    felekfala
    Level 19  
    Zastosowałem tak duże pojemności ponieważ układ będzie pracował w pobliżu silnika ( czyli obciążenie indykcyjne) ale nie tego który będzie sterowany triakiem. W ten sposób chciałem aby chwilowe spadki napięć w sieci nie wpłynęły na układ. Ustawiłem w fuse-ach najdłuższy czas startu rzędu 64 ms (nie wiem co oznacza 16k) a czas narastania mego napięcia to 21ms, Boda ustawiałem i na 2,7V i na 4V więc myślałem, że będzie to działać jak należy.
    Rzeczywiście zapomniałem zastosować kondensatorka 100n na wejściu przed stabilizatorem. Wszystkie kondensatory są przy stabilizatorze, dodatkowo przy samej nóżce zasilającej uC zastosowałem filtr dolnoprzepustowy.
    Dziękuje za odpowiedź sprawdzę podane rozwiązania dzisiaj wieczorem lub jutro i odpowiem o uzyskanych efektach.
  • #16
    mirekk36
    Level 42  
    Ale tak duże kondensatory to można i potrzeba zwykle stosować we wzmacniaczach audio ;)

    Takimi pojemnościami nie zabezpieczysz się przed tym co piszesz i masz na myśli ;) .... Wystarczy, że układ zrobisz tak jak się należy (propozycje podane wyżej) i będzie dobrze. Rzeczywiście w docelowym rozwiązaniu włącz BOD.
  • #17
    hotdog
    Level 26  
    tak jak pisze mirek te kondesatorki ciebie nie uratują. Silinik nie powodują takie spadku napięcia o którym mówisz w sieci. Ewentualnie dławik na zasilaniu trzeba dać.

    Siniki są źródłem zakłóceń EMI, czyli idących w powietrzu. Jeżeli chcesz się przed nimi dobrze zabezpieczyć to tylko obudowa metalowa jako ekran.
  • #18
    mirekk36
    Level 42  
    hotdog wrote:
    Siniki są źródłem zakłóceń EMI, czyli idących w powietrzu. Jeżeli chcesz się przed nimi dobrze zabezpieczyć to tylko obudowa metalowa jako ekran.


    No jasna sprawa, tylko, że zanim się kolega zacznie zabezpieczać tak od tyłu - to najpierw niech poprawnie uruchomi układ bo może się okazać, że szereg tych zabezpieczeń będzie niepotrzebnych przy prawidłowo zrobionym zasilaniu i filtrowaniu.
  • #19
    hotdog
    Level 26  
    mirekk36 wrote:
    No jasna sprawa, tylko, że zanim się kolega zacznie zabezpieczać tak od tyłu - to najpierw niech poprawnie uruchomi układ bo może się okazać, że szereg tych zabezpieczeń będzie niepotrzebnych przy prawidłowo zrobionym zasilaniu i filtrowaniu.


    Jak to mawia jeden z czołowych (niestety) polskich polityków - to Oczywista Oczywistość :)
  • #20
    felekfala
    Level 19  
    Jutro zastosuje się do waszych poleceń i zobaczymy co z tego wyniknie.
    Jednak wydaje mi się że silnik asynchroniczny nie emituje dużych zakłóceń (chyba że jest zasilany z falownika) najbardziej "sieją" silniki komutatorowe z powodu iskrzenia między szczotkami a komutatorem. A napięcie przy włączaniu większych silników asynchronicznych jednak siada na parę okresów z tym że może rzeczywiście mój układ tego nie odczuje.
    Dziękuje za odpowiedzi jutro zastosuje się do waszych rad.
  • #23
    mirekk36
    Level 42  
    tak ja mam pomysł, już wcześniej nawet pisałem o nim.

    Zamiast szukać układów opóźniających reset, pokaż jakieś dokładne fotki tego swojego ustrojstwa to może tu się znajdzie winowajca a przede wszystkim pokaż ten swój poprawiony kod (o ile go poprawiłeś) bo jeśli nie to już pisałem - ma prawo się zachowywać losowo i głupio całe to urządzenie. Ja na miejscu procka bym zwariował mając wykonywać to co wcześniej pokazałeś jako kod programu.