Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Zliczanie impulsów, Timer, 8051

23 Paź 2007 12:09 9421 58
  • Poziom 17  
    Witam. Mam nadzieję, że i tym razem uzyskam od Was pomoc.
    Chciałem napisać program do zliczania impulsów, a dokładnie np. zliczanie impulsów w okresie czasu 15 sekund i jak zostaną zliczone dwa impulsy to ma się zapalić dioda. Poniżej przedstawię kod programu, ale najpierw objaśnienia.

    Timer T0 - zlicza impulsy
    Timer T1 - odmierza czas zliczania

    Kwarc 6Mhz, zatem 6Mhz/12 daje 500000 Hz
    Przyjmuje sobie ziarnko odmierzanego czasu jako 10Hz (o,15 sekundy) Zatem: 500000 Hz/50000
    50000 to zapiane w Hex C350
    FFFF - C350 to daje 3CAF te wartości wykrorzystuje w programie.

    Wiem, że trzeba odpowiednio ustawić poszczególne bity w rejestrze TMOD. Tylko nie wiem, gdyż są 4 tryby działania Timerów ( 0,1,2,3), ja wybrałem MODE 1, czy jest to dopowiednie pod moje potrzeby? Jezel i tak, to czy zapis TMOD=0x0D; jest prawidłowy? Nie wiem czy dobrze skonfigurowałem te Timery, prosiłbym o weryfikacje
    osoby, które mogą pomóc. Nie wiem jak zrobić, żeby dioda się zapalała po zlcizeniu tych 2 impulsów. Byłbym wdzięczny za pomoc. Pozdrawiam.

    Code:
    #include <8051.h>
    
    #include <stdio.h>

    #define SECOND 100
    #define PortLED P1_1

    ////////////////////////////////////////////////////////////////////////
    void main(void)//program glowny
    {
       TMOD=0x0D;           //Ustawienie trybu Timerow
       
       TR1=1;         //Start Timer 1
       TH1=0x3CAF;      //Wpisanie wartosci do rejestra
       TL1=0;
       
       TH0=0xFE;      //Wpisanie wartosci do rejestra (ma zliczyć 2 impulsy i zasygnalizować to)
       TL0=0;   
       TR0=1;         //Start Timer0
       ET1=1;         //Zgoa na przerwanie od TIMER1
       EA=1;         //zezwolenie na przerwanie
       
       while(1)      //petla
       {   
          while(!INT0) {}; //Linia INT0 bramkuej zliczanie      
          while(INT0) {};
          TH0=0;      //zerowanie licznikow TH0   
          TL0=0;      //i TL0 przed pomiarem
       }
          
    }

    //podprogram przerwania
    void T1_int(void) interrupt 3 using 1
    {   
       int count=0;
       TH1=0x3CAF;   //czas do następnego przerwania
       TL1=0x00;
       if (++count==SECOND)
       {
          count=0;
          INT0=!PortLED;
          
       }
    }
  • Poziom 26  
    A nie prościej byłoby ustawić timer, żeby odmierzał 15 sekund, a impulsy zliczać przy pomocy przerwania. Każdy impuls zwiększałby licznik impulsów (w przerwaniu). Po odmierzeniu 15 sekund miałbyś przerwanie od timera, w którym odczytywałbyś licznik impulsów i odpowiednio reagował. Po odczytaniu zerowałbyś licznik impulsów. Cały cykl powtarzałby się od początku.

    Wydaje mi się, że taki algorytm byłby prostszy, pod warunkiem że impulsów nie byłoby zbyt dużo, powiedzmy kilka na sekundę.
    Przy większych częstotliwościach, lepiej byłoby zrobić zliczanie impulsów drugim timerem, tak jak proponowałeś.
  • Poziom 17  
    Docelowo ma być ok. 100 impulsów na sekundę, zatem takie rozwiązanie odpadłoby. Sprawdziłem ten programik, kompiluje się, a po wgraniu do procka...otrzymuje to, ze podłączona dioda świcie/gaśnie naprzemiennie. Byłbym wdzięczny za podpowiedź jak udoskonalić/ przrobić program tak, żeby np. po dwóch impulsach zapaliła się dioda. Proszę o porady/wskazówki/pomoc.
    Pozdrawiam.
  • Poziom 14  
    tryby pracy układu czasowolicznikowego:
    0. licznik 13 bitowy 8th+ 5tl (nie pamiętam czy starsze,czy młodsze)
    1. tryb 16 bitowy 8th +8tl
    2. tryb 8 bitowy tl po przepełnieniu wpisuje wartość z th
    3. dwa liczniki 8 bitowe th0 i tl0 sterowane za pomocą bitów sterujących odpowiednio t1 i t0

    jeśli chodzi o bramkowanie to możesz to zrobić ustalając GATE =1 (to jest bit słowa tmod, ale ono nie jest adresowane bitowo) - poszukaj o układzie czasowo licznikowym to na pewno znajdziesz cos lepszego graficznie :)
    i jeszcze jedno C się dopiero uczę więc niezbyt dokładnie przeanalizowałem program ale wpisujesz do 8 bitowego th1 wartość 16 bitową (kompilator nie ostrzega?)
    Cytat:

    TH1=0x3CAF; //Wpisanie wartosci do rejestra


    jeśli coś jeszcze chcesz wiedziec o t0 i t1 to pisz powodzenia pozdrawiam
  • Poziom 17  
    Dzięki za pomoc. Oczywiście są jeszcze rzeczy, które chciałbym wiedzieć, chętnie zapytam i się dowiem.

    Znam te 4 tryby działania Timerów, wybrałem właśnie tryb 1.
    Wiem, że: TMOD ustawia tryby pracy Timerów 1 i 2. Cztery młodsze bity ustawiają timer0, cztery strasze ustawiają Timer 1.
    Z tym programem to wzorowałem się na literaturze i np. nie wiem:
    jak rozszyfrować zapis TMOD=0x0D; a także zapis TMOD = TMOD | 0x10; ? Dlaczego właśnie jest tak?
    Czy ten kawałek kodu oznacza, że nastąpi przepełnienie po szczytaniu dwóch impulsów? TH0=0xFE; TL0=0;
    Noi chciałbym wiedzieć jak zrealizowac programowo, żeby np. zapalił diodę po szczytaniu 2 impulsów?

    A co do Twojego pytania. Nie, kompilator nie niekrzyczy, pojemność Timera to 65536, więc nie ma problemu.
    Pozdrawiam.
  • Pomocny post
    Poziom 14  
    no dobra tmod skałda się z dwóch czwórek następujących bitów:
    GATE,C/T,M1,M0
    m1 i mo ustalają tryb które znasz.
    C/T określa funcję c/t=1 Counter czyli zlicza impulsy doprowadzone do wejścia T(0lub1 w zalezności który licznik) c/t=0 timer zlicza cykle maszynowe (właściwie to powinno być C/ (negacja) T, tylko nie wiem jak to napisać) :) :(
    Gate - bramkowanie zliczania gate=1 licznik liczy jeżeli tr=1 i int=1; gate=0 licznik liczy jezeli tr=1;
    tmod=0x0d oznacza, że :
    licznik t1:
    gate=0; wystarczy, że tr=1 żeby liczył
    c/t=0 zlicza wewnętrzne impulsy
    m1=0
    mo=0 tryb 0
    licznik t0:
    gate=1 -zliczanie zależy od int1
    c/t=1 zlicza zewnętrzne impulsy doprowadzone do t0
    m1=0;
    m0=1 tryb 1

    Cytat:
    Czy ten kawałek kodu oznacza, że nastąpi przepełnienie po szczytaniu dwóch impulsów? TH0=0xFE; TL0=0;

    i tak i nie - to zależy od trybu
    w trybach od 0 do 2 nie w trybie 3 tak
    16 bitowy licznik to składa się z 2 części 8 bitowych tho- starsza część i tlo młodsza część żeby zwiększyć o 1 tho to przepełnić sie musi tlo, a Ty do niego wpisujesz 0 jeśli chcesz liczyć do 2 to nalepiej wykorzystac tryb 2 wpisując do th fe
    Cytat:
    Noi chciałbym wiedzieć jak zrealizowac programowo, żeby np. zapalił diodę po szczytaniu 2 impulsów?


    przepełnienie licznika jest sygnalizowane ustawieniem bitu TF w słowie TCON i tu masz 2 wyjści albo na bieżąco spawdzasz stan tego bitu i jesli jest ustawiony to go kasujesz i robisz co trzeba; albo 2 wyjscie robisz to w przerwaniu od tego licznika (tu nie musisz kasowac TF)

    Cytat:
    TMOD = TMOD | 0x10;


    co do tego to jakaś funcja logiczna C na słowie TMOD i wartości 0x10 ; wynik umieszczony w TMOD ale co to za funckja to nie pamiętam bo niestey za mało używam :(
    Cytat:
    pojemność Timera to 65536, więc nie ma problemu.


    zgoda ale jak pisałem cały licznik ma taką pojemność, a Ty do jego połowki wpisujesz wartość 16 bitową :)
    uff
    coś jeszcze?
    napisz jak poszło
  • Poziom 17  
    Więc tak...
    Zrozumiałem jak interpetować zapi TMOD=... Ok.
    Z tego co piszesz, to ustawiłem teraz Timer0 w trybie 2, po to , żeby nastąpiło przepełnienie i, żeby mógł pozostać zapis:
    TH0=0xFE;TL0=0;
    Skoro Timer0 jest w trybie 2 to teraz napisałem, że TMOD=0x0E; (00001110).
    Teraz tylko pozostał problem z sygnalizacja diody po tych dwóch impulsach...Napisałeś, że jest to sygnalizowane przepełnieniem bitu TF w słowie TCON. Z tego co wiem, to w rejestrze TCON znajdują się po dwa bity sterujące dla każdego timera TRx i TFx i flaga przepełnienia ustawiona jest automatycznie na 1 w momencie przekroczenia zakresu tegoż Timera. Jednakże brakuje mnie wiedzy jak to zrealizowac programowo Będzie to w funkcji main w pętli while? Czy się mylę?

    Co do tych połówek -bitowych Timerów, to dla pewności teraz zmieniłem te czasy na inne, i np.wstawiłem wartość TH1 = 0x87;
    Ale spotkałem się z czymś takim, że wstawiają właśnie 0x87 jako 0x87FF, co jest 34815, natomiast 3CAF daje 15535. Tym się sugerując wstawiałem, ale chwuilowo to pomińmy. Nakieeuj mnie programowo, jak możesz, jak zrobić to wyświetlenie po zczytaniu tych dwóch impulsów.
    Pozdrawiam.

    A tak obenie wygląda program:
    Code:
    #include <8051.h>
    
    #include <stdio.h>

    #define PortLED  P2_5
    #define SECOND 100    //1sek to 20 przerwan od Timer

    void main(void)
    {   

       TMOD=0x0E;
       
       TH0=0xFE;      
       TL0=0;   
       TR0=1;
       
       TH1 = 0x87;
       TL1 = 0;
       TR1 = 1;
       ET1 = 1;
       EA = 1;

       while(1) {
          
          TH0=0;      //zerowanie licznikow TH0   
          TL0=0;      //i TL0 przed pomiarem
       
          };
       }
    void T1_int(void) interrupt 3 using 1
       {
       static data unsigned char count=0;
       TH1 =0x87;
       TL1 =0;

       if (++count ==SECOND)
          {
          count =0;
          INT0=PortLED=!PortLED;
          }
       }
  • Poziom 14  
    gdyby tak jeszcze jakiś schemat to byłoby prościej ale na razie to:
    Cytat:

    Z tego co piszesz, to ustawiłem teraz Timer0 w trybie 2, po to , żeby nastąpiło przepełnienie i, żeby mógł pozostać zapis:
    TH0=0xFE;TL0=0;

    to jjest nie całkiem dobrze bo zlicz TL0, aTh0 przechowuje wartość jaką należy wpisać po przepełnieniu nalepij byłoby:
    TH0=0xFE
    TL0=0xFE
    Cytat:

    TMOD=0x0E; (00001110).

    ok T0 jest w trybie 2 ale po co gate=1 (pierwsza jedynka) stad pytanie o schemat

    Cytat:
    tego co wiem, to w rejestrze TCON znajdują się po dwa bity sterujące dla każdego timera TRx i TFx i flaga przepełnienia ustawiona jest automatycznie na 1 w momencie przekroczenia zakresu tegoż Timera. Jednakże brakuje mnie wiedzy jak to zrealizowac programowo Będzie to w funkcji main w


    dobrze wiesz x=0 lub 1 odpowiednio dla każdego licznika TRx=1 włącza zliczanie TFx sygnalizuje przepełnienie (przepełnienie i przekroczenie zakresu to chyba nie to samo) ustawienie TF (piszę w skrócie bez x bo dla obu jest tak samo) może powodowac przerwanie jeżeli go włączysz.
    no to chyba teorię mamy z głowy (prawie)
    co do konkretnego roziązania programowego to przychyliłbym sie do propozycji kolegi arturt134
    Twój program w funkcji main tylko w kółko zeruje licznik T0 i nic więcej, a odmirzanie czasu (jeśli jest dobre) w przerwaniu nie sprawdza nic co sie dzieje w T0 i jeszcze jedno jeśli ten czas ma być dokładnie odmirzany to to całkiem nie działa, bo gubisz kilka cykli maszynowych na przyjecie przerwania i wpis nowej wartości; trzeba w asemblerze wstawic coć takiego:
    ORL TL1,#wartość jaką trzeba wpisać do tl1
    MOV TH1, # wartość jaką trzeba wpisac do th1
    jeszcze co do propozycji kolegi arurt134 to Twoje 100 impulsów nie powinno byc zbyt duzo . przemyśl sprawę jeszcze raz i zacznij najlepiej od początku ja ze swojej strony chetnie pomogę ale w C nie jestem mocny jak pisałem
    na rzie ode mnie tyle pozdawiam rs

    dzięki za punkty :)) :))
  • Poziom 17  
    Dzięki za odpowiedź.
    Co d oschematu to nierysowałem gdyż są tam tylko następujące rzeczy:
    -procek AT9S52
    -sygnał zewnętrzny podaje na wejście timera T0, to jest na P3_4
    -diodę sygnalizacyjną podłączam na P2_5. To wszystko.
    Póki co narazie chcę pozostać przy takim rozwiązaniu, jakie jest, tzn. zliczanie impulsów za pomocą drugiego Timera. Sęk w tym, że nie wiem jak to teraz dalje dokończyć. Brakuje mnie jeszcze wiedzy i umiejętności w C...dlatego mam nadzieję, że ktoś z Was pomoże.
    Narazie czasy nie są istotne (super dokładność), chodzi tylko oto, żeby zadziałało.
    Czy w funkcji main powinienem na początku dodać coś w postaci:
    while(TH0=0x00) {PortLED=0;}; jako srawdzenie co się dzieje w TO ?
    Pozdrawiam.
  • Poziom 14  
    A dlaczego nie zastosować sposobu arturt134? Odmierzasz 15 sekund i sprawdzasz ile jest impulsów (wywołanych przerwaniem). Problem ich dużej ilości rozwiążesz jeśli w przerwaniu ilość impulsów będzie zliczane w paru bajtach zamiast w jednym; np. od 0 do 100 w bajcie A po dodaniu impulsu sprawdzasz czy jest sto jeśli jest to A=0 a inkrementujesz bajt B. Dla 2 bajtów masz 25500 impulsów jeśli tego mało to możesz zrobić 255x255 albo jeszcze razy 255 używając bajtu C.
  • Poziom 26  
    Oczywiście, że można zrobić licznik impulsów o długości 16 bitów.
    O zliczaniu małej ilości impu8lsów mówiłem tylko dlatego, że ten procek pewnie robi coś jeszcze oprócz zliczania impulsów. Jeżeli ich częstotliwość jest zbyt duża, to jedno przerwanie jest zgłaszane za drugim, no i kontroler nie może robić nic więcej tylko obsługiwać te przerwania.
    Przepraszam, że nie napisałem tego dostatecznie jasno.

    Reasumując, możesz zawsze zliczać impulsy, pod warunkiem, że licznik posiada odpowiednią długość i procesor ma dość czasu, żeby obsłużyć wszystkie nadchodzące przerwania no i oczywiście wykonywać program główny.
  • Poziom 17  
    Witam. Dzięki za odzew.
    Zacząłem poruszać się tym tropem i chciałbym to skończyć w ten sposób, czyli T0- zlicza impulsy, T1-odmierza czas. I teraz jest taki pomysł.
    Rejestry T0 to TH0, TL0, W tej chwili T0 jest ustawiony w tryb pracy 2. Jednakże myślałem o czymś takim:
    T0 ustawić w tryb pracy 1
    TH0 i TL0 - wartości początkowe ustawić na zero.
    W przerwaniu pozostawić odmierzanie czasu przez T1, natomiast dopisać funkcję, że:
    TH0=a;
    if (a==2) PortLED2=0;

    Czy to jest dobry tok myślenia?
    Bo na logikę, Timer T0 zlicza impulsy, wtedy jego rejsetr powinien się zwiększać (napisałem, że TH0, aczkolwiek nie mam pewnosci czy nie bedzie to TL0). I gdy zliczy dwa impulsy w zadanym przez Timer1 czasie, to zapala diode.
    Jeżeli jest to prawidłowy tok myślenia to prosze o dalsze porady. Powinienem tan zapis umiescic w while w main?
    Code:
    while(1) {
    
          TH0=a;
          if (a==2) PortLED2=0; }

    Pozdrawiam i proszę o dalsze wskazóki.
  • Poziom 26  
    Przypisanie masz w drugą stronę. Powinno być chyba a=TH0.
    No i powinieneś go gdzieś zerować.

    Nie bardzo rozumiem jakie powinno być działanie programu. Czy dioda ma się zapalić po stwierdzeniu 2 impulsów w cigu 15 sekund i palić się do końca świata? Czy może ma się zapalić i palić do końca 15 sekundowego cyklu? A może jeszcze inaczej? Spróbuj opisać działanie programu trochę dokładniej.

    Jeżeli wystarczy stwierdzić, że w ciągu 15 sekund wystąpiły dwa impulsy, to polecam jednak moją metodę z wykrywaniem impulsów w przerwaniu. Po stwierdzeniu że otrzymałeś 2 impulsy, przerwanie po prostu wyłączasz. Odblokowujesz je po upływie cyklu 15 sekundowego, zerując licznik impulsów (jego wartość będzie równa 2).
  • Poziom 17  
    Póki co narazie chce pozostać przy tej metodzie.
    Timer mierzy czas np. 15 sekund, w tym czasie T0 zlicza, nastepuje pomiar.Po skonczeniu pomiru dioda ma gasnąć, kolejny pomiar, zliczone dwa impulsy, dioda się zapala, gaśnie po upływie końca zliczania Timera1, i tak w kółko. Wiem,ze to dziwne, ale poprostuchce sobie sprawdzić jak to wszystko działa. W przyszlości to ma byc zliczanie obrotów(impulsow) od silnika DC, powidzmy coś na wzór obrotoierza, ale to później. Mam nadzieje, że Ci wyjaśniłem o co mnie chodzi.
    Pozdrawiam.
  • Poziom 26  
    Teraz już wszystko jasne.
    Jeżeli się upierasz przy uzyciu timera do zliczania impulsów to OK. Musisz tylko się zabezpieczyć przed przepełnieniem. Zastanów się co się stanie, jeżeli w ciągu jednego cyklu pomiarowego (15 sekund) przyjdzie więcej impulsów niż timer jest w stanie zmieścić w swoim liczniku, np. wskutek zakłóceń.
  • Poziom 17  
    To dobrze, że już wszystko wyjaśniliśmy w pewnych kwestiach.
    Przerobiłem troszke program, ustawiłem Timery w odpowiednie tryby, jednakże prgoram nie działa. Może wiecie czego brakuje w tym kodzie , ewentualnie co jest nie tak?Może zerowanie Timerów jest źle zrobione? Po przejściu dwóch impulsów dioda się niezapala.
    Kod poniżej. Pozdrawiam.
    Code:
    #define PortLED  P2_5 
    
    #define PortLED2  P2_4
    #define SECOND 200    //1sek to 20 przerwan od Timer

    void main(void)
    {   

       TMOD=0x06;
       
       TH0=0;       
       TL0=0;   
       TR0=1;
       
       TH1 = 0x87;
       TL1 = 0;
       TR1 = 1;
       ET1 = 1;
       EA = 1;

       while(1) {
           
          int a;
          a=TH0;
          if (a==2) PortLED2=0;
          TH0=0;      //zerowanie licznikow TH0   
          TL0=0;      //i TL0 przed pomiarem
       
          };
       }
    void T1_int(void) interrupt 3 using 1
       {
       static data unsigned char count=0;
       TH1 =0x87;
       TL1 =0;

       if (++count ==SECOND)
          {
          count =0;
          PortLED=!PortLED;
          }
       }
  • Poziom 26  
    Zerowanie timera powinno być zrobione tak:
    if (a==2)
    {
    PortLED2=0;
    TH0=0; //zerowanie licznikow TH0
    TL0=0; //i TL0 przed pomiarem
    }

    W twoim kodzie timer był zawsze zerowany, niezaleznie od tego czy dwa impulsy wystąpiły, czy nie. No i nie wiem, czy powinienes sprawdzać TH0 czy TL0. Sprawdź, który z tych rejetrów zawiera młodszy bajt wyniku, bo to niego powinieneś odczytywać.
  • Poziom 17  
    Witam.
    Ten kawałek programu wygląda następująco:
    Code:
     while(1) { 
    
           
          int a;
          a=TL0;
          if (a==2)
          {
             PortLED2=0;
             TH0=0; //zerowanie licznikow TH0
             TL0=0; //i TL0 przed pomiarem
          }

       
              }


    Więc tak.
    Rzeczywiście zmieniłem i przypisałem obecnie a=TL0; .
    Program zadziałał, owszem. Jednakże cos jest nie tak i nie mogę do tego dojść. Próbowałem dla kilku wartości zmiennej a, ale dioda cały czas zapala się po jednym impulsie (nieważne jaką wartość ma zmienna a).
    W czym może tkwić problem?
    Co więcej, po przerwaniu dioda PortLED2 cały czas się świeci, niegaśnie, też nie wiem dlaczego. Jakieś sugestie?
    Pozdrawiam.
    Edit:
    Chodzi oto, żeby uzyskać nastepujący efekt:
    Zliczanie impulsów podczas odmierzenia czasu, następnie przerwanie (i w tym momencie, czyli w trakcie trwania przerwania, żeby tutaj nastąpiło wyświetlenie ilości zliczonych impulsów, czyli zapalenie PortLED2).
  • Poziom 26  
    Przypisanie: PortLED=!PortLED miało pewnie służyć do zgaszenia diody. W ten sposób możesz też ją zapalać (jeżeli jest zgaszona, to zmiana stanu na przeciwny spowoduje jej zapalenie).
    Lepiej byłoby przypisać jawnie stan wysoki (bo takim stanem ją chyba gasisz), zamiast zmieniać go na przeciwny.

    Poza tym uruchamianie kodu ja bym przeprowadził dwuetapowo. W pierwszym etapie sprawdziłbym jak działa timer odmierzający 15 sekund, na przykład każąc mu zmieniać stan diody po upływie każdego okresu (na przeciwny). Na czas uruchamiania tego timera resztę kodu bym zaremował.
    Dopiero po stwierdzeniu, że timer 1 sekundowy działa dobrze, zabrałbym się za resztę programu.
  • Poziom 17  
    Więc tak...
    Poprawiłem zliczanie w Timer1, gdyż rzeczywiście było błędne.
    Z kolegą Artur źle się znowu zrozumielismy w jednej rzeczy. Dioda PortLED służy tylko jako sygnalizacja pracy Timera!, tak żebym mógł sprawdzić czy działa poprawnie. Teraz już działa poprawnie.
    Docelowo ma być tak, że mierzy okres 1s, jednakże dla testów ustawiłem w tej chwili ok 10s, tak abym mógł fizycznie zdążyć z podawaniem impulsów na wejście Timer0.
    Program uruchomiłem dwuetapowo, tak jak radziłeś. Wnioskuję, że problem leży przy Timer0, albo coś źle w funkcji while, albo źle go skonfigurowałem.
    obecnie jest tak, że Timer1 jest ustawiony w tryb 1 i Timer0 jest ustawiony w tryb 1. Czyli mam następujacy zapis:
    TMOD=0x15; patrząc na to co kolega wcześniej napisał to jest to:

    Timer1 | Timer0
    G|C/T|M1|M0 |G|C/T|M1|M0 czyli mam, że:
    0001 0101

    T1 ma liczyć czas, T0 ma zliczać impulsy podawane na T0. I teraz chcę mieć pewność czy dobrze to skonfigurowałem? Może problem leży tutaj? Może tutaj pokręciłem właśnie coś?

    Dalej. Program w obecnej chwili działa tak, że po wykryciu impulsu na wejściu T0 zapala diode PortLED2.
    Moim celem jest aby program działał w następujący sposób:
    T1 liczy czas, w tym czasie są podawane impulsy (czyli przyszłosciowo w trakcie 1s), natomiast w drugiej sekundzie ma być wyświetlany wynik, i tak w kółko. Teraz dioda PortLED2 niegaśnie po zapaleniu i zapala się już w trakcie zliczania po otrzymaniu jednego impulsu na T0.
    Mam nadzieję, że już wszystko jasno objaśniłem. Jakieś pomysły jeszcze?
    Byłbym zainteresowany.
    Pozdrawiam i pod spodem obecny kod programu.
    Code:
    #define PortLED  P2_4 
    
    #define PortLED2  P2_5
    #define SECOND 160   //Ok 10 sekund

    void main(void)
    {   

       TMOD=0x15;
           
       TR0=1;
       TH1 = 0x87;
       TL1 = 0;
       TR1 = 1;
       ET1 = 1;
       EA = 1;
     
       TH0=0;
       TL0=0;
       while(1)
       {
       int a;
       a=TL0;
       if (a==2)
          {
             PortLED2=0;
             TH0=0; //zerowanie licznikow TH0
             TL0=0; //i TL0 przed pomiarem
          }
       }
    }
    void T1_int(void) interrupt 3 using 1
       {
       static data unsigned char count=0;
       TH1 =0x87;
       TL1 =0;

       if (++count==SECOND)
          {
          count =0;
          PortLED=!PortLED;
          }
       }
  • VIP Zasłużony dla elektroda
    Temat poprawiłem :arrow: regulamin
  • Poziom 14  
    liczniki wygądają na dobrze ustawione;
    led2 powinien migać niezależnie od wszystkiego i na moje oko w ten program ma sszanse tak działac ,ale jesli sprawdziłbyś to jeszcze raz dla pewności to byloby dobrze (w main pusta pętla);

    teraz istotne pytanie : Jak podajesz impulsy na t0?, jeśli to jest przełącznik to drgają styki i licznik liczy więcej niż Ci się wydaje

    i kolejna sprawa w Twoim programie oba liczniki liczą niezależnie a chyba powinno byś tak :
    1 Pomiar t0 liczy
    2 Wyświetlanie t0 nie liczy, wyswietlasz jego zawartość , zerujesz i idziesz do pkt 1

    a t1 liczy cały czas żeby określać czy pomiar czy wyswietlanie

    moja propozycja jest taka: na końcu programu obsługi t1 negujesz tr0; a w funkcji main najpierw sprawdzasz stan tr0 jeśli jest 1 to nie robisz nic , bo liczy, jesli jest 0 to możesz wyświetlić wynik (tu dygresja jak bedziesz to robił przy pmocy 1 diody? chyba coś więcej tam będzie) i wyzerować go, a potem czekać, aż program od t1 znowu ustawi TR0 nie zmieniając stanu wyswietlanego wyniku

    to jest tylko moja propozycja może mozna zrobic lepiej

    powodzenia 73

    aha przez weekend jestem offline
  • Poziom 17  
    Witaj.
    Sprawdzę to o czym piszesz. Co do wyświetlania wyniku, będzie tam LCD, ale to później. Narazie interesuje mnie tylko to czy działa włąśnie ten program, czy liczniki są dobrze poustawiane. Dlatego dla testu chcę wyświetlić na jednej diodzie zliczenie np. 2 impulsów. Nie mogę tylko zrozumieć jednej kwestii, którą napisałeś
    "led2 powinien migać niezależnie od wszystkiego i na moje oko w ten program ma sszanse tak działac ,ale jesli sprawdziłbyś to jeszcze raz dla pewności to byloby dobrze (w main pusta pętla);"
    Nie mtoę tego rozszyfrować o co Ci chodzi tutaj? :)
    Pozdrawiam.
  • Poziom 14  
    chodzi mi o odmierzanie czasu powinno działać niezależnie tzn w main masz tylko ustawienia wstępne tzn tmod i włączenie timera , a potem pusta pętla i obsługa przerwania od czasu to powinno powodować miganie diody led2
  • Poziom 17  
    Więc tak.
    Witam.

    Na końcu T1 zanegowałem zatem TR0 : TR0=!TR0; Dało to tyle, że rzeczywiście T0 nie zlicza już cały czas, tylko jesto to tak:
    Liczy, przerwanie (nieliczy i tutaj ma być wyświetlany wynik), liczy i tak w kółko.
    Jednakże nie wyświetla mnie wyniku wtedy gdy nieliczy (czyli na czas trwania przerwania). Źle pozmieniałem w main? A wygląda to tak:
    while(1)
    {
    int a;
    a=TL0;

    if (a==2)
    {
    if (TR0=0) {
    PortLED2=0;
    TH0=0; //zerowanie licznikow TH0
    TL0=0; //i TL0 przed pomiarem
    }
    }
    }
    Probowalem na różne sposoby, może powinno to wyglądać inaczej?
    Pozdrawiam.

    Dodano po 29 [minuty]:

    Edit: Sprawdziłem to miganie diody LED2, niestety od czasu do czasu ona nie mruga, tak jak piszesz (no chyba, że są to bardzo długie odstepy czasu, teraz mam nastawy przerwanie co ok. 10 sekund).
  • Poziom 14  
    być może znalazłem bląd
    polega on na tym, że w w przerwaniu deklarujesz zmienną count i od razu przypisujesz jej wartość
    pytania są 2:
    czy przypadkiem przy kazdym zgłoszeniu przerwania zmienna nie jest zerowana?
    czy ta zmienna ( a dokładnie komórka pamięci która przechowuje tą zmienną ) nie jest modyfikowana w innym fragmencie programu?
    najprawdopodobniej nie ale spróbuj zadeklarować ten licznik jako zmienną globalną i sprawdź jak działa, bo tylko to budzi moje wątpliwości reszta przerwania powinna działać dobrze
  • Poziom 17  
    Niestety...niepomogło, deklaracja jako zmienna globalna niemiała żadnego wpływu na program.
    Poprostu nie chce działać...pomysły się mnie też kończą.
  • Poziom 17  
    Code:
    #include <8051.h> 
    
    #include <stdio.h>

    #define PortLED  P2_4
    #define PortLED2  P2_5
    #define SECOND 160   //Ok 10 sekund
    static data unsigned char count=0; //bez przyrownania do 0 tez
    //sprawdzalem
    void main(void)
    {   

       TMOD=0x15;
           
       TR0=1;

       TH1 = 0x87;
       TL1 = 0;

       TR1 = 1;

       ET1 = 1;
       EA = 1;
     
       TH0=0;
       TL0=0;

       while(1)
       {
       int a;
       a=TL0;
     
       if (a==2)
          {
             if (TR0=0) {

             PortLED2=0;
             TH0=0; //zerowanie licznikow TH0
             TL0=0;             }//i TL0 przed pomiarem             
          }          
       }
    }
    void T1_int(void) interrupt 3 using 1
       {
       //static data unsigned char count=0;
       TH1 =0x87;
       TL1 =0;

       if (++count==SECOND)
          {
          count =0;
          PortLED=!PortLED;
          TR0=!TR0;//zmiana T0 liczy
          }
       }


    Dodano po 1 [minuty]:

    Zastanawiam się jeszcze nad kwestią przyrównywania a do TH0 jako integer, czy niepowinno być podawane w systemie 0x01 zamiast a =1.
  • Poziom 14  
    Code:
    #include <8051.h>
    
    #include <stdio.h>

    #define PortLED  P2_4
    #define PortLED2  P2_5
    #define SECOND 160   //Ok 10 sekund
    static data unsigned char count=0; //bez przyrownania do 0 tez
    //sprawdzalem
    void main(void)
    {   

       TMOD=0x15;
           
       TR0=1;

       TH1 = 0x87;
       TL1 = 0;

       TR1 = 1;

       ET1 = 1;
       EA = 1;
     
       TH0=0;
       TL0=0;

       while(1)
     { }
    }
     void T1_int(void) interrupt 3 using 1
       {
       //static data unsigned char count=0;
       TH1 =0x87;
       TL1 =0;

       if (++count==SECOND)
          {
          count =0;
          PortLED=!PortLED;
          TR0=!TR0;//zmiana T0 liczy
          }
       }


    a coś takiego sprawdzałeś ?
    to jest tylko obsługa przerwania od T1 , jak to nie działa to nie wiem
    pozdrawiam i życzę powodzenia

    tu co ok 10sekund powinien zmieniać sie stan diody i nic więcej