اطلاعیه

Collapse
No announcement yet.

شمارنده RPM با وقفه INT1 (دور بر دقیقه)

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

    شمارنده RPM با وقفه INT1 (دور بر دقیقه)

    سلام و احترام.
    من یک مدار دارم که دور موتور رو کامل و دقیق میخونه و کنترل میکنه.(البته باید این کار رو بکنه).

    اوپتی کانتر به پایه DDRD.3 از میکرو ATMEGA32 وصل هست(همون INT1).

    الان با این کدها میتونم بشمارم و نمایش بدم.
    کد:
    #include <mega32a.h>
    #include <delay.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <alcd.h>
    #include <stdbool.h>
    
    
    unsigned int count = 0;
    unsigned char str[16];
    interrupt [EXT_INT1] void ext_int1_isr(void)
    {
     count ++;
    }
    
    
    
    
    void main(void)
    {
     DDRD.3 = 0;
     PORTD.3 = 1;
     
     GICR |= (1<<INT1) | (0<<INT0) | (0<<INT2); // INT1: On
     MCUCR = (1<<ISC11) | (1<<ISC10) | (0<<ISC01) | (0<<ISC00); // INT1 Mode: Rising Edge
     GIFR = (1<<INTF1) | (0<<INTF0) | (0<<INTF2);
     
     lcd_init(16);
     #asm("sei")
    while (1)
     {
      lcd_gotoxy(1,1);
      lcd_putsf("COUNT = ");
    
    
      sprintf(str,"%04d",count);
      lcd_puts(str);
      lcd_gotoxy(8,1);
     }
    }


    اما من نمیخوام که بشماره. میخوام دور بر دقیقه رو محاسبه کنم.
    دستگاه قراره یک موتور رو تا 5000 دور بر دقیقه بخونه. بسیار دقیق.(اون شیعی که جلوی اوپتی کانتر رد میشه هر دور، 2 بار رد میشه).

    حالا من چطور میتونم در لحظه بخونم و نمایش بدم؟
    ممنون میشم راهنمایی بفرمایید. (کدویژن AVR).
    *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

    #2
    پاسخ : شمارنده RPM با وقفه INT1 (دور بر دقیقه)

    شما اینجا یک اشتباه الگوریتمی داری ،

    میخوای سرعت یا همون فرکانس رو اندازه بگیری ( دور شمار یعنی شمارنده تعداد تغییرات در واحد زمان )

    بوسیله اینتراپت داری تعداد عبور از جلوی سنسور رو میشماری و در متغیر count ذخیره میکنی ( از اینکه این روش بهینه نیست فعلا فاکتور میگیریم )

    بخش دوم کمیت کجاست ؟ ( باید مقدار شمارش شده تقسیم بر واحد زمان بشه ... تمام کمیتهای سرعت یک مخرج زمانی دارن ، دور بر ثانیه ، دور بر دقیقه ، متر ثانیه ، کیلومتر بر ساعت و بهمین ترتیب )

    کدی که نوشتید روی ال سی سی دی یک عدد نشون میده که داره مدام افزایش پیدا میکنه به انتهای رنج که رسید صفر میشه و از نو تکرار میشه .
    ساختار برنامه اتون هم بهینه نیست یک حلقه دائم داره بدون دلیل ال سی دی رو مدام آپدیت میکنه که گذشته از درگیر کردن بی دلیل منابع سیستم هر بار نوشتن روی ال سی دی کلی زمان هدر میده ... ال سی دی هم بخاطر آپدیت مداوم اصطلاحا لرزش یا پرش داره .
    روش درستش اینه پارامتر یکبار روی ال سی دی نوشته بشه تا آپدیت نشه بی دلیل درگیر نوشتن روی ال سی دی نشد .

    در هر صورت برای اندازه گیری زمان حداقل باید یک تایمر ست کنی تعداد شمارش شده در واحد زمان رو بدست بیاری بعد میشه به هر واحد دلخواهی تبدیلش کرد .

    میشه با یک تایمر کانتر اینکار رو انجام داد .
    میشه هم از واحد input capture استفاده کرد ...


    نمونه کد با تایمر ۸ بیت که نرم افزاری ۱۶ بیت شده و استفاده از وقفه مقایسه کننده ( زمان بین هربار تغییر سنسور اندازه گیری و تبدیل به سرعت میشه )
    کد:
     // global variables
    volatile uint8_t  counter_enable    = 1;  // enable update of counter result
    volatile uint8_t  counter_highbyte  = 0;  // high byte of 16-bit counter
    volatile uint16_t counter_result    = 0;  // counter result (timer counts per revolution)
    
    // main function
    int main(void) {
      uint16_t counter_value;                 // timer counts per revolution
      uint16_t rpm;                           // revolutions per minute
      PRR    = (1<<PRADC);                    // shut down ADC to save power
      DIDR0  = (1<<AIN1D) | (1<<AIN0D);       // disable digital input buffer on AC pins
      ACSR   = (1<<ACIE) | (1<<ACIS1);        // enable analog comparator interrupt on falling edge
      TIMSK0 = (1<<TOIE0);                    // enable timer overflow interrupt
      sei();                                  // enable all interrupts
      OLED_init();                            // initialize the OLED
      
      // main loop
      while(1) {                              // loop until forever
        counter_enable = 0;                   // lock counter result
        counter_value = counter_result;       // get counter result
        counter_enable = 1;                   // unlock counter result
        if (counter_value > 17) {             // if counter value is valid:
          rpm = (uint32_t)1125000 / counter_value; // calculate RPM value
          OLED_printW(rpm);                   // print RPM value on the OLED
        } else OLED_printB(slow);             // else print "SLOW" on the OLED
      }
    }
    
    // analog comparator interrupt service routine
    ISR(ANA_COMP_vect) {
      if(counter_enable) counter_result = (uint16_t)(counter_highbyte << 8) | TCNT0; // save result if enabled
      TCNT0 = 0;                              // reset counter
      counter_highbyte = 0;                   // reset highbyte
      TCCR0B  = (1<<CS01) | (1<<CS00);        // start timer with prescaler 64 (in case it was stopped)
    }
    
    // timer overflow interrupt service routine
    ISR(TIM0_OVF_vect) {
      counter_highbyte++;                     // increase highbyte (virtual 16-bit counter)
      if(!counter_highbyte) {                 // if 16-bit counter overflows
        TCCR0B = 0;                           // stop the timer
        if(counter_enable) counter_result = 0;// result is invalid
      }
    }

    دیدگاه


      #3
      پاسخ : شمارنده RPM با وقفه INT1 (دور بر دقیقه)

      نوشته اصلی توسط Amie.s.m نمایش پست ها
      شما اینجا یک اشتباه الگوریتمی داری ،

      میخوای سرعت یا همون فرکانس رو اندازه بگیری ( دور شمار یعنی شمارنده تعداد تغییرات در واحد زمان )

      بوسیله اینتراپت داری تعداد عبور از جلوی سنسور رو میشماری و در متغیر count ذخیره میکنی ( از اینکه این روش بهینه نیست فعلا فاکتور میگیریم )

      بخش دوم کمیت کجاست ؟ ( باید مقدار شمارش شده تقسیم بر واحد زمان بشه ... تمام کمیتهای سرعت یک مخرج زمانی دارن ، دور بر ثانیه ، دور بر دقیقه ، متر ثانیه ، کیلومتر بر ساعت و بهمین ترتیب )

      کدی که نوشتید روی ال سی سی دی یک عدد نشون میده که داره مدام افزایش پیدا میکنه به انتهای رنج که رسید صفر میشه و از نو تکرار میشه .
      ساختار برنامه اتون هم بهینه نیست یک حلقه دائم داره بدون دلیل ال سی دی رو مدام آپدیت میکنه که گذشته از درگیر کردن بی دلیل منابع سیستم هر بار نوشتن روی ال سی دی کلی زمان هدر میده ... ال سی دی هم بخاطر آپدیت مداوم اصطلاحا لرزش یا پرش داره .
      روش درستش اینه پارامتر یکبار روی ال سی دی نوشته بشه تا آپدیت نشه بی دلیل درگیر نوشتن روی ال سی دی نشد .

      در هر صورت برای اندازه گیری زمان حداقل باید یک تایمر ست کنی تعداد شمارش شده در واحد زمان رو بدست بیاری بعد میشه به هر واحد دلخواهی تبدیلش کرد .

      میشه با یک تایمر کانتر اینکار رو انجام داد .
      میشه هم از واحد input capture استفاده کرد ...


      نمونه کد با تایمر ۸ بیت که نرم افزاری ۱۶ بیت شده و استفاده از وقفه مقایسه کننده ( زمان بین هربار تغییر سنسور اندازه گیری و تبدیل به سرعت میشه )
      کد:
       // global variables
      volatile uint8_t  counter_enable    = 1;  // enable update of counter result
      volatile uint8_t  counter_highbyte  = 0;  // high byte of 16-bit counter
      volatile uint16_t counter_result    = 0;  // counter result (timer counts per revolution)
      
      // main function
      int main(void) {
        uint16_t counter_value;                 // timer counts per revolution
        uint16_t rpm;                           // revolutions per minute
        PRR    = (1<<PRADC);                    // shut down ADC to save power
        DIDR0  = (1<<AIN1D) | (1<<AIN0D);       // disable digital input buffer on AC pins
        ACSR   = (1<<ACIE) | (1<<ACIS1);        // enable analog comparator interrupt on falling edge
        TIMSK0 = (1<<TOIE0);                    // enable timer overflow interrupt
        sei();                                  // enable all interrupts
        OLED_init();                            // initialize the OLED
        
        // main loop
        while(1) {                              // loop until forever
          counter_enable = 0;                   // lock counter result
          counter_value = counter_result;       // get counter result
          counter_enable = 1;                   // unlock counter result
          if (counter_value > 17) {             // if counter value is valid:
            rpm = (uint32_t)1125000 / counter_value; // calculate RPM value
            OLED_printW(rpm);                   // print RPM value on the OLED
          } else OLED_printB(slow);             // else print "SLOW" on the OLED
        }
      }
      
      // analog comparator interrupt service routine
      ISR(ANA_COMP_vect) {
        if(counter_enable) counter_result = (uint16_t)(counter_highbyte << 8) | TCNT0; // save result if enabled
        TCNT0 = 0;                              // reset counter
        counter_highbyte = 0;                   // reset highbyte
        TCCR0B  = (1<<CS01) | (1<<CS00);        // start timer with prescaler 64 (in case it was stopped)
      }
      
      // timer overflow interrupt service routine
      ISR(TIM0_OVF_vect) {
        counter_highbyte++;                     // increase highbyte (virtual 16-bit counter)
        if(!counter_highbyte) {                 // if 16-bit counter overflows
          TCCR0B = 0;                           // stop the timer
          if(counter_enable) counter_result = 0;// result is invalid
        }
      }
      کاملا درسته صحبت شما. و من قبلا با timer/counter این کار رو انجام میدادم و تقسیم و ... میکردم.
      اما این مداری که به من داده شده، اپتی کانتر به پایه INT1 وصل شده. و باید با INT1 دور رو کنترل کنم.
      *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

      دیدگاه


        #4
        پاسخ : شمارنده RPM با وقفه INT1 (دور بر دقیقه)

        دوست عزیز همونطور که قبلا گفتم شما فقط باید یک تایمر به کدتون اضافه کنید .
        در کد بالا بجای وقفه مقایسه کننده آنالوگ از وقفه پایه ای که قبلا نوشتید استفاده کنید .

        بقیه اش ( صرفنظر از بخش نمایشگر ) مشترکه

        دیدگاه


          #5
          پاسخ : شمارنده RPM با وقفه INT1 (دور بر دقیقه)

          نوشته اصلی توسط Amie.s.m نمایش پست ها
          دوست عزیز همونطور که قبلا گفتم شما فقط باید یک تایمر به کدتون اضافه کنید .
          در کد بالا بجای وقفه مقایسه کننده آنالوگ از وقفه پایه ای که قبلا نوشتید استفاده کنید .

          بقیه اش ( صرفنظر از بخش نمایشگر ) مشترکه

          مشکل دارم باهاش بازم.
          کد:
          [LEFT]
          
          interrupt [TIM0_OVF] void timer0_ovf_isr(void)
          {
            timer0_ov++;                            // sensor 
          }
          
          
          
          TCCR0=0x06;
            counter ++;
            if(counter <= 0)
            {
          //   #asm("sei")
            }
              delay_ms(5);
            if(counter == 150)
            {
          //   #asm("cli")
             delay_ms(2);
             
             count = (timer0_ov*256+TCNT0) / 2;
             }
             
             TCCR0=0x00;
             timer0_ov=0;
             TCNT0=0;
             
             if(counter > 150)
             {
              counter = 0;
             }
          [/LEFT]
          صفر میشه
          *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

          دیدگاه


            #6
            پاسخ : شمارنده RPM با وقفه INT1 (دور بر دقیقه)

            چرا کد رو اینجوری کردی ؟

            با اورفلو تایمر بعنوان پارامتر عادی کار نداریم ...
            کانتر هم اصلا نداریم .
            تایمرت رو اینیتیالایز میکنی ( اینتراپت اورفلو برای نشون دادن تایم اوت استفاده میشه )
            هر بار اینتراپت int1 ست میشه عدد تایمر رو میخونی .
            ۱ تقسیم بر مقداری که تایمر شمرده فرکانس رو بهت میده که به هر کمیتی بخوای میشه تبدیلش کرد .
            ( یک حداقل هم برای تایمر باید در نظر بگیری که به هر دلیل تقسیم بر صفر نشه )
            تایمر رو مجدد اینیتیالایز میکنی .
            بر میگردی به حلقه اصلی برنامه
            اگر تایمر اورفلو شد باید پیغام تایم اوت یا RPM=0 نمایش بدی و تایمر مجدد اینیتیالیز بشه

            دیدگاه


              #7
              پاسخ : شمارنده RPM با وقفه INT1 (دور بر دقیقه)

              نوشته اصلی توسط Amie.s.m نمایش پست ها
              چرا کد رو اینجوری کردی ؟

              با اورفلو تایمر بعنوان پارامتر عادی کار نداریم ...
              کانتر هم اصلا نداریم .
              تایمرت رو اینیتیالایز میکنی ( اینتراپت اورفلو برای نشون دادن تایم اوت استفاده میشه )
              هر بار اینتراپت int1 ست میشه عدد تایمر رو میخونی .
              ۱ تقسیم بر مقداری که تایمر شمرده فرکانس رو بهت میده که به هر کمیتی بخوای میشه تبدیلش کرد .
              ( یک حداقل هم برای تایمر باید در نظر بگیری که به هر دلیل تقسیم بر صفر نشه )
              تایمر رو مجدد اینیتیالایز میکنی .
              بر میگردی به حلقه اصلی برنامه
              اگر تایمر اورفلو شد باید پیغام تایم اوت یا RPM=0 نمایش بدی و تایمر مجدد اینیتیالیز بشه

              یخورده گیج شدم. و نمیدونم باید چکار کنم.
              کل اینترنت و زیرو رو کردم و حتی یه نمونه ای که من مد نظرم هست رو ندیدم.
              موضوع مهم اینه که شما دقیقاً متوجه شدید من چی میخوام. اما من نمیدونم الان باید چطور کدش رو بزنم.
              *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

              دیدگاه


                #8
                پاسخ : شمارنده RPM با وقفه INT1 (دور بر دقیقه)

                نوشته اصلی توسط shoniz نمایش پست ها
                یخورده گیج شدم. و نمیدونم باید چکار کنم.
                کل اینترنت و زیرو رو کردم و حتی یه نمونه ای که من مد نظرم هست رو ندیدم.
                موضوع مهم اینه که شما دقیقاً متوجه شدید من چی میخوام. اما من نمیدونم الان باید چطور کدش رو بزنم.
                کلاک میکرو چند مگاهرتزه ؟

                دیدگاه


                  #9
                  پاسخ : شمارنده RPM با وقفه INT1 (دور بر دقیقه)

                  نوشته اصلی توسط Amie.s.m نمایش پست ها
                  کلاک میکرو چند مگاهرتزه ؟
                  کریستال 8 مگاهرتز - کلاک هم 8 مگاهرتز تعریف شده. atmega32 - CodeVision AVR دارم مینویسم. من ضعفم همین خوندن دور و کنترل موتور هست.
                  *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

                  دیدگاه


                    #10
                    پاسخ : شمارنده RPM با وقفه INT1 (دور بر دقیقه)

                    نوشته اصلی توسط shoniz نمایش پست ها
                    کریستال 8 مگاهرتز - کلاک هم 8 مگاهرتز تعریف شده. atmega32 - CodeVision AVR دارم مینویسم. من ضعفم همین خوندن دور و کنترل موتور هست.
                    با سلام و احترام
                    کدی که دوستمون براتون گذاشتند نمونه خیلی خوبیه. مقاله کاملش رو میتونید در لینک زیر یه نگاهی بندازید. توضیحات خوبی داره. فقط توجه داشته باشید که اون عدد ۱۱۲۵۰۰۰ رو باید طبق توضیحات سایت برای شرایط سخت افزار خودتان تغییر دهید.
                    Simple RPM-Meter. Contribute to wagiminator/ATtiny13-TinyTacho development by creating an account on GitHub.

                    موفق باشید.

                    دیدگاه


                      #11
                      پاسخ : شمارنده RPM با وقفه INT1 (دور بر دقیقه)

                      نوشته اصلی توسط evergreen نمایش پست ها
                      با سلام و احترام
                      کدی که دوستمون براتون گذاشتند نمونه خیلی خوبیه. مقاله کاملش رو میتونید در لینک زیر یه نگاهی بندازید. توضیحات خوبی داره. فقط توجه داشته باشید که اون عدد ۱۱۲۵۰۰۰ رو باید طبق توضیحات سایت برای شرایط سخت افزار خودتان تغییر دهید.
                      Simple RPM-Meter. Contribute to wagiminator/ATtiny13-TinyTacho development by creating an account on GitHub.

                      موفق باشید.
                      بله نگاهش کردم. ظاهراً هم AVR هست. اما کامپایلرش کدویژن نیست یخورده کانورت کردن کدش هماهنگ نمیشه و هنوز نتونستم جواب بگیرم.
                      *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

                      دیدگاه


                        #12
                        پاسخ : شمارنده RPM با وقفه INT1 (دور بر دقیقه)

                        نوشته اصلی توسط shoniz نمایش پست ها
                        کریستال 8 مگاهرتز - کلاک هم 8 مگاهرتز تعریف شده. atmega32 - CodeVision AVR دارم مینویسم. من ضعفم همین خوندن دور و کنترل موتور هست.
                        دوست عزیز این کد رو استفاده کن
                        هر 1 ثانیه متغیرها آپدیت میشن

                        دستورات نمایشگرت رو در آخرین روتین بنویس ( اینتراپت تایمر 1 )

                        کد:
                        volatile uint16_t counter=;    //Main pulse counter
                        
                        
                        volatile uint16_t rpm=;        //Revolution per minute
                        
                        
                        volatile uint16_t rps=;        //Revolution per second
                        
                        
                        
                        
                        
                        
                        
                        
                        void main()
                        {
                        
                        
                        
                        
                           //Init INT1
                           MCUCR|=(1<<ISC01);   //Falling edge triggers interrupt.
                        
                        
                           GICR|=(1<<INT1);  //Enable INT1 IRQ
                        
                        
                           //Timer1 set for 1 sec IRQ
                           //Timer Clock = 1/1024 of sys clk
                           //Mode = CTC (Clear Timer On Compare)
                           TCCR1B|=((1<<WGM12)|(1<<CS12)|(1<<CS10));
                        
                        
                           //Compare value=7812
                        
                        
                           OCR1A=7812;
                        
                        
                           TIMSK|=(1<<OCIE1A);  //Output compare 1A interrupt enable
                        
                        
                           //Enable global interrupts 
                           sei();
                        
                        
                        
                        
                           while(1)
                           {
                              nop
                        
                        
                        }
                             wend
                           {
                              end
                        }
                        }
                        
                        
                        ISR(INT1_vect)
                        {
                           //INT1 pin detect a falling edge IRQ
                           counter++;
                        }
                        
                        
                        ISR(TIMER1_COMPA_vect)
                        {
                           //1000ms Timer1 IRQ
                           rps=counter;
                           rpm=rps*60;
                           counter=0x0000;
                        }
                        جدیدترین ویرایش توسط Amie.s.m; ۰۹:۵۴ ۱۴۰۱/۱۰/۲۹. دلیل: اصلاح کد

                        دیدگاه


                          #13
                          پاسخ : شمارنده RPM با وقفه INT1 (دور بر دقیقه)

                          نوشته اصلی توسط shoniz نمایش پست ها
                          بله نگاهش کردم. ظاهراً هم AVR هست. اما کامپایلرش کدویژن نیست یخورده کانورت کردن کدش هماهنگ نمیشه و هنوز نتونستم جواب بگیرم.
                          با سلام مجدد
                          اون خودش از ide آردوینو استفاده کرده و arduino core مربوط به میکروی خودش رو درش نصب کرده. شما با توجه به میکرویی که دارید میتونید core مربوطه رو از آدرس زیر دانلود کنید و در محیط آردوینو نصبش کنید. ممکن موقع نصب یه مقداری وقت گیر بنظر بیاد ولی بعدش دیگه راحتید.
                          Arduino hardware package for ATmega1284, ATmega644, ATmega324, ATmega324PB, ATmega164, ATmega32, ATmega16 and ATmega8535 - MCUdude/MightyCore

                          موفق باشید.

                          دیدگاه


                            #14
                            پاسخ : شمارنده RPM با وقفه INT1 (دور بر دقیقه)

                            نوشته اصلی توسط Amie.s.m نمایش پست ها
                            دوست عزیز این کد رو استفاده کن
                            هر 1 ثانیه متغیرها آپدیت میشن

                            دستورات نمایشگرت رو در آخرین روتین بنویس ( اینتراپت تایمر 1 )

                            کد:
                            volatile uint16_t counter=;    //Main pulse counter
                            
                            
                            volatile uint16_t rpm=;        //Revolution per minute
                            
                            
                            volatile uint16_t rps=;        //Revolution per second
                            
                            
                            
                            
                            
                            
                            
                            
                            void main()
                            {
                            
                            
                            
                            
                               //Init INT1
                               MCUCR|=(1<<ISC01);   //Falling edge triggers interrupt.
                            
                            
                               GICR|=(1<<INT1);  //Enable INT1 IRQ
                            
                            
                               //Timer1 set for 1 sec IRQ
                               //Timer Clock = 1/1024 of sys clk
                               //Mode = CTC (Clear Timer On Compare)
                               TCCR1B|=((1<<WGM12)|(1<<CS12)|(1<<CS10));
                            
                            
                               //Compare value=7812
                            
                            
                               OCR1A=7812;
                            
                            
                               TIMSK|=(1<<OCIE1A);  //Output compare 1A interrupt enable
                            
                            
                               //Enable global interrupts 
                               sei();
                            
                            
                            
                            
                               while(1)
                               {
                                  nop
                            
                            
                            }
                                 wend
                               {
                                  end
                            }
                            }
                            
                            
                            ISR(INT1_vect)
                            {
                               //INT1 pin detect a falling edge IRQ
                               counter++;
                            }
                            
                            
                            ISR(TIMER1_COMPA_vect)
                            {
                               //1000ms Timer1 IRQ
                               rps=count;
                               rpm=rps*60;
                               counter=0x0000;
                            }
                            من کدهارو آوردم توی کد ویژن. دقیقا همون چیزی که شما نوشتید. اما نمیشماره.

                            کد:
                            #include <mega32a.h>
                            #include <delay.h>
                            #include <stdio.h>
                            #include <stdlib.h>
                            #include <alcd.h>
                            #include <stdbool.h>
                            
                            
                            // Declare your global variables here
                            
                            
                            unsigned char str[16];
                            volatile unsigned int counter=0;    //Main pulse counter
                            volatile unsigned int rpm=0;        //Revolution per minute
                            volatile unsigned int rps=0;        //Revolution per second
                            
                            
                            
                            
                            void main()
                            {
                             DDRD.3 = 0;
                             PORTD.3 = 1;
                            
                            
                            
                            
                            
                            
                               //Init INT1
                             MCUCR|=(1<<ISC01);   //Falling edge triggers interrupt.
                            
                            
                            
                            
                             GICR|=(1<<INT1);  //Enable INT1 IRQ
                            
                            
                            
                            
                               //Timer1 set for 1 sec IRQ
                               //Timer Clock = 1/1024 of sys clk
                               //Mode = CTC (Clear Timer On Compare)
                             TCCR1B|=((1<<WGM12)|(1<<CS12)|(1<<CS10));
                            
                            
                            
                            
                               //Compare value=781
                            
                            
                            
                            
                             OCR1A=781;
                            
                            
                            
                            
                             TIMSK|=(1<<OCIE1A);  //Output compare 1A interrupt enable
                            
                            
                            
                            
                               //Enable global interrupts 
                               
                             lcd_init(16);
                             lcd_gotoxy(0,0);
                             lcd_putsf("TEST COUNTER .CO");
                             #asm("sei")
                            
                            
                            
                            
                            
                            
                            
                            
                             while(1)
                             {
                              lcd_gotoxy(1,1);
                              lcd_putsf("COUNT = ");
                            
                            
                              sprintf(str,"%04d",count);
                              lcd_puts(str);
                              lcd_gotoxy(8,1);
                            
                            
                            
                            
                             }
                            }
                            
                            
                            
                            
                            interrupt [EXT_INT1] void ext_int1_isr(void)
                            {
                               //INT1 pin detect a falling edge IRQ
                               counter++;
                            }
                            
                            
                            
                            
                            interrupt [TIM1_COMPA] void timer1_compa_isr(void)
                            {
                               //1000ms Timer1 IRQ
                               rps=count;
                               rpm=rps*60;
                               counter=0x0000;
                            }
                            *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

                            دیدگاه


                              #15
                              پاسخ : شمارنده RPM با وقفه INT1 (دور بر دقیقه)

                              نوشته اصلی توسط shoniz نمایش پست ها
                              من کدهارو آوردم توی کد ویژن. دقیقا همون چیزی که شما نوشتید. اما نمیشماره.

                              کد:
                              #include <mega32a.h>
                              #include <delay.h>
                              #include <stdio.h>
                              #include <stdlib.h>
                              #include <alcd.h>
                              #include <stdbool.h>
                              
                              
                              // Declare your global variables here
                              
                              
                              unsigned char str[16];
                              volatile unsigned int counter=0;    //Main pulse counter
                              volatile unsigned int rpm=0;        //Revolution per minute
                              volatile unsigned int rps=0;        //Revolution per second
                              
                              
                              
                              
                              void main()
                              {
                               DDRD.3 = 0;
                               PORTD.3 = 1;
                              
                              
                              
                              
                              
                              
                                 //Init INT1
                               MCUCR|=(1<<ISC01);   //Falling edge triggers interrupt.
                              
                              
                              
                              
                               GICR|=(1<<INT1);  //Enable INT1 IRQ
                              
                              
                              
                              
                                 //Timer1 set for 1 sec IRQ
                                 //Timer Clock = 1/1024 of sys clk
                                 //Mode = CTC (Clear Timer On Compare)
                               TCCR1B|=((1<<WGM12)|(1<<CS12)|(1<<CS10));
                              
                              
                              
                              
                                 //Compare value=781
                              
                              
                              
                              
                               OCR1A=781;
                              
                              
                              
                              
                               TIMSK|=(1<<OCIE1A);  //Output compare 1A interrupt enable
                              
                              
                              
                              
                                 //Enable global interrupts 
                                 
                               lcd_init(16);
                               lcd_gotoxy(0,0);
                               lcd_putsf("TEST COUNTER .CO");
                               #asm("sei")
                              
                              
                              
                              
                              
                              
                              
                              
                               while(1)
                               {
                                lcd_gotoxy(1,1);
                                lcd_putsf("COUNT = ");
                              
                              
                                sprintf(str,"%04d",count);
                                lcd_puts(str);
                                lcd_gotoxy(8,1);
                              
                              
                              
                              
                               }
                              }
                              
                              
                              
                              
                              interrupt [EXT_INT1] void ext_int1_isr(void)
                              {
                                 //INT1 pin detect a falling edge IRQ
                                 counter++;
                              }
                              
                              
                              
                              
                              interrupt [TIM1_COMPA] void timer1_compa_isr(void)
                              {
                                 //1000ms Timer1 IRQ
                                 rps=count;
                                 rpm=rps*60;
                                 counter=0x0000;
                              }
                              با سلام
                              کد دوستمون رو اگر خواستی استفاده کنی فکر میکنم rpm=rps*60 را باید به rpm=rps*30 تبدیل کنی چون تا اونجایی که یادمه گفته بودید به ازای هر دور گردش دوبار پالس ارسال میشه.
                              موفق باشید.

                              دیدگاه

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