اطلاعیه

Collapse
No announcement yet.

مشکل با ایجاد زمان دقیق تایمر

Collapse
X
 
  • فیلتر
  • زمان
  • Show
Clear All
new posts

    مشکل با ایجاد زمان دقیق تایمر

    سلام خدمت دوستان

    من یه کدی نوشتم که توش تایمر های 0 و 2 فعال هستن. میکرو atmega8 هست و با کلاک 4 مگ داخلی کار میکنه. فرکانس تایمر صفر هم روی 62.5 کیلو هرتز هست. اومدم زمان یک ثانیه رو با این تایمر با استفاده از متغیر d درست کردم . خروجی PB.5 برای 90 ثانیه روشن و به مدت 60 ثانیه خاموش میشه. مشکل اینه که در عمل به 90 ثانیه نمیرسه و در حدود 87 ثانیه پین روشن میمونه و بعدش خاموش میشه و برای دوره 60 ثانیه هم حدود یک ثانیه اختلاف وجود داره و 59 ثانیه هست تقریباً. در حالی که توی پروتئوس همه چیز درسته.

    این مشکل به خاطر استفاده از کریستال داخلی هست یا این که به خاطر طولانی بودن برنامه ای که توی وقفه ی تایمر نوشتم این اتفاق می افته؟

    یه مسئله ی دیگه اینه که اگه برنامه ی وقفه تایمر خیلی طول بکشه به طوری که از وقفه ی بعدی کاملاً عبور کنیم . به نظرم زمان 90 ثانیه مثلاً باید 100 ثانیه طول بکشه یعنی باید بیش تر از 90 ثانیه طول بکشه نه این که کمتر از 90 ثانیه. درست میگم؟؟

    با تشکر

    کد:
    #include <mega8.h>
    #include <delay.h>
    #define ADC_VREF_TYPE 0xC2
    
    unsigned char a=0,b=0,c=0,m=23,e=0,n=0,CH=0,co_bar=0,gas_bar=0,t=0,u=0,co_show=0,gas_show=0,d=0;
    flash unsigned char num[]={0,1,3,7,15,31,63,127,255,255,255};
    volatile unsigned int v=0;
    volatile unsigned char k=0,co_mode=0,gas_mode=0,co_set=3,gas_set=3,timer=0;
    unsigned int s=0;
    
    interrupt [TIM0_OVF] void timer0_ovf_isr(void)
    {  d+=1;
      if(co_mode==0)
      {  co_show=co_bar;
      }
      else
      {  co_show=co_set;
      }
      if(gas_mode==0)
      {  gas_show=gas_bar;
      }
      else
      {  gas_show=gas_set;
      }
      if(d<123)
      {  if(co_mode==1) t=1;
        else  t=0;
        if(gas_mode==1) u=1;
        else  u=0;
      }
      else
      {  t=0;
        u=0;
      }
      
      if(d%2==1) // namayeshe bar graph
      {  PORTC.5=1;
        PORTD=num[co_show];
        PORTC|=num[co_show%8];
        PORTC.4=t;
      }
      if(d%2==0)
      {  PORTC.4=1;
        PORTD=num[gas_show];
        PORTC|=num[gas_show%8];
        PORTC.5=u;
      }
    
      if(d==244) // yek sanie
      {  d=0;
        if(timer<5)
        {  timer++;
          if(timer==5)
          {  co_mode=0;
            gas_mode=0;
          }
        }
        if(s<10)// fa'al nashodane khorooji ta paydar shodane sensor vaghti taze be bargh vasl shode
        {  s+=1;
          PORTB.2=1;// cheraghe entezar roshan mishe
        }
        if(e<90)
        {  if((e%90)==89 && s==10)
          {  PORTB.2=0;
            if(CH<2)
            {  ADCSRA|=0x40;
              while ((ADCSRA & 0x10)==0);
              v=ADCW;
              co_bar=v/32;
              if(v>(32*co_set))
              {  PORTB|=0x10;
                if(k==0 && n<3)  
                {  TCCR2|=0x1B;
                  n+=1;
                  CH=1;
                }
                if(n>2)
                {  TCCR2&=0x00;
                  PORTB.3=1;
                  n+=1;
                  if(n==5)  n=0;
                }
              }   
              else
              {  TCCR2&=0x00;
                PORTB&=0x21;
                PORTB.3=1;
                n=0;
                CH=0;
              }
            }
          }
          if(++e==90)
          {  PORTB.5=0;
          }
        }
        else
        {  if((e%90)==59 && s==10)
          {  
            if(CH==0 || CH==2)
            {  ADCSRA|=0x40;
              while ((ADCSRA & 0x10)==0);
              v=ADCW;
              gas_bar=v/30;
              if(v>(30*gas_set))
              {  PORTB|=0x10;
                if(k==0 && n<3)
                {  TCCR2|=0x1B;
                  n+=1;
                  CH=2;
                }
                if(n>2)
                {  TCCR2&=0x00;
                  PORTB.3=1;
                  n+=1;
                  if(n==5)  n=0;
                }
              }
              else
              {  TCCR2&=0x00;
                PORTB&=0x21;
                PORTB.3=1;
                n=0;
                CH=0;
              }
            }
          }
          if(++e==150)
          {  PORTB.5=1;
            e=0;
          }
        }
        if(k>0) k+=1;
      }
    }
    
    interrupt [TIM2_COMP] void timer2_comp_isr(void)
    {  if(a<m) a+=1;
      if(a==m)
      {  if(++b==m)
        {  if(((c++)%2)==0)
          {  OCR2=0x40;
            m=44;
          }
          else
          {  OCR2=0xFC;
            m=23;
          }
          b=0;
          a=0;
        }
      }
    }
    
    void main(void)
    {
    PORTB=0x2B;
    DDRB=0x3C;
    
    PORTC=0x30;
    DDRC=0x33;
    
    PORTD=0x00;
    DDRD=0xFF;
    
    TCCR0=0x03;
    TCNT0=0x00;
    
    TCCR1A=0x00;
    TCCR1B=0x00;
    TCNT1H=0x00;
    TCNT1L=0x00;
    ICR1H=0x00;
    ICR1L=0x00;
    OCR1AH=0x00;
    OCR1AL=0x00;
    OCR1BH=0x00;
    OCR1BL=0x00;
    
    ASSR=0x00;
    TCCR2=0x00;
    TCNT2=0x00;
    OCR2=0xFC;
    
    MCUCR=0x00;
    
    TIMSK=0x81;
    
    UCSRB=0x00;
    
    ACSR=0x80;
    SFIOR=0x00;
    
    ADCSRA=0x85;
    ADMUX=0xC2;
    
    SPCR=0x00;
    
    TWCR=0x00;
    
    #asm("sei")
    
    while (1)
       { if(PINB.0==0)
        {  TCCR2=0x00;
          PORTB.3=1;
          k=1;
        }
        if(PINB.1==0)  
        {  co_mode=1;
          timer=0;
        }
        if(PINC.3==0)  
        {  gas_mode=1;
          timer=0;
        }
        if(PINB.1==0 && co_mode==1)
        {  co_set++;
          timer=0;
          if(co_set==11) co_set=0;
        }
        if(PINC.3==0 && gas_mode==1)
        {  gas_set++;
          timer=0;
          if(gas_set==11) gas_set=0;
        }   
       }
    }

    #2
    پاسخ : مشکل با ایجاد زمان دقیق تایمر

    سلام
    کریستال داخلی دقت اش به درد ساعت نمیخوره بهتره از تایمر 2 با کریستال 32768 خارجی استفاده کنی.
    كرشمه اي كن و بازار ساحري بشكن @-}--@-}--@-}--به غمزه رونق و ناموس سامري بشكن
    ياصاحب الزمان(عج)

    دیدگاه


      #3
      پاسخ : مشکل با ایجاد زمان دقیق تایمر

      به نظر من توی وقفه برنامه تون از رجیستر TCNT0 استفاده میکردید و به راحتی با تغییر مقدار اولیه این رجیستر میتونستید دقت ثانیه شمارتون رو درستش کنید. دوما واقعا لازم بود که این همه برنامه رو داخل وقفه بیارید.داخل while نمیشد نوشت؟! :surprised:
      www.gam-co.blogsky.com

      دیدگاه


        #4
        پاسخ : مشکل با ایجاد زمان دقیق تایمر

        نوشته اصلی توسط vahidabedi
        به نظر من توی وقفه برنامه تون از رجیستر TCNT0 استفاده میکردید و به راحتی با تغییر مقدار اولیه این رجیستر میتونستید دقت ثانیه شمارتون رو درستش کنید. دوما واقعا لازم بود که این همه برنامه رو داخل وقفه بیارید.داخل while نمیشد نوشت؟! :surprised:
        دقت ثانیه شمار در حدی بالا هست که در طول 90 ثانیه کمتر از 0.06 ثانیه خطا داشته باشه که مهم نیست برام ولی حدود 3 ثانیه خطا داره oo:

        یه مسئله ای که هست مقدار زیادی از اون همه کدی که توی وقفه تایمر صفر هست اصلاً با هر بار وقفه اجرا نمیشه و تقریباً هر 90 ثانیه یک بار کد ها اجرا میشه که لازم بود از داخل وقفه اجرا بشه.

        دیدگاه


          #5
          پاسخ : مشکل با ایجاد زمان دقیق تایمر

          توی پروتئوس فرکانس میکرو رو اندکی تغییر بدید ببینید چی میشه. مثلاً به جای 4MHz بذارید 3.9MHz
          بعدش، بهتره توی وقفه کاری رو انجام ندید. توی وقفه فقط یه سری پرچم و متغیر شمارنده رو مقداردهی کنید و توی حلقه while اصلی با استفاده از این پرچم ها و شمارنده ها کارهاتون رو انجام بدید. دقت کنید که شمارش ثانیه عمداً با خطا همراه نباشه (از مقسم هایی استفاده کنید که اعشار نتیجه نده).
          مثلاً از روی 62.5 کیلو، با شمارشِ 125 تا برسید به 500 هرتز. بعدش از این 500 هرتز، برسید به ثانیه:
          [code=c]
          void interrupt... //------ count 125 to create 500Hz from 62.5kHz
          {
          count_500Hz++;
          if(count_500Hz>=500){
          count_1s++;
          count_500Hz = 0;
          }
          }[/code]
          حالا توی while اصلی می تونید با شمردنِ ثانیه کارهای خودتون رو انجام بدید.
          اینجور کد نویسی با کریستال داخلی هم خطاش قابل چشم پوشیه.
          بیایید با Google آشتی کنیم!

          دیدگاه


            #6
            پاسخ : مشکل با ایجاد زمان دقیق تایمر

            نوشته اصلی توسط E.N
            این مشکل به خاطر استفاده از کریستال داخلی هست یا این که به خاطر طولانی بودن برنامه ای که توی وقفه ی تایمر نوشتم این اتفاق می افته؟
            بله، رزوناتور داخلی توی کارش دقیق نیست(بخاطر همین بیشتر کریستال می ذارن).

            موراد زیادی برای خطا وجود داره. مثلا بهتره به قول moha3 از تایمر2 با کریستال ساعت استفاده کنید. به برنامه تون دقت نکردم ولی بهتره از پیشنهاد moha3 استفاده کنید.

            دیدگاه

            لطفا صبر کنید...
            X