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

[atmega16][c] czujnik wstrząsów na INT1, procek świruje...

PO. 01 Mar 2009 15:15 1323 4
REKLAMA
  • #1 6221675
    PO.
    Poziom 20  
    Mojej walki ciąg dalszy, pamiętam o poprzednich tematach, uczę się i kiedyś do nich wrócę :) .

    Otóż podłączyłem czujnik wstrząsów do PD3 i chciałem wykrywać wstrząsy przerwaniem. A propos, okazało się że samochodowy 12v świetnie chodzi na 5v, diodki mrugają więc wiem że wstrząsy wykrywa. Wstrząs sygnalizowany jest zwarciem sygnału do masy - i zmierzone że 0 się pojawia.
    To co się dzieje dalej nie zależy od czujnika bo zwieranie zworką PD3 do masy daje takie same efekty jak wstrząs na czujniku. A ja już głupieję, przetrzepałem dokumentację procka na wszystkie strony, spróbowałem wszystkiego a on dalej świruje.
    Świrowanie objawia się tym że po wywołaniu obsługi przerwania INT1 nie wraca z niego do programu. Obsługa przerwania sprowadzała się do podstawienia 1 pod zmienną wstrzas.
    Gdy póbuję to uprościć i nie obsługiwać przerwania ale badać stosowną flagę w GIFR to następuje jakby reset - wyraźnie widać że lcd się inicjalizuje od początku.
    W kodzie jak widać pojawiły się dodatkowe instrukcje do lcd, stąd wiem co i gdzie się dzieje. Delay po to, żebym zauważył żę coś się wydarzyło (lub nie).
    lcd_zint() wystawia na lcd liczbę jednocyfrową (tu 0/1).

    
    #include<avr/io.h>
    #include<avr/interrupt.h>
    #include<stdint.h>
    #include<c:/ja/h_lcd.h>
    
    #define F_CPU 1000000
    #include<util/delay.h>
    
    
    #define GLUE(a, b)     a##b
    #define PORT(x)        GLUE(PORT, x)
    #define PIN(x)         GLUE(PIN, x)
    #define DDR(x)         GLUE(DDR, x)
    
    #define b(x) (1<<(x))
    
    #define set1   |= 
    #define set0    &= ~ 
    #define toggle    ^=
    
    volatile uint8_t wstrzas=0;
    
    (...)
    
    ISR(INT1_vect){
    // lcd_goto(1,0);
     lcd_zint(wstrzas);
     _delay_ms(500);
     wstrzas=1;
    // lcd_goto(1,0);
     lcd_zint(wstrzas);
     _delay_ms(500);
    }
    
    (...)
    
    int main(void){
    
    //deklaracja wolnych pinów jako in+pullup
     DDRD=0x00;
     PORTD=0xff;
     DDRA=0x00;
     PORTA=0xff;
    
    //deklaracja klawki
     DDRC=0x0f;
     PORTC=0xff; //pullup + logika negacji 
     
     //init drutów
     DDRA=0x00;
     PORTA=0xff;
    
     lcd_init();
     wczytaj_ustawienia();
    
     TCCR1B set0 (b(2));
     TCCR1B set1 (b(1)|b(0));  //preskaler64
     OCR1A=15625;
     
     MCUCR set0 b(3);
     MCUCR set0 b(2); 
     GICR set1 b(7); //czujnik wstrząsów 
    
    prestart:
    
    
     lcd_cls();
     lcd_text("Startujemy?!");
    
    sei();
     do{
      
      lcd_goto(0,0);
      lcd_zint(wstrzas);
      
     /* if(GIFR&b(7)){
       lcd_zint(1);
        GIFR set1 b(7); }
       else lcd_zint(0);
      */
      _delay_ms(500);
      _delay_ms(300);
      wstrzas=0;
    
    //  lcd_rozkaz(0x1c);
    
      //keycheck();
      //if(kl[12]==1) setup(); 
      //if(kl_o==13) goto start;
     }while(1);
     
     


    Instrukcje zakomentowane to rózne wersje testowe (albo oryginalne instukcje z programu), tak samo zakomentowywałem ISR. Więcej nie umieszczam bo program jest duży ale ta pętla jest wieczna :) i nie powinno się już po niej nic dziać...

    Macie jakieś pomysły na to co zrobić z dziwnym zachowaniem procka?

    PS: aha, czyszczenie flagi GIFR w przerwaniu też nic nie daje, w manualu jest ze powinna sama się czyścić ale i tak spróbowałem.

    PS2: testowane zarówno przy przerwaniu na opadającym zboczu jak i przerwaniu na low level, różnic jakby nie ma...
  • REKLAMA
  • #2 6222054
    dawid512
    Poziom 32  
    Bezwzględnie wyrzuć to opóźnienie z przerwania! Ono ma być krótkie! Ustawiaj sobie tylko jakąś flage a w programie głównym kasuj.
  • REKLAMA
  • #3 6222108
    Freddie Chopin
    Specjalista - Mikrokontrolery
    po jakiemu to jest napisane? czemu wszyscy na sile chca utrudnic wyjatkowo prosta skladnie jezyka C? te wszystkie GLUE, set1, toggle i b(x) tylko zaciemniaja obraz, tak ze sie tego nie chce czytac.

    pozatym to co pokazales to smietnik, a nie kod. skoro masz zakomentowane 50% tego kodu, to nie dalo sie go WYWALIC z posta? czy kazdy forumowicz w oku ma preprocesor kodu?

    swoje wlasne naglowki dolacza sie przy pomocy #include "..." a nie podajac pelna sciezke w < > - dzieki " " dolaczany jest plik ktory jest w tym samym folderze co aktualnie kompilowany kod. mozna oczywiscie podfoldery "podfolder/plik.h" jak i wychodzic do gory "../costam.h"

    pokazujesz jakas funkcje lcd_zint(...) i myslisz ze wiadomo co sie w niej dzieje? moze w srodku jest jakis kolejny goto z etykieta dziwna w zupelnie innym miejscu?

    tyle, wiecej z tego niezrozumialego i celowo zaciemnionego (nie mowiac juz o tym, ze niekompletnego) kodu nie chce mi sie wyciagac.

    na koniec jeszcze puenta:
    C JEST P R O S T E ! ! ! dlatego tez gdy widze te makra ktore na sile chca ukryc zwykla skladnie i zrobic z niego bascoma to mnie cos targa - czy jak ktos napisze "a |= (1<<3);" to jest mniej zrozumiale niz "a set1 b(3);"? dla mnie na pewno nie, poniewaz jest cos takiego jak KONWENCJA - funkcja ma nazwe i przyjmuje parametry w nawiasach, wiec jesli dla kogos to takie cierpienie napisac po ludzku (var |= costam), to mozna choc zrobic makro typu set1(PORT,bit).

    4\/3!!
  • REKLAMA
  • #4 6222453
    PO.
    Poziom 20  
    eh...
    W bascomie nie piszę bo... to bascom ;) . Ale c też nie jest idealne, nie oszukujmy się. No ale nie o tym miałem.

    Nie czytacie uważnie opisu problemu. Zaremowane jest żeby było widać, co jeszcze próbowałem i żeby można było samemu w razie czego sprawdzić co robiłem, jak robiłem albo zerknąć co robiłem nie tak i napisać o tym. Opóźnienia są po to, żeby było widać gołym okiem co się dzieje a nie przez 1/1000000sekundy.
    Normalnie nie ma ani obsługi wyświelacza w tym miejscu, ani opóźnień, ani nawet sprawdzenia wstrząsu w tej pętli, to wszystko jest do testów!
    A że dałem tyle ile dałem - nie chciałem dawać za mało, żeby nie było zarzutu że coś oczywistego jest nie tak. Stąd includy, ustawianie pinów i podobne bzdurki.
    Ścieżka pełna bo ten plik jest w jeszcze innym katalogu niż reszta - ale racja zrobię drugą kopię i poprawię to na przyszłość.

    lcd_zint jak pisałem wystawia na lcd jednocyfrową liczbę, po prostu wysyła znak +0x30 (jako przesunięcie tablicy znaków). Nie trzeba nawet sprawdzać tą funkcją, można nawet sprawdzać stany diodkami jeśli ktoś chce się bawić w testowanie na żywym organiźmie.
    LCD działa, przemęczone i przetestowane wcześniej. Aha, i nie ma tam żadnych etykiet o dziwo :) .
  • #5 6227555
    PO.
    Poziom 20  
    Dopisuję ciąg dalszy testów. Pomyślałem żeby przy zerowaniu flagi przerwania wyłaczyć obsługę przerwań - i to też nic nie dało...
    
    sei();
     do{
      
      lcd_goto(0,0);
      if(GIFR&b(7)){
       lcd_znak('a');
        cli();
    	GIFR set1 b(7); 
    	sei();}
       else lcd_znak('b');
      _delay_ms(500);
      _delay_ms(300);
    
     }while(1);


    Pytanie czemu zerowanie flagi wywołuje reset? Wszystko jest ok dopóki nie zewrę pinu do masy (zmieniłem obsługę lcd żeby było czytelniej i prościej) - lilterka 'b' ładnie się świeci więc pętla chodzi w kółko.
    Obsługi przerwania w kodzie nie ma, badam tylko flagę.
    Reset jest pewny - bo przy wyzwalaniu low lewel resetuje się w kółko dopóki zworka siedzi a przy zboczu opadającym reset jest tylko raz. Wyraźnie widać inicjalizację lcd i teksty powitalne.
    Sprawdzone na dwóch prockach więc nie(?) sprzęt.
    Zasilanie niezależnie czy z usb czy z lm7805.

    Mam nadzieję, że temat nie umrze... Co oczywistego pomijam?
REKLAMA