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

Jak zmieniać stan niski na wysoki za pomocą generatora? ATmega168 i język C.

johnnny94 21 Lut 2019 15:16 921 17
  • #1 17794350
    johnnny94
    Poziom 8  
    Witam,

    mam problem ze stworzeniem w języku C generatora, który będzie mi zmieniał stan niski na wysoki (stan niski 10ms, stan wysoki 0.32ms) przez czały czas działania programu niezależnie od pętli głównej programu. Czy jest to wogóle możliwe? Liczę na pomoc w dojściu do rozwiązania tego zagadnienia.
    ATmega 168 taktowana wewnętrzym oscylatorem 8MHz.

    Kod który udało mi się utworzyć.
    Czujnik podłączony do 13 nóżki ((PCINT1/OC1A) PB1)

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #2 17794421
    mr.Sławek
    Poziom 32  
    A nie prościej generwać przerwanie co 10000us i 3200us i zmieniać stan wyprowadzenia?
  • #3 17794454
    johnnny94
    Poziom 8  
    Chodzi o coś takiego?

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #4 17794487
    mr.Sławek
    Poziom 32  
    Raczej chodziło mi o to by na przemian generować przerwania co 10000us i 3200us. W obsłudze przerwania wpisywać odpowiadające tym czasom wartości rejestrów.
  • #5 17794522
    ex-or
    Poziom 28  
    Skoro to timer 16 bitowy to najprościej wygenerować przebieg sprzętowo, bez żadnych przerwań - ustawić timer w tryb PWM albo CTC z OCR1A lub ICR1 jako wartość maks, preskaler 2, wartość top 41279, wartość rejestru Compare Match (OCR1B lub OCR1A) 39999 albo 1279 w zależności od ustawionej polaryzacji, wyjście oczywiście musi być albo OC1A albo OC1B.
  • #6 17797001
    Konto nie istnieje
    Poziom 1  
  • #7 17810331
    johnnny94
    Poziom 8  
    Wybrałem tryb 9 (Phase and Frequency Correct) i napisałem następujący kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    chciałem początkowo uzyskać jakiekolwiek impulsy na wyjściu PB1 (OC1A), natomiast nie ważne jakie wartości wpisuje i tak nic się nie zmienia. Czy w pętli głównej też należy dodać jakieś komendy?? z tego co znajduje w internecie to występują tylko w przypadkach rozjaśniania albo gaszenia diody lub przy rozruchu silnika, kiedy to współczynnik wypełnienia ma być zmienny, a nie jak w moim przypadku stały.
    Fala wyjściowa ma mieć 96.899225Hz (10ms+0,32ms)
  • #8 17810675
    ex-or
    Poziom 28  
    To jest źle
    johnnny94 napisał:
    TCCR1B |= (1<<COM1A1); // POCZĄTKOWO STAN NISKI

    To jest tutaj niepotrzebne
    johnnny94 napisał:
    sei(); // ODBLOKOWANIE GLOBALNE PRZERWAŃ

    Brakuje ustawienia pinu jako wyjście
    Cytat:
    If one or both of the COM1A1:0 bits are written to one, the OC1A output
    overrides the normal port functionality of the I/O pin it is connected to. [...]. However, note that the Data Direction Register (DDR) bit correspond-
    ing to the OC1A or OC1B pin must be set in order to enable the output driver.
  • Pomocny post
    #9 17811994
    Konto nie istnieje
    Poziom 1  
  • #10 17812432
    johnnny94
    Poziom 8  
    stan niski ma mieć 0,0100sec natomiast stan wysoki 0,00032sec = 0,01032sec stąd f=96,899225Hz

    Rozpisałem sobie w taki sposób:

    Jak zmieniać stan niski na wysoki za pomocą generatora? ATmega168 i język C.


    powstał mi kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Przy takim programie na oscyloskopie widzę częstotliwość impulsów ok 122Hz
  • #11 17812999
    Konto nie istnieje
    Poziom 1  
  • #12 17813339
    johnnny94
    Poziom 8  
    Masz rację 0,0132 to jest około 76Hz, natomiast u mnie okres wynosi T= 0,01032 co daje f=96,899Hz.
  • Pomocny post
    #13 17813684
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #14 17814824
    ex-or
    Poziom 28  
    johnnny94 napisał:
    stan niski 10ms, stan wysoki 0.32ms

    emarcus napisał:
    10 ms = 0.010000 [sec]
    0.0032 ms = 0.000032 [sec]
    Suma = 0.010032 [sec] = T


    Litości! :-? :roll:
    Weź to sobie rozpisz na spokojnie. Na kartce w kratkę. W słupkach. Liczby dokładnie w pozycjach. Powoli.
  • #15 17821243
    johnnny94
    Poziom 8  
    Więc już działa poprawnie. Teraz powstał inny problem którego się nie spodziewałem, aczkolwiek jest problem z przerwaniem, a dokładniej wstawiam kod programu
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    nie jestem w stanie osiągnąć delaya mniejszego niz 1.8ms. W czym może być problem? przy ustawieniu _delay_ms(10) przerwanie wynosi 80ms.
  • #16 17821418
    ex-or
    Poziom 28  
    johnnny94 napisał:
    jest problem z przerwaniem,

    Jakim przerwaniem? Tu nie widać żadnego przerwania.
    Aaaa...chodzi Ci o "przerwanie pracy programu przez delay"? Po co te delaye? Może napisz co właściwie chcesz nimi osiągnąć.
    johnnny94 napisał:
    przy ustawieniu _delay_ms(10) przerwanie wynosi 80ms

    Widać nadal masz ustawiony CKDIV w Fuse bitach i procek chodzi na 1MHz.
    Chociaż nie bardzo się to zgadza z...
    johnnny94 napisał:
    Więc już działa poprawnie
  • #17 17821466
    johnnny94
    Poziom 8  
    Więc już działa poprawnie, odnosiło się do Timera i ustawienia trybu PWM
  • #18 17830342
    SylwekK
    Poziom 32  
    johnnny94 napisał:
    Więc już działa poprawnie. Teraz powstał inny problem którego się nie spodziewałem, aczkolwiek jest problem z przerwaniem, a dokładniej wstawiam kod programu
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    nie jestem w stanie osiągnąć delaya mniejszego niz 1.8ms. W czym może być problem? przy ustawieniu _delay_ms(10) przerwanie wynosi 80ms.


    Jeśli aktywne są przerwania to delay będzie opóźniał.
    Pokaż całość programu.
REKLAMA