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

Pętle w C, wielokrotne wykonywanie instrukcji if.

10 Maj 2008 14:52 3149 33
  • Poziom 15  
    Witam.

    To moje początki w programowaniu w C. Chcę, aby pierwsza instrukcja if wykonała się 800 razy, po czym przez kolejne 800 wykonywana była druga instrukcja if. Czynności te miałyby powtarzać się cyklicznie. Będę bardzo wdzięczny za pomoc.

    Code:
    #include  <intrinsics.h> 
    
    #include  <msp430x20x3.h>

    unsigned int counter1=3, counter2=100 ,counter3=150 ,counter4=200;
    int k;

    #define PER1  3
    #define PER2  100
    #define PER3  150
    #define PER4  200
    void main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;
      BCSCTL1 = CALBC1_16MHZ;
      DCOCTL = CALDCO_16MHZ;
      BCSCTL2 = DIVS_3;
      P1DIR |= 0x1E;
      TACCR0 = 3;
      TACCTL0 = CCIE;
      TACTL = TASSEL_2 + MC_2 + ID_2;
        __enable_interrupt();
      while(1);
    }
    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A (void)
    {
      int temp;
      temp = TAR;
      if(counter1 == temp)
      {
        k = 6;
        P1OUT ^= 0x02;
        counter1 = temp + k;
        k += 3;
      } 
      if ( counter1 == temp )
      {
        k = 2403;
        P1OUT ^= 0x02;
        counter1 = temp -k;
        k -= 3;
      } 
      TACCR0 += 3;
    }
    [3.12.2020, webinar] Zagadnienia pomiarowe w nowoczesnej inżynierii materiałowej. Zarejestruj się
  • Poziom 25  
    a słyszałeś o pętli for? albo o while?
  • Poziom 15  
    Słyszałem o obydwu. Myślisz,że to będzie działać? :
    Code:
    #include  <intrinsics.h> 
    
    #include  <msp430x20x3.h>

    unsigned int counter1=3, counter2=100 ,counter3=150 ,counter4=200;
    int k;

    #define PER1  3
    #define PER2  100
    #define PER3  150
    #define PER4  200
    void main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;
      BCSCTL1 = CALBC1_16MHZ;
      DCOCTL = CALDCO_16MHZ;
      BCSCTL2 = DIVS_3;
      P1DIR |= 0x1E;
      TACCR0 = 3;
      TACCTL0 = CCIE;
      TACTL = TASSEL_2 + MC_2 + ID_2;
        __enable_interrupt();
      while(1);
    }
    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A (void)
    {
      int temp;
      temp = TAR;
      for (m=1, m <= 1600, m++)

      if(counter1 == temp | m <= 800)
      {
        k = 6;
        P1OUT ^= 0x02;
        counter1 = temp + k;
        k += 3;
      }
         
      if ( counter1 == temp | m >=800 )
      {
        k = 2403;
        P1OUT ^= 0x02;
        counter1 = temp -k;
        k -= 3;
      } 
     if ( m == 1600)
     {
       m = 1;
     }

      TACCR0 += 3;
    }
  • Poziom 25  
    Brakuje nawiasów klamrowych dla sekcji pętli for, poza tym źle postawiony jest warunek dla pętli
  • Poziom 42  
    O ile nawiasy nie są konieczne (po prostu będzie wykonywana tylko pierwsza instrukcja, a więc cały if) to skłądnia polecenia for jest błedna - rozdziela się średnikami, nie przecinkami, które służą do rozdzielania poleceń w ramach "sekcji" (bardzo rzadko używane).

    Ponadto przy takim zapisie warunki powinny zawierać mnożenie logiczne, a nie sumę. A czy nie lepiej napisać dwie pętle?
  • Poziom 15  
    Dlaczego warunek dla pętli był źle postawiony?

    Cytat:
    Ponadto przy takim zapisie warunki powinny zawierać mnożenie logiczne, a nie sumę.
    Chcę aby zawartość instrukcji if wykonała się tylko wtedy gdy obydwa warunki są prawdziwe.

    Mój obecny problem to chciałbym wykonywać pętlę for w nieskończoność. w poniższym programie. Jak to zrobić?


    Code:
    #pragma vector=TIMERA0_VECTOR 
    
    __interrupt void Timer_A (void)
    {
      int temp;
      temp = TAR;
      int k;
     
       k = 6;

         for (m=1; m <= 1600, m++)
         {

            if(counter1 == temp | m < 800)
            {
       
              P1OUT ^= 0x02;
              counter1 = temp + k;
              k += 3;
            }
          
             if ( counter1 == temp | m =800 )
            {
             P1OUT ^= 0x02;
                     k = 2403;
            }
     
            if ( counter1 == temp | m >800 )
            {
                 P1OUT ^= 0x02;
              counter1 = temp -k;
              k -= 3;
            } 
     
     
        }

    }
      TACCR0 += 3;
    }
  • Poziom 25  
    for(;;;){}; powinien się wykonywać w nieskończoność, albo możesz dać while(true){};
  • Pomocny post
    Poziom 42  
    czemu nie tak:
    Code:

    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A (void)
    {
      int temp;
      temp = TAR;
      int k;
     
       k = 6;
       for(;;)
       {
         for (m=1; m <800[b];[/b] m++)
         {

            if(counter1 == temp)
            {

              P1OUT ^= 0x02;
              counter1 = temp + k;
              k += 3;
            }
       }   
          if ( counter1 == temp)
         {
          P1OUT ^= 0x02;
                  k = 2403;
         }
     
         for (m=1; m <800; m++)
         {
            if ( counter1 == temp)
            {
                 P1OUT ^= 0x02;
              counter1 = temp -k;
              k -= 3;
            }
     
     
        }
      }
    }
      TACCR0 += 3;
    }
  • Poziom 15  
    Dzięki. Chyba mam już to czego szukam.

    Dodano po 16 [minuty]:

    Czy pętla for( ; ; ) spowoduje,że pętla for poniżej będzie resetowała się po każdych 1600 przebiegach?
  • Poziom 42  
    pętla for( ; ; ) oznacza pętlę nieskończoną. Nie wiem, co rozumiesz pod pojęciem "resetowania pętli". są dwie pętle wykonywane 800 razy rozdzielone jednym poleceniem i ta sekwencja będzie powtarzana w nieskończoność.
  • Poziom 15  
    Pod pojęciem resetowania pętli chciałem wykonywać dwie pętle na przemian. Każda z tych pętli wykonywałaby się 800 razy. Czy pętla nieskończona for ( ; ; ) zapewni to?
  • Poziom 28  
    Może powinieneś po zakończeniu jednej pętli zmieniać stan flagi na inny i badając ją stwierdzać którą aktualnie ma wykonywać
  • Poziom 15  
    Hmm,więc co zmienić w poniższym kodzie tak aby pętla for wykonywała się od 1 do 1600 i ponownie od 1 do 1600 itd.


    Code:
    #pragma vector=TIMERA0_VECTOR 
    
    __interrupt void Timer_A (void)
    {
      int k,temp;
      temp = TAR;
      long int var;
      int aux = 0;
      if ( temp == 65535 )
      {
       aux = aux + 1;
      }
      var = temp + 65535 * aux;
      for ( ; ; )
       {
     
       k = 6;

         for (m=1; m <= 1600, m++)
         {

            if(counter1 == var | m < 800)
            {
       
              P1OUT ^= 0x02;
              counter1 = var + k;
              k += 3;
            }
          
             if ( counter1 == var | m = 800 )
            {
             P1OUT ^= 0x02;
                     k = 2403;
            }
     
            if ( counter1 == var | m > 800 )
            {
                 P1OUT ^= 0x02;
              counter1 = var + k;
              k -= 3;
            }
                    if ( counter1 == var | m = 1600)
                    {
                    TAR = 0;
                    aux  = 0;
                    }
            }
       }
    }
      TACCR0 += 3;
    }


    Jak zabrać się do ustawiania tych flag? Jestem początkujący w programowaniu.

    pozdrawiam[/quote]
  • Pomocny post
    Poziom 34  
    Każdy coś dopowie, ale nikt nie zauważy, że kod jest jako wektor przerwania. Przecież jak tam będzie pętla nieskończona, to się kod zawiesi na nieustannym sprawdzaniu po jednym tyknięciu. Wartość rejestru TAR jest odczytywana tylko raz (nie wiem od czego jest ten rejestr, ale wpływa na wartość zmiennej "var", która później się nie zmienia przez co praktycznie wszystkie warunku szlak trafia).
    Jeśli ma przypadać jedno sprawdzenie warunku if na jedno zdarzenie od timera, to można dodać licznik w zmiennej, który będzie się zwiększał modulu 1600 i w zależności od wartości wybierać warunek do sprawdzenia.
  • Poziom 15  
    Dlaczego kod miałby się zawiesić po jednym tyknięciu? W kodzie zamieszczonym wyżej do przerwania wchodzę co 3 takty zegara. Otrzymuję to dzięki instrukcji:

    Code:
    TACCR0 += 3; 
    
    W związku z tym wartość TAR jest odczytywana przy każdym wejściu w przerwanie.
    Rejestr TAR przechowuje liczbę przejść "down-to-high" jego wejściowego zegara.

    Ostatnim pomysłem było to by wejść do przerwania tylko raz a następnie porównywać "złapaną" na początku przerwania wartość TARu z zadeklarowanymi przez siebie zmiennymi.

    Wcześniejszy problem już rozwiązałem biorąc zawartość obsługi do zawartości pętli while(1). Obecnym problemem jest to,że program pada po kilku,kilkunastu lub kilkudziesięciu przebiegach.

    Code:
    #include  <intrinsics.h> 
    
    #include  <msp430x20x3.h>

    volatile long unsigned int counter1=3;
    int delta=6,m;
    unsigned int temp; 
    long int var;
    int aux = 0;

    void main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;
      BCSCTL1 = CALBC1_16MHZ;
      DCOCTL = CALDCO_16MHZ;
      BCSCTL2 = DIVS_3;
      P1DIR |= 0x1E;
      TACCR0 = 3;
      TACCTL0 = CCIE;
      TACTL = TASSEL_2 + MC_2 + ID_3; // SMCLK- Timer_A input, continuous mode, clock divider-8
        __enable_interrupt();
       
      while(1);
    }
    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A (void)
    {
    while(1)
    {
     for (m=1; m <= 1600; m++)
      {
        temp = TAR;
        if ( TAR == 65535 )
         {
         aux = aux + 1;
        }
         var = temp + 65535 * aux;
         
         if((counter1 == var) && (m < 800))   
               {
       
                P1OUT ^= 0x02;
                counter1 = var + delta;
                delta += 3;
               }
     
        if (( counter1 == var ) && ( m >= 800 )) 
               {
                P1OUT ^= 0x02;
                counter1 = var + delta;
                delta -= 3;
               }

        if ( (counter1 == var) && (m == 1600))
               {
               TAR = 0;
               aux  = 0;
               counter1 = 3;
               delta = 6;
               }
      }
    }
    }
  • Poziom 20  
    Niestety BoskiDialer ma rację. co z tego, że do przerwania chesz wchodzić co ileś, jeśli nigdy z niego nie wychodzisz.
  • Poziom 15  
    Cytat:
    Zdefiniuj pojęcie "pada"


    Do analizy programu używam breakpointów dzięki którym obserwuję wartość używanych zmiennych w wybranym przez siebie punkcie programu. Przed chwilą program wykonywał się poprawnie do momentu gdy:
    counter1=30,var=30,delta=15,temp=30. Obserwacja kolejnego fragmentu wykonywania się programu jest już jednak niemożliwa. Nie rozumiem tym bardziej, że opisana sytuacja występuję przy różnych wartościach wspomnianych zmiennych.

    Do przerwania wchodzę raz. Mimo to program powinien działać. Nie mówię, że jest to jedyne rozwiązanie tego problemu.

    pozdrawiam
  • Pomocny post
    Poziom 34  
    Zastosowanie timera samo przez się (chyba, że jest inaczej) jest znakiem, ze czynności okresowe mają być wykonywane przy poszczególnych tyknięciach a nie hurtowo 1600 sprawdzeń po jednym tyknięciu lub co gorsza cały czas. Kod z trzeciego postu jest chyba najbliższy oczekiwaniu, tylko usunąć z niego linijkę z pętlą która powtarza pierwszy warunek, oraz dać zwiększanie zmiennej m. Według mnie całość powinna wyglądać jakoś tak:
    Code:

    // [...]
    int m = 0;
    // [...]

    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A (void)
    {
       int temp = TAR;

       if(m < 800)
       {
          // warunek pierwszy (wykonywany, dla m od 0 do 799)
    /*
          if(counter1 == temp)
          {
             k = 6;
             P1OUT ^= 0x02;
             counter1 = temp + k;
             k += 3;
          }
    */   
       } else
       {
          // warunek drugi (dla m od 800 do 1599)
    /*
          if(counter1 == temp)
          {
             k = 2403;
             P1OUT ^= 0x02;
             counter1 = temp -k;
             k -= 3;
          } 
    */
       }
       
       if(++m == 1600)
          m = 0;

       // to nie wiem po co
       TACCR0 += 3;
    }

    Wtedy jest po jednym sprawdzeniu na jedno tyknięcie od timera, przez pierwsze 800 tyknięć jest sprawdzany warunek pierwszy, 800 warunek drugi i znów pierwszy..
  • Poziom 15  
    Cytat:
    czy któraś konkrętna pętla się zawiesza, czy po prostu któraś z linijek definitywnie ulega zapętleniu się samej w sobie?


    Może opiszę mój pomysł i wykonanie nieco bardziej dokładnie. Zmienna temp służy do przechwytywania wartości TAR na samym początku pętli ( TAR zlicza niezależnie od tego co dzieję się w napisanym programie). Pierwszy warunek if w którym użyta jest zmienna aux nie jest używany w pierwszym etapie wykonywania się programu, więc tu nie ma problemu. Pierwsze wykonanie zawartości drugiego warunku if następuję dla counter1=3, kolejne dla counter1=9,18,30 itd. Osiągnąłem to dodając counter1 do delta w każdym wejściu w ten warunek. Program zawsze przestaje działać właśnie w tym warunku ( drugim warunku if) po kilku,kilkunastu lub kilkudziesięciu przebiegach. Hmm, zaraz spróbuję usunąć zmienną temp i robić porównanie bezpośredno do TAR ( w końcu i tak cały czas jestem wewnątrz obsługi przerwania).

    Cytat:
    Zastosowanie timera samo przez się (chyba, że jest inaczej) jest znakiem, ze czynności okresowe mają być wykonywane przy poszczególnych tyknięciach a nie hurtowo 1600 sprawdzeń po jednym tyknięciu lub co gorsza cały czas.

    W ostatnim programie, który wkleiłem każde tyknięcie TAR, w zależności od częstotliwości wejściowego zegara licznika, przypada na kilka,kilkanaście przebiegów pętli z 1600 przejściami.

    To programowanie mikrokontrolera Texas Instruments. Szkoda,że oprogramowanie nie jest ogólnie dostępne.

    pozdrawiam
  • Pomocny post
    Poziom 34  
    W poście z "01 Cze 2008 21:22:59" jest kilka błędów.. po pierwsze nie można liczyć na to, że wstrzelisz się dokładnie w wartości od timera.. warunek na powiększenie aux powinien być taki, że jeśli odczytana wartość jest mniejsza niż ostatnia odczytana, to wtedy zwiększasz aux (uniezależniasz się od konkretnej wartości 65535) podobnie jest z warunkami counter1==var - jeśli TAR będzie rosnął zbyt szybko, to warunek nie zostanie spełniony (i już nie będzie spełnialny, ponieważ counter1 nie jest zmieniany) i się kod zablokuje.. tutaj dał bym warunek counter1<=var. Dodatkowo jeśli masz pętlę nieskończoną, to czemu nie przeniesiesz kodu do funkcji main()?
  • Poziom 15  
    Przepraszam za opóźnienie w odpowiedzi.

    Cytat:
    po pierwsze nie można liczyć na to, że wstrzelisz się dokładnie w wartości od timera..


    W ostatnim z wklejonych przeze mnie programów okres sygnału na wejściu licznika to 4us. Okres sygnału taktującego CPU to 62.5 ns a wykonanie każdej instrukcji zajmuje od 1 do 6 cykli tego sygnału. Dlatego w pierwszych 800 przebiegach pętli for dla określonej wartości TAR zawsze wykona się ten fragment programu:


    Code:
    {
    
        temp = TAR;
        if ( temp == 65535 )
         {
         aux = aux + 1;
         }
         var = temp + 65535 * aux;
         
         if((counter1 == temp) && (m < 800))   
               {
       
                P1OUT ^= 0x02;
                counter1 = var + delta;
                delta += 3;
               }


    czyli każda kolejna wartość TAR tzn.1,2,3,4,5 itd. będzie zawsze sprawdzana w tym warunku:
    Code:
    if((counter1 == temp) && (m < 800))
    .Być może nadal czegoś nie rozumiem.
    Cytat:
    Dodatkowo jeśli masz pętlę nieskończoną, to czemu nie przeniesiesz kodu do funkcji main()?



    Masz rację. Nie ma sensu robić tego w przerwaniu.
  • Pomocny post
    Poziom 34  
    Co do wstrzeliwywania się to jest moje myślenie paranoiczne, że zawsze coś może pójść nie tak, lub - jeśli przeniesiesz to do pętli main - pojawi się przerwanie które by zajęło procek na dłuższy czas, to mimo tego program zareaguje poprawnie lub przynajmniej się nie zawiesi. Gdybyś zamienił warunek na zwiększenie aux, to przy okazji usunął byś błąd, gdyż jeśli zwiększasz aux przy temp==65535, to zmienna "var" zmienia wartość tak:
    - 0x0FFFE
    - 0x1FFFF (aux został zwiększony za szybko)
    - 0x1000
    w efekcie "var" zmienia się niemonotonicznie, a pewnie nie tego oczekiwałeś. Ogólnie zawsze lepiej myśleć, że coś może pójść nie tak i że możesz nie wstrzelić się z warunkiem.

    (edit)

    Po krótkim ponownym przeczytaniu tematu i rozmyślaniom doszedłem do wniosku, że nie chodzi o to, aby 800 razy sprawdzić spełnialność warunku (gdyż na efekt działania miał by wpływ wynikowy kod) tylko raczej oczekiwanie tak długo, aż warunek będzie spełniony 800 razy - potem następny.. Wtedy kod mógł by wyglądać mniej więcej tak:
    Code:

    void main(void)
    {
       [...]
       volatile long unsigned int counter1=3;
       int delta=6, m;
       long int var = 0;
       while(1)
       {
          // obliczenie przyrostu wartości TAR, zwiększenie wartości var
          var += (TAR - var) & 0xFFFF;

          // jeśli upłynęło dość czasu - jakaś tam operacja
          if(counter1 <= var)
          {
             // część wspólna
             P1OUT ^= 0x02;
             // wyznaczenie następnego momentu w oparciu o ostatni czas, dzięki temu
             // kod się synchronizuje z timerem a nie wykorzystuje go do odmierzania czasu
             counter1 += delta;
             
             // część różna
             if(m < 800)
                delta += 3;
             else
                delta -= 3;

             // zwiększenie m oraz sprawdzenie czy to jest przypadek końcowy. jeśli tak - reinicjalizacja cyklu
             if(++m >= 1600)
             {
                m = 0;
                TAR = 0;
                var = 0;
                counter1 = 3;
                delta = 6;
             }
          }
       }
  • Poziom 15  
    Rozumiem już swój błąd w wawrunku na zwiększanie aux. Co myślisz o takim rozwiązaniu:
    Code:
    temp = TAR;
    
        if ( temp == 0 )
         {
         aux = aux + 1;
         }
         var = temp + 655356 * aux;


    Rozumiem też cel zastosowania warunku counter1<=var.

    Jaki ma cel następująca operacja?
    Code:
    var += (TAR - var) & 0xFFFF;


    [/code]

    Dodano po 20 [minuty]:

    Mam problem z debugowaniem, wiec nie moge poki co przetestowac programu z wprowadzonymi zmianami, ale wydaje sie ze problem tkwil w warunku counter1== var zamiast counter1<=var.
  • Pomocny post
    Poziom 34  
    Nowa propozycja jest lepsza, ale jeśli pobierzesz TAR przy wartości zero, to zwiększysz aux przez co wartości "var" zaczną się od 65536.
    Co do kodu:
    Code:
    var += (TAR - var) & 0xFFFF;

    to jest to właśnie zwiększanie "var" pozbawione wszelkich błędów. Najpierw jest liczony przyrost wartości TAR od ostatniej wartości (wszystko na prawo od +=) poprzez odjęcie od TAR wartości "var" i zamaskowanie. wtedy jeśli masz np var==0x1000 a TAR==0x1005, po prawej stronie wyjdzie wartość 5, po dodaniu do var otrzymasz 0x1005. Dla var=0x1FFF0 i TAR==0x000F różnica wyjdzie 0x001F (po zamaskowaniu), po dodaniu var==0x2000F. Ogólnie zawsze można łatwo policzyć przyrost wartości pomimo przepełnienia licznika (jeśli licznik się przepełni, to przy odejmowaniu też powstanie przepełnienie ostatecznie dając poprawną wartość) a dzięki temu można łatwo aktualizować wartość zmiennej var.
  • Poziom 15  
    Taki pomysł na zwiększanie "var" to idealne rozwiązanie dla mojego programu, który działa coraz lepiej.

    Mam jeszcze dwa problemy. Mimo, że okres sygnału wejściowego licznika ma 4us zaś okres sygnału taktującego CPU to 62.5ns, wykonanie jednego przbiegu pętli "for" zajmuje więcej niż 1 takt zegara licznika. Wykonanie każdej instrukcji to od 1 do 6 cykli a dla pierwszych 800 przebiegów wykonuje się niewielki fragment programu jak poniżej plus dwie linijki:
    Code:
    temp = TAR;
    
        var += (TAR - var) & 0xFFFF;
         
         if((counter1 <= var) && (m < 800))   
               {
       
                P1OUT ^= 0x02;
                counter1 = var + delta;
                delta += 3;
               }


    Drugi problem to warunek resetujący counter1, delta oraz TAR dla 1600 przebiegu pętli "for" nigdy się nie wykonuje bo counter1 i delta zwiększają się monotonicznie dla kolejnych przebiegów tej pętli.

    Całość obecnego programu wygląda tak:
    Code:
    #include  <intrinsics.h> 
    
    #include  <msp430x20x3.h>

    long unsigned int counter1=3;
    int delta=6,m;
    unsigned int temp; 
    long int var;
     
    void main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;
      BCSCTL1 = CALBC1_16MHZ;
      DCOCTL = CALDCO_16MHZ;
      BCSCTL2 = DIVS_3;
      P1DIR |= 0x1E;
      TACTL = TASSEL_2 + MC_2 + ID_3;
       
      while (1)
    {
     
     for (m=1; m <= 1600; m++)
      {
        temp = TAR;
        var += (TAR - var) & 0xFFFF;
         
         if((counter1 <= var) && (m < 800))   
               {
       
                P1OUT ^= 0x02;
                counter1 = var + delta;
                delta += 3;
               }
     
        if (( counter1 <= var ) && ( m >= 800 ) && (m != 1600)) 
               {
                P1OUT ^= 0x02;
                counter1 = var + delta;
                delta -= 3;
               }

        if ( (counter1 == var) && (m == 1600))
               {
               TAR = 0;
               //aux  = 0;
               counter1 = 3;
               delta = 6;
               }
      }
       

    }
  • Pomocny post
    Poziom 34  
    nie musisz już odczytywać TAR do temp'a, wystarcza jeden odczyt przy aktualizowaniu zmiennej "var". Przy warunku zerującym - tam też wstaw nierówność counter1 <= var. Przy okazji można wtedy zauważyć, że żeby którykolwiek z tych trzech if'ów był spełniony, musi być spełniony warunek if(counter <= var) a więc można go wyciągnąć tak jak ja to zrobiłem w poście z piątku.

    Powiedz jeszcze, czy warunek if((counter1 <= var) && (m < 800)) i if (( counter1 <= var ) && ( m >= 800 ) && (m != 1600)) mają być sprawdzone po 800 razy czy kod odpowiadający tym warunkom ma być wykonany po 800 razy. Jeśli warunki mają być sprawdzone po 800 razy, to twój kod jest bliższy poprawności, ale w to wątpie, bo wtedy długość wykonywania jednej iteracji będzie miała wpływ na działanie programu (np z 800 sprawdzeń kod do warunku pierwszego będzie sprawdziny 800 razy, ale spełniony tylko 174 [np] razy). Jeśli warunki mają być spełnione po 800 razy, to mój kod jest bliższy poprawnemu. Tak wiec chodzi o 800 krotne sprawdzenie czy spełnienie warunku?

    Kolejna sprawa, to aktualizowanie zmiennej counter1 - zdecydowanie odradzam w tym przypadku wyliczanie nowej wartości względem "var" na korzyść wykorzystania starej wartości. Jeśli poślizg wykonywania się pętli będzie znaczący np licznik zdąży się zwiększyć dwa razy, to następnym razem warunek będzie spełniony po delta tyknięciach licząc od teraz (to jest odmierzanie) a nie od momentu, kiedy naprawdę powinien być (to jest synchronizowanie z mojego postu z piątku). Błąd wyrównania będzie się kumulował w ostateczności sygnał wyjściowy będzie miał duży rozrzut względem sygnału oczekiwanego (może się wydłużać)
  • Poziom 15  
    W moim programie chcę w jak najprostszy sposób określać liczbę zmian stanu wyjściowego bitu więc chyba wygodniej będzie wykorzystać Twoją wersję kodu czyli kod odpowiadający poszczególnym warunkom ma być wykonany po 800 razy.

    Wyłączyłem zmienną var z wyliczania nowej wartości counter1. Dla pierwszych 1500 przebiegów pętli for program poniżej działa dokładnie tak jak chcę. Problemy występują przy resetowaniu.

    Jak działa następująca operacja?
    Code:
    if(++m >= 1600)


    Obecny program:
    Code:
    #include  <intrinsics.h> 
    
    #include  <msp430x20x3.h>

    long unsigned int counter1=3;
    int delta=6,m;
    unsigned int temp; 
    long int var;
     
    void main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;
      BCSCTL1 = CALBC1_16MHZ;
      DCOCTL = CALDCO_16MHZ;
      BCSCTL2 = DIVS_3;
      P1DIR |= 0x1E;
      TACTL = TASSEL_2 + MC_2 + ID_3;
       
      while (1)
    {
     
     for (m=1; m <= 1600; m++)
      {
       
        var += (TAR - var) & 0xFFFF;
         
         if(counter1 <= var)   
               {
               
                P1OUT ^= 0x02;
                counter1 += delta;
               
                if ( m < 800 )
                   {
                    delta += 3;
                   }
                if (( m > 800) && (m != 1600))
                  {
                    delta -=3;
                  } 
               }
     
        if  ( m == 1600 ) 
               {
                 TAR = 0; 
                 counter1 = 3;
                 delta = 6;
                 m = 0;
                }

      }
       

    }