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

Zliczanie impulsów, Timer, 8051

cristof_w 29 Paź 2007 15:51 9064 58
  • #31 29 Paź 2007 15:51
    cristof_w
    Poziom 17  

    Tak, sprawdzałem ten program dwuetapowo. Sprawdziłem wcześniej to co proponujesz sprawdzić i działa tak jak powinien, didoa świeci co około 10 sekund. Ten kawałek kodu jest zatem prawidłowy, ale reszta też wydaje się być w porządku, jednkaże skoro nie działa, to jakiś diabeł gdzieś tam siedzi.

  • #32 30 Paź 2007 08:52
    arturt134
    Poziom 26  

    Przepraszam, że tak długo się nie odzywałem, ale byłem "wyjechany". Przyszedł mi do głowy jeszcze jeden pomysł. Spróbuj postarać się o jakiś symulator, który potrafi symulować peryferia. Nie jestem pewien, ale chyba IAR potrafi (wersja 30 dniowa do ściągnięcia za darmo z www.iar.se).. Być może ktoś podpowie jakiś inny dobry symulator do 8051.
    Wydaje mi się, że może śledząc działanie programu na symulatorze uda ci się znaleźć przyczynę jego niedziałania.

  • Pomocny post
    #33 30 Paź 2007 10:07
    zumek
    Poziom 39  

    cristof_w napisał:
    ... ale reszta też wydaje się być w porządku, jednkaże skoro nie działa, to jakiś diabeł gdzieś tam siedzi.

    Mi się ten ...
    Code:

    ...
       if (a==2)
          {
             if (TR0=0) {

             PortLED2=0;
             TH0=0; //zerowanie licznikow TH0
             TL0=0;             }//i TL0 przed pomiarem             
          }         
    ...
    ... "diabeł" nie podoba ;)
    Zamiast porównania TR0==0 , masz przypisanie :(
    Co to za kompilator , że nie ostrzega o unreachable code :?:

    Piotrek

  • #34 30 Paź 2007 13:53
    romsik
    Poziom 14  

    witam jestem

    cieszę się, że to działa. Jak to działa to mogę Ci powiedzieć czemu nie działa całość. niepotrzebnie sprawdzasz czy tl0=2 sprawdzaj tylko TR0 i jeśli jest zero to zapal sobie diodę ale inną niż ta od 10sekund. a najlepiej to jeśli tr0=0 to zatrzymaj jeszcze T1 i mrugnij diodą led tyle razy ile jest t0. miganie diody znajdziesz na http://mikrokontrolery.net/8051_c_02.htm (fajny kurs c na 51)
    i ustaw TR1 jak sie "wymiga"
    73 i
    powodzenia :D , a jak cos nie gra to od razu daj kod :)

  • #35 31 Paź 2007 12:41
    cristof_w
    Poziom 17  

    Witam.
    Dwie kwestie.
    1. Do kolegi zumek. Dzięki, bardzo celne spostrzeżenie, patrzyłem na to milion razy i przeoczyłem...
    Mimo tego progam niedziała...
    2. Do kolegi romsik...Chyba trochę namieszałeś, możesz jaśniej?
    Dioda LED służy tylko do tego, żebym mógł spojrzeć czy Timer1 dobrze działa. Dioda LED2 ma za zadanie zapalić się wtedy, gdy zliczone zostaną dwa impulsy. Z tego powodu sprawdzam właśnie TL0, czy minęła już zadana liczba impulsów. Bo skąd inaczej będzie wiadomo, że już zadaną liczbę razy został podany sygnał na T0?? Ja tego nie wiem, dlatego proszę jaśniej.
    Ja nie chcę zatrzymywać Timera1, chcę żeby cyklicznie odmierzał czas, w pierwszych 10 sekundach podaje w tym czasie sygnały na T0, w drugich 10 sekundach wyświetlam. Ot, jak bym chciał, żeby to zadziałało.
    Pozdrawiam.

  • #36 31 Paź 2007 14:50
    romsik
    Poziom 14  

    Witam ponownie!

    Ok co do diod to mój błąd wydawało mi się, że tą samą diodę zmieniasz w funkcji main i w przerwaniu, ale jest ok.
    Jeśli zaś chodzi o zatrzymywanie timera 1 to rozumiem Cię jak ma program działać docelowo. Pytałem kiedyś jak podajesz impulsy na t0 i się nie pochwaliłeś. Jeśli to robisz przez jakiś switch bezpośrednio to drgają styki i licznik zliczy więcej impulsów niż 2( dioda się nie zaświeci, bo nie jest spełniony warunek a==2). stąd moja propozycja, żeby zatrzymać t1, zobaczyć ile policzył t0 (migająca dioda) i z powrotem włączyć t1. to wszystko oczywiście w celach testowych, żeby upewnic się czy program działa tak jak chcesz pozdawiam i powodzenia

  • #37 31 Paź 2007 15:10
    cristof_w
    Poziom 17  

    Więc tak.
    Impulsy podaje za pomocą przycisku, a nie z generatora. W przyszłości będa to impulsy z czujnika, ale narazie to nieistotne.
    Spróbuję się pobawić i napisać tak jak proponujesz. Zobaczymy co z tego wyjdzie, dam znać.

  • #38 04 Lis 2007 19:07
    cristof_w
    Poziom 17  

    Więc tak.
    Z tymi diodami niesprawdzałem (za barszo nie wiem jak), ale tak jak sugerował kolega Artur134, zassałem sobie programik symulujący (inny od tego co polecałeś).
    Tam kod jest przekonwertowany do Assemblera, z którego znam tylko podstawy.
    Zrobiłem krokową pracę programu i zauważyłem w trakcie pracy proramu coś takiego:

    W pewnym momencie dochodzi do nastepujących linijek kodu;

    X: MOV R2, TL0
    Y: MOV R3,#00
    Z: CJNE R2,#02,003F
    I tutaj chyba jest problem...program tutaj się zapętla, cały czas skacze z linijki X do Y i do Z i tak cały czas w kółko. W tym czasie w rejestrze IPTR jest zmiana 3Fh na 41h i na 43h i tak w kółko. Cały czas sprawdzam program krokowo. W innych rejestrach w tym czasie nic się niezmienia.
    Mnie to osobiście nic nie mówi, ale może Wam to coś powie?
    Może teraz będzie znacznie jaśniej rozwiązać ten błąd?
    Pozdrawiam i proszę o wskazówki.

  • #39 05 Lis 2007 08:35
    romsik
    Poziom 14  

    CJNE tłumaczy się jako Compare and Jump if Not Equal czyli porównaj i skocz jeśli różne, porównuje zawartość rejestru R2 z liczbą 2 i wykonuje skok jeśli są różne , MOV R2,TL0 przenosi zawartość TLO do R2 czyli w zasadzie porównujesz TL0 z liczbą 2 wniosek końcowy w TL0 jest liczba różna od 2

    IPTR to pewni Instruction Pointer czyli coś takiego co wyznacza adresy kolejmych rozkazów (po polsku licznik rozkazów lub wskaźnik instrukcji, a in english Program Counter jeszcze to się nazywa)

    sprawdź sobie co pokazuje TL0 ewentualnie co jest w pod adresem 8A (8a to adres TL0 w obszarze SFR (Special Function Registers))

    aha pewnie będzie 0 bo jak się do niego dostaną impulsy jakiekolwiek podajesz coś jakoś na T0 w tym programie (symulatorze ) ?


    i jeszcze moje zdanie na temat symulatorów: są lepsze i gorsze do nauczenia się czegoś na sucho się nadają, ale problemy zaczynają sie właśnie jeśli program ma coś zewnętrznego zliczać czy choćby sprawdzać stan portów

    powodzenia

  • #40 05 Lis 2007 13:35
    cristof_w
    Poziom 17  

    Więc tak.
    Po szybkim kursie Assemblera wiem już o co chodzi w tym kodzie.
    Wartość rejestru TL0 (z wcześniejszych linijek kodu wynika, że jest to 0) jest ładowana do rejestru R2. Do rejestru R3 jest ładowana wartość 0.
    CJNE porównuje zatem, tak jak napisałes, TL0 z argumentem 2 i skacze, gdy są nierówne.
    Zatem skoro cały czas skacze i się zapętla, nigdy te wartości nie będa sobie równe! To przez to, że na TL0 nic nie jest podawane?
    Pytanie, dlaczego??
    Sprawdziłem co jest w rejestrze TL0. Tak jak mówiłeś jest to 0.
    Czy coś to mówi?

    Tylko, niepoznałem się jeszcze dobrze na tym programie i nie wiem jak np. ręcznie wpisać mu wartość. Nie wiem jak ręcznie podać na T0 cokolwiek, musze się jescze pobawić tym programem.

    Dodano po 1 [godziny] 53 [minuty]:

    Zrobiłem jeszcze coś takiego:
    w programie zmieniłem wartość a z 2 na 0 (a==0).
    program "poszedł" dalej, jednakże znowu się dalje zapętla, i znowu skacą pewne wartości w rejestrze IPTR. Dochodzi do SJMP 003F i powraca, i tak cały czas...
    Czyli klapa...
    Jest natomiast pytanie.
    Jak mogę rozumieć wartość 003F w wyrażeniu poniższym
    CJNE R2,#02,003F ? (to jest to co się zapętlał poprzednio).
    Może jeszcze jakieś sugestie odnośnie tego, co może być źle?

  • #41 05 Lis 2007 13:55
    romsik
    Poziom 14  

    SJMP to krórtki skok , a ta wartość w rozkazie CJNE to adres względny zapisany w kodzie U2, taką liczbę trzeba dodac di zawartości IPTR aby uzyskać adres nastepnego rozkazu...tak mówi lista rozkazów (dokumentacja do asemblera), ale w symulatorze to może być adres gdzie ma skoczyć dokładnie. Jeśli po tym rozkazie w IPTR jest taka wartość to tak jest tzn jest to już wyliczony adres

    a to sprawdzałeś miganie)

    efektem ubocznym zajmowania się symulatorem będzie nauczenie się asemblera, :) pozdrawiam

    miganie powoduje miganie diody dołączonej do p1.7 miga z coraz mniejszą częstotliwością

    miganie2 powoduje miganie tej samej diody ilość mignięć jako argument

  • #42 06 Lis 2007 12:53
    cristof_w
    Poziom 17  

    Być może postęp...
    Popełniłem kilka prób, program działa różnie w zasadzie, być może też drgania styków mają na to wpływ.
    Więc tak:
    while(1)

    Code:
       {
    
       int a;
       a=TL0;
       f (a==4)
         {
              {
              migaj(a);
              TH0=0;
              TL0=0;
              }
       }

    W powyższym przypadku dioda zawsze udiłuje mrugać tyle razy, ile wynosi a.
    W poniższym przypadku dioa zawsze mruga raz (niezależnie ile razy podam stan na wejscie T0)
    Code:
    a=TL0;
    
                     migaj(a);
              TH0=0;
              TL0=0;

    Cieszy mnie natomiast to, że T0 zlicza tylko w jednym cyklu 10-sekundowym, a nie w obojętnie którym, tak, żeby można było wyswietlać właśnie w tym drugim cyklu.
    Natomiast nie chce działać to wyswietlanie w drugim cyklu, dioda LED2 zawsze zapala się zaraz po impulsie na wejście T0.
    Nadal nie wiem dlaczego takie kwiatki wychodzą.
    Jeszcze np. w poniższym przypadku
    Code:
    while(1) 
    
       {
       a=TL0;
       }
    }
    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
       
          migaj(a);
          TH0=0;
          TL0=0;
          }
        }

    didoa mruga..............tak, że blokuje Timer, który przestaje działać poprawnie.

  • #43 06 Lis 2007 14:25
    romsik
    Poziom 14  

    cześć
    gdybyś mógł dawać całe programy to byłby pełny obraz tego co robisz

    w tym ostatnim kodzie błąd polega natym, że w programie obsługi przerwania robisz coś co trwa długo (miganie) tak nie można Twój program działa tak, że zaczyna migać, ale mija 10 sekund i znowu zaczyna migać i znowu i takie zapetlenie przerwania
    migaj(a);
    TH0=0;
    TL0=0; ten fragment MUSI być w funkcji main

  • #44 06 Lis 2007 16:06
    cristof_w
    Poziom 17  

    Więc precyzyjnie ku jasności...

    Code:
    void main(void) 
    
    {   

       TMOD=0x15; //ustawienie Timer/Counter
           
       TR0=1; //zalaczenie

       TH1 = 0x87;
       TL1 = 0;

       TR1 = 1; //zalaczenie

       ET1 = 1;
       EA = 1;
     
       TH0=0;
       TL0=0;
       
       while(1)
       {
          a=TL0;
          if (TR0==0)
             {
             migaj(a);
               TH0=0;
               TL0=0;
               }
       }
    }


    Powyżej sam main.
    Powyższy program działa następująco:
    po podaniu sygnału na wejście T0 (nawet tylko jednego sygnału), dioda zaczyna mrugać, jednkaże:
    -mruga nie raz, a kilka razy, czyli niezależnie od ilości sygnałów na wejście T0
    -plusem jest to, że zaczyna mrugrac dopiero w drugim cyklu odliczania Timera (wtedy kiedy T0 już nie liczy), natomiast kolejnym minusem jest to, iż gdy T0 się załączy, nadal mruga, a niepowinno, gdyż w tym okresie ma być kolejne zliczanie impulsów, tak by zostały wyświetlone w następnym okresie.
    Czyli niedziała...

  • #45 06 Lis 2007 16:24
    romsik
    Poziom 14  

    jak na mój gust to nie wyłączasz T1 a powinieneś po to żeby dioda się "wymigała" tzn mignęła tyle razy ile jest w TL0, jest chyba tak program jest w funkcji migaj wtedy mija 10 sekudnd zminia sie co ma sie zminic i on wraca do migania przed migaj (a) daj tr1=0, a po tr1=1, miganie trwac może długo (nie wiesz ile bo styki drgają) i usisz zatrzymać ten timer, jak zmienisz sposób wyswietlania to bedzie sobie mógł pracowqac caly czas

  • #46 06 Lis 2007 16:40
    cristof_w
    Poziom 17  

    Niestety...
    To niepomogło.
    Zauważ, że napisałem iż podam jeden sygnał na wejscie T0, a dioda mruga sobie ile chce, powinna tyle razy, ile sygnałów.

  • #47 06 Lis 2007 16:43
    romsik
    Poziom 14  

    no to w takim razie a nie jest TL0 albo coś innego pokaż CAŁY kod

  • #48 06 Lis 2007 17:02
    cristof_w
    Poziom 17  

    Być może diabeł tkwi w jakimś okrutnym szczególe, którego niemożna się dopatrzyć. Przeciez ten program jest naprawdę trywialny, już nie wiem co jest nie tak...
    Może wychaczę lepszy prgoram symulacyjny i coś to wtedy zmieni. Póki co kod poniżej, może coś zauważysz.

    Code:
    #define PortLED  P2_4 
    
    #define PortLED2  P2_5
    #define SECOND 160   //Ok 10 sekund
    int a;
    unsigned char d=2;

    //Funkcja mrugania diody
     void czekaj(unsigned char x)
     {
     unsigned char a,b;
      for( ; x > 0; x--)
    for(a = 0; a < 255; ++a)

    for(b = 0; b < 255; ++b);
    }
    void migaj(unsigned char x)
    {
    for(; x>0; x--)
    {
    PortLED2=0;
    czekaj (10);
    PortLED2=1;
    czekaj(5);
    }
    }
    ////////////////////////////////////////////////////
    void main(void)
    {   

       TMOD=0x15; //ustawienie Timer/Counter
           
       TR0=1; //zalaczenie

       TH1 = 0x87;
       TL1 = 0;

       TR1 = 1; //zalaczenie

       ET1 = 1;
       EA = 1;
     
       TH0=0;
       TL0=0;
       
       while(1)
       {
          a=TL0;
          if (TR0==0)
             {
             //TR1=0;
             migaj(a);
                               TH0=0;
                               TL0=0;
                               //TR1=1;
               }
       }
    }
    //Przerwanie od Timer1
    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
         
          }
       }
       

  • #49 06 Lis 2007 17:09
    romsik
    Poziom 14  

    2 wątpliwości
    1. typ zmiennej a TL0 jest unsigned char, a"a" inteeger zmień "a" na unsigned char
    2. to chyba jest dobrze ale zmienna a wystę puje w funkcji czekaj i głównej czy się nie mieszają - sprwadzaj po kolei, bo sam chce wiedzieć co jest źle
    gód lak :)

  • #50 06 Lis 2007 17:42
    cristof_w
    Poziom 17  

    Dla bezpieczeństwa zmieniłem zmienną, żeby nie były takie same, zmieniłem także typ zmienniej na unsigned char m; m=TLO;
    Niestety znowu to samo, jak poprzednio, bez znaczenia czy przed i po mrugaj(m) dam TR1=0; i TR1=1. W tym drugim przypadku jest nawet gorzej.

  • #51 06 Lis 2007 18:40
    romsik
    Poziom 14  

    sorry na dzisiaj wysiadam pytaj innych powodzenia i pozdrawiam

  • #52 07 Lis 2007 18:24
    cristof_w
    Poziom 17  

    Uruchomiłem program symulacyjny i mam pewne spostrzeżenia.
    Poniewaz bylo kilka programow, to zaznaczam, ze byl to ten z takim kawalkiem

    Code:
    while(1) 
    
       {
          m=TL0;
          if (TR0==0)
             {
             
             migaj(m);
               TH0=0;
               TL0=0;
               
               }
       }

    I tak.
    Prgoram wykonywal sie krokowo, gdzy doszedl do
    m=TL0;
    if (TR0==0)
    to się zapętlił. Wyjscie nastąpiło dopiero w momencie gdy rejestr TH1 osiągnal wartość FFFF (rósł od 8707 do FFFF).
    Następnie przeszedł do przerwania i znowu do if (TR0==0), (nie do m=TL0.)
    Oczywiscie w tym czasie niebyly podawane impulsy na T0, ale czy tak byc powino, ze sie tam tak zapętla?
    Jeszcze ejdna uwaga. W krokowej pracy prgoramu zauwazyłem, że w przerwaniu
    Code:
    if (++count==SECOND) //wykonuje tutaj
    
          {
          count =0;
          PortLED=!PortLED;
          TR0=!TR0;//zmiana T0 liczy
          PortLED2=1;
          }
       }
       
    /skacze do konca programu
    W ogóle pomija to co jest w powyższej pętli przerwania.
    Niepotrafie impremetnować jeszcze zachowania programu po odczycie rejestru, ale jak na mój gust tak być niepowinno. czy może to być jakaś wskazówka?

    Dodano po 7 [minuty]:

    Nie wiem czy nieznalazłem przyczyny...
    Wiadomo, impulsy podaje na wejscie TIMERA0, czyli na port P3_4.
    Jednakże wyczytałęm gdzieś, że zliczanie ma miejsce wtedy, gdy linia /INT0 jest w stanie wysokim!!.
    W programie w ogóle linia /INT0 nie jest sterowana.
    Czy to może być prawda? Może ktoś to potwierdzić?

  • #53 08 Lis 2007 14:47
    Michal19881
    Użytkownik obserwowany

    a nie lepiej napisac ten prgram w asemblerze tego mikrokontrolera?
    mysle ze za odliczanie do tylu bedzie odpowiadala instrukcja djnz

  • #54 08 Lis 2007 16:46
    snow
    Poziom 28  

    Michal19881 napisał:
    a nie lepiej napisac ten prgram w asemblerze tego mikrokontrolera?


    A dlaczego lepiej? A może lepiej napisać w kodzie binarnym? C jest tak samo dobry jak inne.

  • #56 08 Lis 2007 18:32
    cristof_w
    Poziom 17  

    Siędzę nad tym raczej nietrudnym programem już trochę...piszę go w C i niezamierzam przechodzić w trkacie na Assembler, zwłaszcza, że znam go za słabo.
    Macie może jeszcze jakieś pomysły jaki diabeł w nim siedzi?
    Znalazłem w ksiażce program, w którym zawartość Timera0 jest wyświetlana jako 16 bitów (na 16 diodach) i nie ma w tym żadnej filozofii!!
    LEDS=~TL0;
    więc dlaczego nie chce wyświetlać odpowiedniej ilości mrugnięć diody? Może dlatego, że TL0 jest bajtem i on się gubi przy porównaniu m=TL0 i wyświetla to jakoś inaczej?
    Pozdrawiam.

  • #57 09 Lis 2007 10:19
    romsik
    Poziom 14  

    Code:
     a=TL0;
    
          if (TR0==0)
             {
             //TR1=0;
             migaj(a);
                               TH0=0;
                               TL0=0;
                               //TR1=1;
               }



    chyba wiem co jest.!
    program działa tak:
    na poczatku jest ok
    t0 zlicza impulsy t1 liczy czas
    t1 odliczył czas i negujemy TR0 (a powinno być TR0=0)
    skoro TR0==0 to w main może wejść do migaj i wchodzi
    miga jak powinien ale jak się wymiga to TR0 dalej jest zero i znowu tu wchodzi i zaczyna migać z niewiadamo mi na razie z jakim m. dlatego tak jak pisałeś po zatrzymaniu T1 jest jeszcze gorzej. Moja propozycja jest taka:

    na końcu przerwani TR0=0 zamist TR0=!TR0
    a w main
    Code:
     m=TL0;
    
          if (TR0==0)
             {
             TR1=0;
             migaj(a);
                               TH0=0;
                               TL0=0;
                              TH1 =0x87;// to po to żeby t1 zaczął liczyć od razu z dobry ustawieniami możliwe ,że to nie jest konieczne
                               TL1 =0;
                               TR0=1; // i tu jest nasz diabeł nie pozwalamy tym sposobem na kolejne miganie
                               TR1=1;// niech znowu odmierza czas :)

               }




    sprawdź to i powodzenia

    do kolegi ostryas jakbyśmy się tak znali natym :) to by ten wątek nie był taki długi :(

    rada moja jak zawsze uruchamiaj jak najmniejsze fragmenty

  • #58 09 Lis 2007 17:49
    cristof_w
    Poziom 17  

    No cóż...
    Cieszę się, że miałeś koncepcje, ale niestety znowu klapa...
    Program w ogóle się wysypuje...mruga w nieskończoność.
    W teorii ładnie to wszystko wygląda.
    Czy testowałeś może ten proram w symulatorze?

  • #59 12 Lis 2007 09:52
    romsik
    Poziom 14  

    właśnie uruchomiłem środowisko keila deneruję sie tylko na takie przypisanie P1^2 =0;
    on odpowiada:
    error c141: syntax error near '='
    czego on chce?

    Dodano po 24 [minuty]:

    poradzłem sobie z tym