اطلاعیه

Collapse
No announcement yet.

جلوگیری از تکرار اینتراپت

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

    جلوگیری از تکرار اینتراپت

    با سلام خدمت دوستان و اساتید گرامی

    در برنامه ای نیاز به فشردن یک کلید می باشد که چون ولتاژ پشت کلید 12 ولت است من توسط یک اپتوکوپلر آنرا به حدود 3 ولت رسانده (البته خوب حفاظت هم شده ) به یکی از پایه های میکرو دادم ( ATXmega128A1 ) روی Pin هفتم پورت F . که اینتراپت هم فعال نمودم و داره کار می کنه .

    مشکل : مشکل اینجاست که زمانی که کلید را می فشارم گاهی اوقات روتین زیر برنامه مربوطه یکبار اجرا میشود و گاهی بیش از یکبار ( دو یا سه بار ) اجرا میشود . :eek:
    به نظر می رسد وقتی وارد روتین اینتراپت هستم نیز اگر کلید فشرده شود یا در هنگام فشردن قطع و وصل شود پس از پایان روتین زیر برنامه ، مجددا آنرا اجرا می کند .

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

    خواستم با نوشتن شرط از این اتفاق جلوگیری کنم ولی بی فایده بود . لطفا راهنمایی فرمائید .

    کد برنامه main برای تعریف اینتراپت

    کد:
    int main(void)
    {
    	system_clocks_init();
    	PortSetting();
    	
    	TWI_Hard_init();
    	I2C_Init();
    	LCD.LCDinit();
    	LCD.LCDcursorOFF();
    	
    	
    	
    	
    	LoadSetting();
    	usarte0_init(); // Scale
    	
    	// Interupt Enable
    	// External interrupt 0 on PC0, enable pullup, sence falling edge
    	PORTF.PIN7CTRL = PORT_ISC_RISING_gc;      
    	PORTF.INT0MASK = PIN7_bm;
    	PORTF.INTCTRL = PORT_INT0LVL_LO_gc;
    	
    	// Times Enable
    	TCC1_PER = 7811;   // (F Crystal) 16.000.000 / (TC_CLKSEL_DIV256_gc) 16000000 / 1024 = 15625 (1s) / 2 = 7812 = 500 ms
    	TCC1_INTCTRLA = TC_ERRINTLVL_OFF_gc | TC_OVFINTLVL_LO_gc;
    	TCC1_CTRLA = TC_CLKSEL_DIV1024_gc;
    	
    	PMIC_CTRL = PMIC_LOLVLEN_bm;
    	
    
    
    	cli();
    	sei();
    	
    	while(1)
    	{
    		if(Starter == 0)
    		{
    			
    			Logo();
    			shart = 1;
    			Starter = 1;
    			
    			
    			ShowDateTime();
    		}
    		Ready();
    	
    		
    	}
    	
    	return (0);
    }
    در تابع port setting این پین بصورتی ورودی تعریف شده است و با یک مقاومت آری 10 کیلو کل پورت pull down شده است .

    کد اینتراپت

    کد:
    ISR(PORTF_INT0_vect)
    {
    	// SW Int
    	if(ShartInterrupt)
    	{
    		ShartInterrupt = false;
    		LED_2_ON;
    		KeyPress();
    		LED_2_Off;
    		ShartInterrupt = true;
    	}
    }
    - به دنبال فرصت عمري تباه کردم ! فرصت جواني ام بود من اشتباه کردم .

    #2
    پاسخ : جلوگیری از تکرار اینتراپت

    به دلیل وجود Bounce، با هر بار فشار دادن کلید چندین بار قطع و وصل انجام می شود. یک روش ممکن این است که در روتین وقفه، بصورت موقت وقفه پورت را غیر فعال کنید و توسط یک تایمر بعد از گذشت زمانی در حد چندین میلی ثانیه، مجددا وقفه را فعال کنید.
    اوژن: به معنای افکننده و شکست دهنده است
    دانایی، توانایی است-Knowledge is POWER
    برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
    وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
    قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
    اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
    ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

    دیدگاه


      #3
      پاسخ : جلوگیری از تکرار اینتراپت

      حتی با وجود غیر فعال کردن اینتراپت در اولین اجرای اینتراپت مورد نظر باز هم این اتفاق تکرار میشود . در نهایت شرط اجرا نشدن را برای تابع اصلی که در اینجا Keypress می باشد اعمال کردم که مشکل تا حدودی حل شد . ولی هنوز گاهی از هر 30 بار زدن کلید یک بار اتفاق می افتد .
      - به دنبال فرصت عمري تباه کردم ! فرصت جواني ام بود من اشتباه کردم .

      دیدگاه


        #4
        پاسخ : جلوگیری از تکرار اینتراپت

        نوشته اصلی توسط طراح
        به دلیل وجود Bounce، با هر بار فشار دادن کلید چندین بار قطع و وصل انجام می شود. یک روش ممکن این است که در روتین وقفه، بصورت موقت وقفه پورت را غیر فعال کنید و توسط یک تایمر بعد از گذشت زمانی در حد چندین میلی ثانیه، مجددا وقفه را فعال کنید.
        از این روش من هم مدتها استفاده میکردم که همیشه مجبور بودم با اینتراپتها یه تایمر رو هم فعال کنم
        اما یه روش ساده تر هم وجود داره که توی روتین وقفه به اندازه دیبانس کلید تاخیر بذارید و قبل از return دستور پاک کردن پرچم وقفه رو بذارید:
        کد:
        GIFR|=0x40;

        این دستور پرچم اینتراپت صفر رو پاک میکنه
        نکته مهمی که هست لحظه برداشتن کلید و نوسانات حاصل از اون هست
        برای اون مینتونید در روتین وقفه توی حلقه while منتظر برداشته شدن کلید بمونید و پس از برداشته شدن دوباره تاخیر بذارید تا نوسان هاش حذف بشه بعد با خیال راحت پرچم اینتراپت مد نظرتون رو پاک کنید و در نهایت return
        اما اگه نمیخواید منتظر بمونه مسلما یه متغیر باید استفاده کنید که لحظه فشار و برداشتن کلید رو مشخص کنه
        [br /][hr]http://pcenter.ir[hr][br /]

        دیدگاه


          #5
          پاسخ : جلوگیری از تکرار اینتراپت

          خیلی ممنون بعد از تست و بررسی دقیق نتیجه رو اعلام می کنم .
          - به دنبال فرصت عمري تباه کردم ! فرصت جواني ام بود من اشتباه کردم .

          دیدگاه


            #6
            پاسخ : جلوگیری از تکرار اینتراپت

            نوشته اصلی توسط ConstantError
            از این روش من هم مدتها استفاده میکردم که همیشه مجبور بودم با اینتراپتها یه تایمر رو هم فعال کنم
            اما یه روش ساده تر هم وجود داره که توی روتین وقفه به اندازه دیبانس کلید تاخیر بذارید و قبل از return دستور پاک کردن پرچم وقفه رو بذارید:
            کد:
            GIFR|=0x40;

            این دستور پرچم اینتراپت صفر رو پاک میکنه
            نکته مهمی که هست لحظه برداشتن کلید و نوسانات حاصل از اون هست
            برای اون مینتونید در روتین وقفه توی حلقه while منتظر برداشته شدن کلید بمونید و پس از برداشته شدن دوباره تاخیر بذارید تا نوسان هاش حذف بشه بعد با خیال راحت پرچم اینتراپت مد نظرتون رو پاک کنید و در نهایت return
            اما اگه نمیخواید منتظر بمونه مسلما یه متغیر باید استفاده کنید که لحظه فشار و برداشتن کلید رو مشخص کنه
            با تشکر از شما و جناب طراح

            با غیر فعال کردن اینتراپت در ابتدای روتین وقفه و مجددا فعال نمودن آن پس از لحظاتی توسط تایمر و همین طور با پاک نمودن Flag مربوطه به آن وقفه در انتهای روتین وقفه خوشبختانه مشکل تکرار اینتراپت حل شد .

            توضیحاتی در مورد Interrupt Flag Register
            این رجیستر مربوطه به پرچم وقفه برای پورت های Xmega می باشد که بصورت زیر نوشته میشود

            کد:
            PORTF.INTFLAGS
            بیت صفرم مربوطه به اینتراپت صفر و بیت یکم مربوطه به اینتراپت یک و مابقی بیت های Reserved می باشند .
            در هنگام بروز وقفه پرچم مربوطه فعال میشود که باعث عمل کردن روتین وقفه است . اما چیزی که در اینجا مهم است این است که با نوشتن عدد یک در همان flag (بیت) مربوطه شما آن را غیر فعال میکنید برای مثال با نوشتن دستور زیر آخرین وقفه بوجود آمده در پرچم وقفه صفر حذف میشود . و مثل این است که وقفه ای صورت نگرفته است .

            کد:
            	PORTF.INTFLAGS = 0x01;
            در واقع در اینجا با نوشتن دستور فوق در آخرین خط روتین وفقه و البته با غیر فعال نمودن وقفه پورت در ابتدای روتین وقفه دیگر با فشردن کلید روتین مورد نظر فقط یک بار انجام میشود .
            نکته اینکه در کد های بالا کد ها برای پورت F نوشته شده اند .
            - به دنبال فرصت عمري تباه کردم ! فرصت جواني ام بود من اشتباه کردم .

            دیدگاه


              #7
              پاسخ : جلوگیری از تکرار اینتراپت

              مشکل : مشکل اینجاست که زمانی که کلید را می فشارم گاهی اوقات روتین زیر برنامه مربوطه یکبار اجرا میشود و گاهی بیش از یکبار ( دو یا سه بار ) اجرا میشود . :eek:
              به نظر می رسد وقتی وارد روتین اینتراپت هستم نیز اگر کلید فشرده شود یا در هنگام فشردن قطع و وصل شود پس از پایان روتین زیر برنامه ، مجددا آنرا اجرا می کند .
              ببخشید فقط یک نظر :
              ممکنه چون شما لبه پایین رونده رو چک میکنین چون سرعت عملکرد شاسی به مراتب کمتر و خیلی کندتر از سرعت رفرش میکرو هستش این عمل چند مرتبه تکرار میشه :read:
              بعدا یه جمله قشنگ مینویسم

              دیدگاه


                #8
                پاسخ : جلوگیری از تکرار اینتراپت

                مطلبی که شما فرمودید درست است . اما همین موضوع خود مشکل بود . که در تاپیک های قبلی بررسی و حل شد . با تشکر
                - به دنبال فرصت عمري تباه کردم ! فرصت جواني ام بود من اشتباه کردم .

                دیدگاه

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