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

[ATmega88p] Timer zaczyna działać po około minucie

m471 07 Sty 2020 23:24 816 11
  • #1 18388745
    m471
    Poziom 5  
    Witam,

    Napisałem program, który docelowo miał odbierać dane z komputera przez modem BT HC-05 interfejsem UART oraz potwierdzać odebranie danej, oraz wysyłać dane z ADC jeśli przyciśnięty zostanie przycisk (w rzeczywistości jest to wycinek pewnego programu, więc niektóre zmienne etc. mogą być bez sensu). Odczyt ADC wykonuję wykorzystując przerwania capture timera 1.
    Problem tkwi w tym, że program prawidłowo działa ok. minutę po restarcie procesora, wcześniej jedynie odbiera i potwierdza dane.
    Głowię się nad tym cały dzień, w czym może tkwić problem?

    Kod:
    main.c:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    init.c:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Biblioteka UART Petera Fleury'ego (niestety nie mogę udostępnić linku)

    Schemat podłączenia (piny Rx i Tx podłączone są do modemu bt):
    [ATmega88p] Timer zaczyna działać po około minucie

    Z góry dziękuję za odpowiedź
    Pozdrawiam :)
  • #2 18388797
    BlueDraco
    Specjalista - Mikrokontrolery
    Jaki jest okres przerwań timera? Gdzie go programujesz?
    Poza tym dość niefrasobliwie dobierasz typy danych. Jednobitowe znaczniki są u Ciebie 16-bitowe (int) zamiast _Bool/bool (tak, od 20 lat jest taki typ w języku C i nie trzeba go "robić") , masz jakieś dziwne konwersje z char na int i podobne - po co?
  • #3 18389033
    ex-or
    Poziom 28  
    m471 napisał:
    w czym może tkwić problem?

    W skopanym "flow' programu. Na pierwszy rzut oka widać, że dwa wystąpienia uart_getc (i to z różnymi zmiennymi) oraz pętla while w ostatnim else są podejrzane.
    BlueDraco napisał:
    masz jakieś dziwne konwersje z char na int i podobne - po co?

    W libie Fleurego uart_getc zwraca typ int gdzie w starszym bajcie zwracane są ewentualne błędy. Z kolei uart_putc przyjmuje unsigned char.
  • #4 18389438
    m471
    Poziom 5  
    ex-or napisał:

    W skopanym "flow' programu. Na pierwszy rzut oka widać, że dwa wystąpienia uart_getc (i to z różnymi zmiennymi) oraz pętla while w ostatnim else są podejrzane.


    Generalnie program ma odebrać jedną zmienną, i czekać aż przyjdzie druga (w głównym programie wpisuje potem wartość drugiej zmiennej w rejestr ocr, a w który określa pierwsza zmienna, tak realizuje sterowanie silnikami przez bt) i to działa bez zarzutów. Problem mam z timerem który pierwsze przerwanie wywołuje po około minucie i dalej już działa jak powinien.

    Dodano po 6 [minuty]:

    BlueDraco napisał:
    Jaki jest okres przerwań timera? Gdzie go programujesz?
    Poza tym dość niefrasobliwie dobierasz typy danych. Jednobitowe znaczniki są u Ciebie 16-bitowe (int) zamiast _Bool/bool (tak, od 20 lat jest taki typ w języku C i nie trzeba go "robić") , masz jakieś dziwne konwersje z char na int i podobne - po co?


    Masz racje, nie podałem ważnego. Częstotliwość uC to 8Mhz (wiem ze powinna być wielokrotnością 1,8432 do uarta ale czekam aż mi przyjdzie kwarc i chce testować resztę działania programu). Timer programuję w pliku init.c jeśli o to chodzi. Konwersje tak jak kolega powiedział, trzeba do liba. Jeśli natomiast chodzi o typ bool, w każdej instrukcji warunkowej mam warunek którym porównuje wartości liczbowe, stąd nie używam typu bool.
  • #5 18393159
    BlueDraco
    Specjalista - Mikrokontrolery
    W tym programie jest mnóstwo błędów. Popatrz chociażby na zmienną ADC_tmp - zły typ, zły zasięg. Dwa kolejne odczyty ADC - po co, skoro dane z pierwszego odczytu są używane tylko wtedy, gdy drugi odczyt spełnia określony warunek?

    Nie pytałem, w którym pliku programujesz timer, tylko jak chciałeś go zaprogramować (okres, przerwania).
  • #6 18405582
    m471
    Poziom 5  
    BlueDraco napisał:
    W tym programie jest mnóstwo błędów. Popatrz chociażby na zmienną ADC_tmp - zły typ, zły zasięg. Dwa kolejne odczyty ADC - po co, skoro dane z pierwszego odczytu są używane tylko wtedy, gdy drugi odczyt spełnia określony warunek?

    Nie pytałem, w którym pliku programujesz timer, tylko jak chciałeś go zaprogramować (okres, przerwania).


    ADC_tmp usunąłem, operuje juz na adc i rzutuję ją do uarta. Aktualnie timer programuje tak, żeby działało, ponieważ faktyczny okres jest znacznie inny od wyliczonego. Choć wciąż nie wiem, dlaczego ten timer włącza się po minucie, nie widzę powiązania z błędami które wymieniłeś, czy to może być wina programatora? Używam USBasp, ponadto przy zakupie dostałem taśmę o długości ok 20cm, a z tego co czytałem długość przewodu łączącego USBasp z uC nie powinna przekroczyć 10cm...
  • #7 18405703
    trol.six
    Poziom 31  
    Mam dziwne wrażenie jak patrze na te linijke, jakie przerwanie wykorzystujesz...

    Cytat:
    ISR(TIMER1_CAPT_vect)


    ... że to działa całkiem przypadkowo.
  • #8 18405848
    excray
    Poziom 41  
    trol.six napisał:
    Mam dziwne wrażenie jak patrze na te linijke, jakie przerwanie wykorzystujesz...

    Wektor jest OK. Nie ok jest to, że OCR1A i ICR1nie zostały skonfigurowane, a dokładniej, to że jest tam 0.
  • #9 18406709
    trol.six
    Poziom 31  
    No a kiedy się flaga tegoż przerwania ustawi? Bo w nocie jest taki rysunek:

    [ATmega88p] Timer zaczyna działać po około minucie


    Aha... bo tam jest tryb CTC. ;) A to faktycznie.
    .
  • #10 18592330
    m471
    Poziom 5  
    excray napisał:
    trol.six napisał:
    Mam dziwne wrażenie jak patrze na te linijke, jakie przerwanie wykorzystujesz...

    Wektor jest OK. Nie ok jest to, że OCR1A i ICR1nie zostały skonfigurowane, a dokładniej, to że jest tam 0.


    ICR1 jest skonfigurowane w Timer_init()
  • #11 18592543
    JarekC
    Poziom 32  
    Problemem może być to że zapis do 16-bitowego rejestru np ICR1 musi być wykonany we właściwy sposób.

    U ciebie przy inicjalizacji timera jest tylko:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    spowoduje to że dana zostanie zapisana do tymczasowego rejestru i nie zostanie przepisana do rejestru ICR1.
    Zapis do docelowego 16-rejestru następuje dopiero w momencie zapisu do jego młodszej części.

    Prawidłowa sekwencja to :
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    W przypadku odczytu kolejność jest odwrotna.
    Poza tym dlaczego OR a nie przypisanie konkretnej wartości.

    Są pewne wyjątki np odczyt OCR1A/B może być w dowolnej kolejności.

    Pełny opis znajdziesz w karcie katalogowej procesora, rozdział "Accesing 16-bit Registers"
  • #12 18592569
    excray
    Poziom 41  
    m471 napisał:
    ICR1 jest skonfigurowane w Timer_init()

    W niewłaściwy sposób i w niewłaściwej kolejności.
REKLAMA