اطلاعیه

Collapse
No announcement yet.

timer capture

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

    timer capture

    سلام
    کسی تایمر رو تو مد capture راه انداخته؟ می خوام عرض پالس یه ورودی رو بدست بیارم.
    https://www.linkedin.com/in/mohammadhosseini69

    http://zakhar.blog.ir

    #2
    پاسخ : timer capture

    نوشته اصلی توسط محمد حسینی
    سلام
    کسی تایمر رو تو مد capture راه انداخته؟ می خوام عرض پالس یه ورودی رو بدست بیارم.
    سلام
    باید رجیستر TC_CMR را برای مد Capture به صورت زیر تنظیم کنید. همانطور که در شکل پایین مشاهده می کنید سیگنال خود را به TIOA میدهید. و با توجه به فرکانسی که شکل موج دارد کلاک ورودی تایمر را تنظیم میکند.
    بیت EDTRGEDG را برابر 01 قرار می دهید که در لبه بالا رونده تریگر خارجی تایمر تریگ شود. بیت ABETRG را برابر 1 قرار می دهید که TIOA به عنوان تریگر خارجی انتخاب شود. بیت LDRA را هم برابر 01 قرار می دهید تا در لبه بالا رونده مسیر TIOA رجیستر RA بار شود. که با توجه به تنظیم رجیسترهای قبلی همواره این رجیستر با مقدار 0 بار می شود.
    بیت LDBDIS را با 1 تنظیم می کنید که در هنگام بار شدن RB کلاک تایمر غیرفعال شود. بیت LDRB را برابر 10 قرار می دهید تا در لبه پایین رونده مسیر TIOA رجیستر RB بار شود.



    برای خواندن مقدار رجیسترهای RA و RB بهتر از وفقه بار شدن RB را فعال کنید. (بیت LDRBS) در روتین وقفه مقدار دو رجیستر RA , RB را می خوانید و تفاوت این دو تعداد شمارش های تایمر در طول پالس دریافتی بر روی TIOA می باشد که با توجه به فرکانس کلاک ورودی تایمر در نتیجه دوره تناوب کلاک ورودی تایمر می توان طول این پالس را برحسب زمان بدست آورد. بعد از بدست آوردن اختلاف این دو رجیستر کلاک تایمر را فعال می کنید (فقط فعال میکنید و تریگ نرم افزاری انجام نمی دهید.) تا در لبه بالا رونده بعدی TIOA روند قبلی دوباره اجرا شود.

    دیدگاه


      #3
      پاسخ : timer capture

      نوشته اصلی توسط حامد AT91
      ... که با توجه به تنظیم رجیسترهای قبلی همواره این رجیستر با مقدار 0 بار می شود.
      یعنی عرض پالس همیشه برابر رجیستر B میشه؟

      امتحان کردم جواب نداد! یکم بیشتر توضیح میدی؟ من می خوام duty cycle رو بدست بیارم. وقفه هم ترجیحا نداشته باشه. می خوام هر وقت که خواستم رجیسترهای A و B رو بخونم و محاسبات رو انجام بدم. یعنی تایمر همیشه آخرین مقادیر رو داشته باشه.
      ممنون
      https://www.linkedin.com/in/mohammadhosseini69

      http://zakhar.blog.ir

      دیدگاه


        #4
        اندازه گیری فرکانس و ضریب وظیفه با مد capture

        سلام
        الگوریتم قبلی که گفتم کلی بود. اما طبق همین من چک کردم درست کار نمی کرد و برای اینکه درست کار کند باید عمل تریگر کردن تایمر را توسط TIOB انجام داد و الباقی تنظیمات به همان صورتی هست که گفتم و باید سیگنالی را که می خواهید اندازه گیری کنید به دو پایه TIOA,TIOB تایمر وصل کنید که به صرفه نیست از دو پایه میکرو برای اینکار استفاده کنید.
        حالا از روش زیر که در شکل زیر هم معلوم هست استفاده می کنیم. که فقط از یک پایه TIOA برای اینکار استفاده می کنیم. مزیت این روش به قبلی این می باشد که ما هم دوره تناوب (فرکانس) سیگنال را بدست می آوریم و هم مدت زمان LOW بودن و هم مدت زمان HIGH بودن سیگنال در نتیجه ضریب وظیفه (DC) را هم به راحتی بدست می آید. تنظیمات مربوطه روی شکل مشخص هست و در برنامه زیر هم می توانید ببینید. برنامه زیر به صورتی نوشته شده است که هم می توانید از وقفه استفاده کنید هم بدون وقفه.



        در برنامه زیر تایمر صفر تنظیمات مربوطش شده است و از TIOA0 که PA0 می باشد به عنوان ورودی استفاده می شود. اگر می خواهید از وقفه استفاده کنید برنامه های داخل while(1) را باید پاک کنید و اگر به صورت معمولی می خواهید استفاده کنید و نمی خواهید از وقفه استفاده کنید تنظیمات وقفه تایمر و روتین آن را پاک کنید و از برنامه داخل while(1) برای خواندن رجیسترها و محاسبات استفاده کنید.
        در برنامه زیر از PWM1 که PA1 می باشد. برای تولید یک شکل موج و تست برنامه راه اندازی شده. که از وقفه آن هم برای تغییر ضریب وظیفه استفاده شده است که به صورت خودکار تقریبا هر 2 ثانیه ضریب وظیفه آن افزایش می یابد تا به حداکثر مقدار خود برسد و سپس کاهش پیدا می کند و دوباره افزایش می یابد. که این قسمت فقط برای تست برنامه می باشد.

        کد:
        #include <Atmel/ioat91sam7s64.h>
        #include <intrinsics.h>
        #include "lcd.h"
        //------------------------------------------------------
        unsigned int ipwm,i1timer,i2timer,i3timer;
        //------------------pwm irq-------------------------------
        void pwmc_irq_handler(void)
        {
        unsigned int dummy;
        dummy = AT91C_BASE_PWMC->PWMC_ISR;
        dummy = dummy;
        ipwm++;
        if (ipwm==50000)
         {
         ipwm = AT91C_BASE_PWMC_CH1->PWMC_CDTYR + 10;
         if (ipwm==250)
         {
         AT91C_BASE_PWMC_CH1->PWMC_CUPDR =10;
         }
         else
         {
         AT91C_BASE_PWMC_CH1->PWMC_CUPDR = ipwm; 
         }
         ipwm=0;
         }
        }
        //---------------------timer irq---------------------------
        void timer0_irq_handler(void)
        {
        unsigned int dummy;
        dummy = AT91C_BASE_TC0->TC_SR;
        dummy = dummy;
        i1timer=AT91C_BASE_TC0->TC_RA;
        i2timer=AT91C_BASE_TC0->TC_RB;
        if(i3timer!=i1timer)
         {
         lcd_clear ();
         lcd_gotoxy (0,0);
         lcd_puts (i1timer);
         lcd_gotoxy (0,5);
         lcd_puts (i2timer);
         lcd_gotoxy (0,11);
         lcd_puts (i2timer-i1timer);
         lcd_gotoxy (1,0);
         lcd_putsf("f=");
         lcd_puts (6000000/i2timer);
         lcd_putsf("hz");
         lcd_gotoxy (1,10);
         lcd_putsf("DC=");
         lcd_puts (((i2timer-i1timer)*100)/i2timer);
         lcd_putsf("%");
         i3timer=i1timer;
         }
        }
        //--------------------main---------------------------
        void main()
        {
        //--------------------start up--------------------------
        AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS; // AT91C_WDTC_WDDIS=(1<<15)
        AT91C_BASE_RSTC->RSTC_RMR=0xA5000001;
        //--------------------speed up--------------------------
        AT91C_BASE_CKGR->CKGR_MOR = 0xF01;
        AT91C_BASE_CKGR->CKGR_PLLR = 0x7C3F18; //pllout 96000000
        AT91C_BASE_PMC->PMC_MCKR = 0x7; //mck 48000000
        AT91C_BASE_PMC->PMC_SCER = 0x1;
        //------------------set clk------------------------------
        AT91C_BASE_PMC->PMC_PCER = ( 1<<AT91C_ID_PIOA ); // AT91C_ID_PIOA=2
        AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_PWMC); // AT91C_ID_PWMC=10
        AT91C_BASE_PMC->PMC_PCER = ( 1<<AT91C_ID_TC0 ); // AT91C_ID_TC0=12
        //-------------------set pwm----------------------------
        AT91C_BASE_PIOA->PIO_PDR = (1<<1);
        AT91C_BASE_PIOA->PIO_MDER = (1<<1);
        AT91C_BASE_PIOA->PIO_ASR = (1<<1);
        AT91C_BASE_PWMC_CH1->PWMC_CMR = 0x203;   
        AT91C_BASE_PWMC_CH1->PWMC_CPRDR = 250;
        AT91C_BASE_PWMC_CH1->PWMC_CDTYR = 10;
        AT91C_BASE_PWMC->PWMC_ENA = 0x2;
        //--------------------set aic pwm---------------------------
        AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PWMC] = (unsigned int) pwmc_irq_handler;
        AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PWMC] = 0x7;
        AT91C_BASE_AIC->AIC_ICCR = (1<<AT91C_ID_PWMC);
        AT91C_BASE_PWMC->PWMC_IER = 0x2;
        AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_PWMC);
        //--------------------set timer--------------------------
        AT91C_BASE_PIOA->PIO_PDR = (1<<0);
        AT91C_BASE_PIOA->PIO_MDER = (1<<0);
        AT91C_BASE_PIOA->PIO_BSR = (1<<0);
        AT91C_BASE_TC0->TC_CMR = 0x90641; //tcclks=mck/8=6000000
        AT91C_BASE_TC0->TC_CCR = 0x1;
        //--------------------set aic timer-------------------------
        AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC0] = (unsigned int) timer0_irq_handler;
        AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] = 0x5;
        AT91C_BASE_AIC->AIC_ICCR = (1<<AT91C_ID_TC0);
        AT91C_BASE_TC0->TC_IER = (1<<6);
        AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_TC0);
        //-----------------------------------------------------
        lcd_pininit(16,15,5,6,7,8,26,27,28,29);
        lcd_init ();
        lcd_clear ();
        lcd_gotoxy (0,0);
        lcd_puts (0);
        lcd_gotoxy (0,5);
        lcd_puts (0);
        lcd_gotoxy (0,11);
        lcd_puts (0);
        lcd_gotoxy (1,0);
        lcd_putsf("f=");
        lcd_puts (0);
        lcd_putsf("hz");
        lcd_gotoxy (1,10);
        lcd_putsf("DC=");
        lcd_puts (0);
        lcd_putsf("%");
        ipwm=0;
        i3timer=0;
        __enable_interrupt();
        //-----------------------------------------------------
        while (1)
         {
        /* while ((AT91C_BASE_TC0->TC_SR&(1<<6))==0);
         i1timer=AT91C_BASE_TC0->TC_RA;
         i2timer=AT91C_BASE_TC0->TC_RB;
         if(i3timer!=i1timer)
          {
          lcd_clear ();
          lcd_gotoxy (0,0);
          lcd_puts (i1timer);
          lcd_gotoxy (0,5);
          lcd_puts (i2timer);
          lcd_gotoxy (0,11);
          lcd_puts (i2timer-i1timer);
          lcd_gotoxy (1,0);
          lcd_putsf("f=");
          lcd_puts (6000000/i2timer);
          lcd_putsf("hz");
          lcd_gotoxy (1,10);
          lcd_putsf("DC=");
          lcd_puts (((i2timer-i1timer)*100)/i2timer);
          lcd_putsf("%");
          i3timer=i1timer;
          }*/
         }
        }
        //---------------------------------------------------------
        در ضمن فرکانس میکرو هم روی 48مگاهرتز تنظیم شده است. در شکل زیر هم خروجی برنامه بر روی LCD را مشاهده میکنید. فایل باینری و برنامه پیوست می باشد.

        فایل های پیوست شده

        دیدگاه

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