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

O co chodzi w tym kodzie?

AsKeR 12 Sty 2010 23:42 1412 6
  • #1 7527576
    AsKeR
    Poziom 11  
    Mam problem ze zrozumieniem programu z książki "Mikrokontrolery Avr W Praktyce" (Doliński).

    /****************************************************************/
    /* Ćwiczenie 6 - Zastosowanie komparatora analogowego do budowy */
    /*               przetwornika analogowo-cyfrowego.              */
    /*               Wyzwalanie funkcji przechwytywania timera1     */
    /*               za pomocą komparatora.                         */
    /*               Przerwanie od przechwytywania.                 */
    /*               Obsługa wewnętrznej pamięci EEPROM.            */
    /* J.D. '2003                                                   */
    /****************************************************************/
    #include <io.h>
    #include <interrupt.h>
    #include <signal.h>
    #include <eeprom.h>
    
    //********************  zmienne globalne  *******************
    unsigned char liczt0;
    volatile unsigned char pomiar;    //flaga dokonania pomiaru
    union{
          unsigned int wspkal;        //współczynnik kalibracji
          unsigned char wspkalb[2];
          }uwspkal;
    
    void czekaj(unsigned long zt) //procedura wytracania czasu
    {
     #define tau 10.38
     unsigned char zt1;
     for(;zt>0;zt--)
     {
      for(zt1=255;zt1!=0;zt1--);
     }
    }
    
    SIGNAL (SIG_INPUT_CAPTURE1)  //obsługa przerwania od przechwycenia
    {
     union{
           unsigned int czas;
           unsigned char czasb[2];
          }uczas;
     unsigned char czas8;
    
     uczas.czasb[0]=ICR1L;       //zatrzaśnij rejestry przechwytywania
     uczas.czasb[1]=ICR1H;
     czas8=~((uczas.czas/uwspkal.wspkal)<<2);   //normalizacja wyniku 
                       //do postaci 6-bitowej liczby binarnej przesuniętej o 2 bity 
                       //w lewo (PORTB1 i 0 są wykorzystywane przez komparator
                       //analogowy)
     PORTB=(PORTB&0x03)|czas8;   //wyświetl wynik na LEDach
     pomiar=1;                   //pomiar dokonany (zapal flagę)
     sbi(PORTD,4);               //zacznij rozładowywać kondensator pomiarowy
    }
    
    int main(void)
    {
     DDRD=0x13;       //PORTD we oprócz PD4, PD1 i PD0 - wy
     PORTD=0xff;      //z podciąganiem
     PORTB=0x01;      //PB0 z podciąganiem
     DDRB=0xfc;       //PORTB7-2 - wy, PORTB1-0 - we
     TCCR1A=0;        //funkcje porównania i PWM wyłączone
     TCCR1B=0x41;     //preskaler XTAL/1 dla TC1, przechwytywanie na
                      //narastającym zboczu
     TIMSK=0x08;      //zezwolenie na przerwania od przechwytywania
     ACSR=1<<ACIC;    //zezwolenie na wyzwalanie przechwytywania komparatorem
     czekaj(10*tau);
     TIFR=0xff;       //kasuj przerwania od timerów
     
     if(bit_is_clear(PIND,1))
     {             //wciśnięty SW4 - kalibracja
      do
      {
       cbi(PORTD,4);        //ładuj kondensator pomiarowy
       TCNT1H=0;      //zeruj licznik 1 pomiar czasu ładowania
       TCNT1L=0;
       sbi(TIFR,ICF1);
       while(bit_is_clear(TIFR,ICF1));    //czekaj aż napięcie mierzone zrówna się z napięciem
                                          //wejściowym
       uwspkal.wspkal=(ICR1L+256*ICR1H);
       sbi(PORTD,4);
       czekaj(1*tau);          //opóźnienie związane z częstotliwością odświeżania
      }while(bit_is_set(PIND,0));
      uwspkal.wspkal/=64;
      eeprom_wb(1,uwspkal.wspkalb[0]);  //zapisz współczynnik kalibracji 
      eeprom_wb(2,uwspkal.wspkalb[1]);  //do pamięci EEPROM
      sbi(TIFR,ICF1);
     }
     else
     {
      uwspkal.wspkal=eeprom_rw(1);  //odczytaj współczynnik kalibracji z EEPROM-u
     }
     sei();                //odblokuj globalne przerwania
     while(1)              //główna pętla pomiarowa
     {
      cbi(PORTD,4);        //ładuj kondensator pomiarowy
      TCNT1H=0;            //zeruj licznik 1 - pomiar czasu ładowania
      TCNT1L=0;
      pomiar=0;
      while(pomiar==0);    //czekaj aż napięcie mierzone zrówna się z napięciem
                           //na kondensatorze pomiarowym
      czekaj(23*tau);      //opóźnienie związane z częstotliwością odświeżania
                           //wskaźnika LED
     }
    }
    
    



    Nie rozumiem dokładnie o co chodzi w następujących liniach:
      uwspkal.wspkal=(ICR1L+256*ICR1H);

       sbi(TIFR,ICF1);

     uwspkal.wspkal/=64;


    Może ktoś w prosty sposób wyjaśnić mi dlaczego tam są takie działania wykonywane?
  • #2 7527623
    mirekk36
    Poziom 42  
    uwspkal.wspkal=(ICR1L+256*ICR1H);


    a wiesz jak działają unie??? .... bo tu zapisujesz do zmiennej 16bitowej wspkal wartość 16bitowego rejestru przechwytywania

    sbi(TIFR,ICF1);


    ustawiasz bit ICF1 w rejestrze TIFR


    uwspkal.wspkal/=64;


    a to mogłoby być zapisane tak:

    uwspkal.wspkal = uwspkal.wspkal / 64;


    teraz jaśniej ? ;)
  • #5 7529747
    mirekk36
    Poziom 42  
    zamiast tego 256 a dzięki temu, że to unia można byłoby równie dobrze tak to zapisać:

    uwspkal.wspkalb[0] = ICR1H;
    uwspkal.wspkalb[1] = ICR1L;


    dzięki temu nie trza mnożyć przez 256 ;) ..... oj poczytaj jednak o uniach bo inaczej bez takich podstaw to i tak daleko nie zajedziesz. A unie i struktury to na prawdę fajne mechanizmy ;) w C
  • #6 7531133
    AsKeR
    Poziom 11  
    a dlaczego uwspkal.wspkal jest dzielone przez 64 za każdym razem?
    (dzięki za pomoc - to już ostatnie pytanie )
  • Pomocny post
    #7 7531506
    mirekk36
    Poziom 42  
    Pomyś sobie co się stanie z liczbą 4 jeśli podzielisz ją przez 2 ?

    tak na prawdę przesuniesz zawartość bajtu w prawo o jeden bit prawda?

    a jak podzielisz np liczbę 64 przez 16 - to masz przesunięcie w prawo o 4 bity prawda?

    a jeśli podzielisz liczbę dwubajtową INT np przez 64 - to o ile bitów w prawo ją przesuniesz???? a do tego jak poczytasz w PDF'ie procka - w jaki sposób przechowywana jest wartość po pomiarze ADC w rjestrze 16bitowym - to myślę że połączysz wszystkie fakty w jedność i zrozumiesz dlaczego jest to dzielenie o które pytasz ;)
REKLAMA