اطلاعیه

Collapse
No announcement yet.

interrupt در mplab

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

    interrupt در mplab

    سلام به جمیع مهندسین
    یه سوال دارم اونم اینکه :
    من AVR رو بلدم و باهاش کار میکنم و چن وقتیه دارم با pic کار میکنم و با mplab x ide و کامپایلر c18 کد میزنم
    میخام از interrupt میکرو استفاده کنم . چنتا برنامه رو نگاه کردم اما راستشو بخاید چیزی نفهمیدم میشه لطف کنید یه توضیح کلی در مورد interrupt های pic و بالاخص سری 18f452 بدید ؟ اینکه چه جوری فعال میشن یا چه جوری باید ازشون استفاده کرد و . . . . . . . ؟
    اگه بتونید یه سورس هم برام بزارید واقعا ممنون میشم

    راستی mplab x ide با mplab ide فرق داره؟ یا جفتشون یکی هستن؟

    اضافه شده در تاریخ :
    واقعا کسی بلد نیست جواب بده یا نمیخاید جواب بدید یا حال جواب دادنو ندارید ؟
    سوال خیلی سختیه ؟!!!!!!!!!!!!!
    لطفا جواب بدید
    *****براي آدمي بهتر است که اصلا به دنيا نيايد تا اينکه بيايدو هيچ تاثيري نگذارد *****
    ناپلئون بناپارت

    #2
    پاسخ : interrupt در mplab

    دوست عزیز سلام از اینکه منتظر بودید معظرت می خوام

    اینتراپت ها توی avr و pic به جز چند تا فرق اساسی تفاوتی با هم ندارند:

    1- توی avr برای هر ماژولی (adc-timer-وقفه های خارجی و....) یه بردار وقفه تعریف میشه .(خودتون که دیگه بهتر می دونید.)
    2- توی avr اولویت وقفه ها قابل تغییر نیست (مثلا اولویت وقفه ی خارجی 0 همیشه بالاتر از وقفه ی تایمر است.)
    3-هر وقفه که اتفاق بی افته به صورت خودکار پرچم وقفه هم reset مسشه
    اما در pic های هشت بیتی :

    فقط دو بردار وقفه تعریف میشه (high و low) ولی در عوض میتونید اولویت وقفه ی ماژول ها رو خودتون تعیین کنید.
    مثلا اگه وقفه ی تایمر 0 و adc فعال باشه میتونید وقفه ی تایمر 0 رو high وقفه ی adc رو low تعیین کنید.
    پرچم وقفه ها باید به صورت نرم افزاری reset بشه.

    در مورد میکروی pic18f452 اگه میخواین خوب متوجه بشید اول برید دیتاشیت رو باز کنید و صفحه ی 77 رو بخونید.
    من یه توضیح مختصر میدم:

    رجیستر intcon(اینتراپت کنترل رجیستر)
    رجیستر مهمی هست دو تا بیت مهم دار یعنی بیت های 7 و6 توضیحات رو بخونید.

    رجیستر های PIR :
    توی این رجیستر ها پرچم وقفه های که شما قبلا فعال کردید وجود دارند که و در زمانی که وقفه اتفاق می افته شما باد پرچم مورد نظر رو صفر
    کنید.

    رجیستر های PIE:
    توی این رجیستر شما وقفه هایی رو که میخواین فعال بشند تنظیم می کنید.

    رجیستر های IPR:
    توی این رجیستر ها شما اولویت وقفه ها رو مشخص می کنید(وقفه با ارزش کم یا زیاد)

    رجیستر RCON:
    توی این رجیستر مشخص می کنید که وقفه ها اولویت دار باشن یا نه(بیت IPEN)

    (انگشتام افتاد :redface

    اگه میخواین یه وقفه رو تنظیم کنید (مثلا تایمر) بعد از اینکه این صفحات رو خوندید برید توی صفحه ی تایمر بلوک دیاگرام رو ببنید
    بعدش در آخر کار جدولی وجود دار ه به نام REGISTERS ASSOCIATED توی این جدول بیت هایی که باید تنظیم شند های لایت
    شده اند وبه راحتی می فهمید که کجا رو باید تنظیم کنید.

    من با کامپایلر XC کار می کنم و یه تفاوت جزیی توی تعریف بردار وقفه با c18 دار من توی XC8 رو اینجا مینویسم.

    یه مثال برای تایمر 0:

    کد:
    void Timer0_init(void){
    
      T0CONbits.T0PS = 1;//1:4PRES
      T0CONbits.PSA = 0;
      T0CONbits.T0CS = 0;//INTERNAL CLOCK
      T0CONbits.T08BIT = 0;//16BIT TIMER
     
      TMR0 = 45535;
      INTCONbits.T0IF = 0;
      INTCONbits.T0IE = 1;//ENABLE INTERRUPT
    
      T0CONbits.TMR0ON = 1;//START TIMER0
    RCONbits.IPEN = 0; //Disable priority levels
      INTCONbits.PEIE = 1;
      INTCONbits.GIE = 1;
    }
    کد:
    void interrupt timer0_isr(void){
          TMR0 = 45535;
      INTCONbits.T0IF = 0;
    تایمر صفر هر 20ms سر ریز میشه ویه وقفه میده(کلاک میکرو 16 MHz )
    اگه خوب توضیح ندادم معضرت میخوام اگه جاییشو متوجه نشدید بگید تا چنتا مثاله دیگی بزارم.
    در زندگيت به کسي اعتــــماد کن که به او ايمــــان داري نه احســاس . . .

    چه بسيار انسان ها ديدم تنشان لباس نبود؛و چه بسيار لباس ها ديدم که انساني درونش نبود ...!

    دیدگاه


      #3
      پاسخ : interrupt در mplab

      نه داداش دمت واقعا گرم
      و انگشتات درد نکنه که در مورده رجیستراش توضیح دادی ولی ........!
      من هنوز بلد نیستم که چه جوری توی برنامه ازشون استفاده کنم
      منظورم من #pragma code و این جور صحبتاشه
      مثلا توی CV دستور زیرو مینوشتیم:
      کد:
      interrupt [EXT_INT0] void x (void)
        {
       دستورات وقفه
        };
      حالا میخاستم شبیه به یه چنین چیزیو توی mplab x ide ,c18 بگید
      راستی mplab x ide با mplab ide فرق داره؟ یا جفتشون یکی هستن؟
      بازم ممنون

      اضافه شده در تاریخ :
      راستی توی pic اگه اولویت یه وقفه از یکی دیگه بالاتر باشه و مثلا جفتشون با هم رخ بدن به اونی که اولویتش بالا تره رسیدیگی میشه و اولویت پایینه بعدا رسیدگی میشه یا پایینیه کلا حذف میشه ؟
      یه سوال دیگه : توی avr به ازای هر flag یه بردار داشتیم و دستورات مربوط به هر کدوم رو از هم جدا مینوشتیم حالا توی اینجا که کلا دوتا بیشتر نیست چه جوری باید وقفه مورد نظرتو انتخاب و توی اون دستورات لازمو بنویسی؟منظورم اینه که چه جوری میفهمه که الان این دستوراتی که توی isr نوشتیم مربوط به کدوم یک از وقفه هاست؟ مثلا فرض کنید میخایم از 4 یا 5 تا وقفه استفاده کنیم به صورت همزمان؟ آیا باید توی هر روتین بیایم تمامی flag هارو خودمون چک کنیم و if بزاریم که اگه این flag یک بود این کارو کن و اگه اون یکی یک بود اون کارو انجام بده ؟
      *****براي آدمي بهتر است که اصلا به دنيا نيايد تا اينکه بيايدو هيچ تاثيري نگذارد *****
      ناپلئون بناپارت

      دیدگاه


        #4
        پاسخ : interrupt در mplab

        سلام. من با کامپایلر های میکروچیپ کار نکردم ولی میدونم که توی PIC هر وقفه برای خودش بردار نداره. شما باید پرچم ها رو بررسی کنید.

        نوشته اصلی توسط اوس موسی
        راستی mplab x ide با mplab ide فرق داره؟ یا جفتشون یکی هستن؟
        MPLABX IDE نسخه جدید MPLAB IDE هست که کامپایلرهای جدید XC8, XC16 و XC32 روش نصب میشن. بعلاوه تفاوتهای کوچیک دیگه.

        دیدگاه


          #5
          پاسخ : interrupt در mplab

          سلام

          استفاده از وقفه ها در C18 کار مشکلی نیست

          1 . ابتدا کد های زیر رو به پروژه اضافه کنید


          کد:
          void high_isr(void);
          void low_isr(void);
          
          /*============================*/
          
          #pragma code high_vector = 0x08
          void interrupt_at_high_vector(void) {
            _asm GOTO high_isr _endasm
          }
          #pragma code /* return to the default code section */
          
          
          #pragma code low_vector = 0x18
          void interrupt_at_low_vector(void) {
            _asm GOTO low_isr _endasm
          }
          #pragma code /* return to the default code section */
          
          /*============================*/

          که به وسیله این کدها , هنگام وقفه جریان برنامه رو به آدرس تابعی که بردار وقفه در اون قرار داره هدایت میکنید , یعنی همون تابع high_isr و low_isr

          2 . حال فقط کافیست روتین وقفتون رو درون دو تابع فوق بنویسید :


          کد:
          /**********< high_isr >**********/
          #pragma interrupt high_isr
          void high_isr(void){
          
          // your code
          
          }// end high_isr()
          /**********************< low_isr >***********************/
          #pragma interruptlow low_isr
          void low_isr(void){
          
          // your code
          
          }// end low_isr()


          برای مثال :


          کد:
          /**********< high_isr >**********/
          #pragma interrupt high_isr
          void high_isr(void){
          
            #if defined(USB_INTERRUPT)
              USBDeviceTasks();
            #endif
          
              //XX2++ ;
          }// end high_isr()
          /**********************< low_isr >***********************/
          #pragma interruptlow low_isr
          void low_isr(void){
          
            if (PIR1bits.RC1IF == 1) {
          
              i_BuffUSART1_RX[ il_x1 ] = getc1USART();
              il_x1++ ;
              il_x2 = il_x1 ;
              if( i_BuffUSART1_RX == 0 ){
                il_x1 = 0 ;
              }
          
          
              PIR1bits.RC1IF = 0;
            }// END RC1
          
          
          }// end low_isr()

          در کد های بالا رسیدگی به وضایف USB در اولویت بالا قرار دارد و دریافت سریال در اولویت پایین
          حال اگر هر دو وقفه با هم اتفاق بیفتد , ابتدا به بردار وقفه , با اولویت بالا , رسیدگی میشود
          دقت کنید که در روتین وقفه پایین ابتدا چک میکنم که آیا بیت PIR1bits.RC1IF ست شده است یا خیر , این کار برای تفکیک وقفه ها از هم صورت میگیرد , پس اگر وقفه تایمر یا وقفه ... اتفاق افتاد فقط با چک کردن پرچم آن متوجه دلیل رخ دادن وقفه میشیم و در انتهای رسیدگی به آن وقفه , پرچم فوق را 0 میکنیم تا دوباره وقفه رخ ندهد

          بله میکروهای 8 بیتی PIC به این شکل عمل میکنند , اما میکروهای 16 و 32 بیتی دارای بردار وقفه مجزا هستند
          نا اميدي يه دروغ بزرگه که آدما به خودشون ميگن
          تلاش يه حقيقت بزرگه که با صبر به ثمر ميرسه

          دیدگاه


            #6
            پاسخ : interrupt در mplab

            با عرض سلام تو PIC که هر موقعی یه وقفه ای رخ میده و بردار وقفه میپره من تو دیتا شیت چیز تحت عنوان ادرس دهی بردار وقفه ندیدم پس چطور میکرو از روی بردار وقفه متوجه میشه که به کدام سرویس روتین وقفه پرش کنه

            دیدگاه


              #7
              پاسخ : interrupt در mplab

              نوشته اصلی توسط mostafa6369 نمایش پست ها
              با عرض سلام تو PIC که هر موقعی یه وقفه ای رخ میده و بردار وقفه میپره من تو دیتا شیت چیز تحت عنوان ادرس دهی بردار وقفه ندیدم پس چطور میکرو از روی بردار وقفه متوجه میشه که به کدام سرویس روتین وقفه پرش کنه
              سلام
              متوجه سوالتون نمیشم!
              خب در زبان C، کامپایلر به عبارات خاصی حساسه و وقتی وقفه اتفاق میفته، مستقیم به همون قسمت پرش می کنه!
              وظیفه ی کامپایلر هم همینه که اون عبارات خاص رو به آدرس تعبیر می کنه و کد هگزش رو تولید می کنه!
              این قضیه منحصر به میکروی PIC نیست!
              سوال دیگه ای مورد نظرتون هست؟؟
              *** يا راهي خواهم يافت، يا راهي خواهم ساخت ... ***

              دیدگاه


                #8
                پاسخ : interrupt در mplab

                نوشته اصلی توسط mostafa6369 نمایش پست ها
                با عرض سلام تو PIC که هر موقعی یه وقفه ای رخ میده و بردار وقفه میپره من تو دیتا شیت چیز تحت عنوان ادرس دهی بردار وقفه ندیدم پس چطور میکرو از روی بردار وقفه متوجه میشه که به کدام سرویس روتین وقفه پرش کنه
                PIC ها فقط دوتا بردار وقفه دارن و مثلا شما تعریف می کنین UART و SPI اینتراپتشون توی تقدم بالا باشه و وقتی هر کدموم اینتراپتش فعال بشه آدرس 0008h اجز می شه . حالا شما باید توی برنامه ی اینتراپت بیایین پرچم اینتراپت ها رو چک کنین ببینین اینتراپت کدوم ماژول رخ داره که برنامه ی متناسب با اون رو اجرا کنه

                دیدگاه


                  #9
                  پاسخ : interrupt در mplab

                  جناب اقای مرادی خیلی ممنون از اینکه پاسخ دادین من تو مثال زیر اومدم و هر دو وقفه مربوط به تایمر صفر و یک را فعال کردم و فرض میکنم که اولویت وقفه اینجا مطرح نیستش اما زمانیکه برنامه را دیباگ میکنم و در اینجا تایمر یک زودتر سر ریز میشه و تو سرویس روتین هر دو وقفه اومدم و پرچمها را چک میکنم اما موققع دیباگ نمودن وقتی تایمر یک سریز شد و درخواست وقفه میده میپره روی تابع اولی که مربوط به تایمر صفر است و چون شرط پرچم این تایمر صدق نمیکنه وارد تابع نمیشه اما داخل همین تابع دایما دور میزنه و به Void بعدی که مربوط به تایمر یک است نمیرود تا شرط را بررسی کنه چرا دلیلش چیه؟
                  اما اگر تایمر صفر را حالت low_priority اضافه کنم مشکلم حل میشه ممکنه کمکم کنید چون در حالت اولویت یکسان برای تمام وقفه هم باید درست کار کنه درسته؟
                  نمونه کد داخل شکل زیر امده است

                  دیدگاه


                    #10
                    پاسخ : interrupt در mplab

                    نوشته اصلی توسط mostafa6369 نمایش پست ها
                    جناب اقای مرادی خیلی ممنون از اینکه پاسخ دادین من تو مثال زیر اومدم و هر دو وقفه مربوط به تایمر صفر و یک را فعال کردم و فرض میکنم که اولویت وقفه اینجا مطرح نیستش اما زمانیکه برنامه را دیباگ میکنم و در اینجا تایمر یک زودتر سر ریز میشه و تو سرویس روتین هر دو وقفه اومدم و پرچمها را چک میکنم اما موققع دیباگ نمودن وقتی تایمر یک سریز شد و درخواست وقفه میده میپره روی تابع اولی که مربوط به تایمر صفر است و چون شرط پرچم این تایمر صدق نمیکنه وارد تابع نمیشه اما داخل همین تابع دایما دور میزنه و به Void بعدی که مربوط به تایمر یک است نمیرود تا شرط را بررسی کنه چرا دلیلش چیه؟
                    اما اگر تایمر صفر را حالت low_priority اضافه کنم مشکلم حل میشه ممکنه کمکم کنید چون در حالت اولویت یکسان برای تمام وقفه هم باید درست کار کنه درسته؟
                    نمونه کد داخل شکل زیر امده است

                    http://s5.picofile.com/file/8363034326/timer.jpg
                    من زیاد با کامپایلر xc8 کار نکردم و با ccs کد میزنم و زیاد از xc8 سر در نمیارم.
                    اگه از CCI syntax استفاده کنید باید مشخص کنید که تابعی که نوشتید اینتراپت اولویت بالا هست یا پایین(این کار فقط برای سری 8 بیتی PIC18 هست) اگر هم مشخص نکنید کامپایلر به صورت دیفالت اولویت بالا رو در نظر میگیره. توی همه ی PIC ها (8-bit) یک بردار وقفه هست و در PIC18 ها دو بردار وقفه وجود داره که دارای اولویت است، اولویت بالا و پایین. البته وقتی CCI syntax روشن باشه به جز این باید توی تعریف تابع اینتراپت یه نکاتی رو رعایت کنید.
                    خوب شما اینتراپت هایی که تعریف کردید هر دو توی اولویت بالا هست پس لازم نیست توی 2 تا تابع جدا گنه کد ها رو بنویسید و وقتی اینتراپت تایمر 1 هم رخ بده میکرو میره از آدرس اولویت بالا شروع میکنه دستورات رو اجرا میکنه به خاطر همین هم اول دستورات تایمر 0 رو اجرا میکنه .
                    شما میگین که توی تابع دور میزنه . شما که دستور شرطی نوشتید فقط باید یک بار اجرا کنه . شاید به خاطر اینکه برای یک اولویت دو تا تابع نوشتین خطا رخ میده . اگه شما بیاید از روی دستورات اسمبلی تولید شده رو تو ذهن خودتون اجرا کنین خیلی سریع به اشکال برنامه پی میبرید

                    این کدی که بر اساس CCI syntax نوشته شده
                    void __interrupt(high_priority) timers_isr(void)
                    {
                    if (TMR0IE && TMR0IF) { // any timer 0 interrupts?
                    TMR0IF=0;
                    //your code
                    }
                    if (TMR1IE && TMR1IF) { // any timer 1 interrupts?
                    TMR1IF=0;
                    //your code
                    }
                    // process other interrupt sources here, if required
                    return;
                    }


                    این کد رو یک بار تست کنید احتمالا درست کار کنه
                    جدیدترین ویرایش توسط M. Moradi; ۱۲:۴۲ ۱۳۹۸/۰۳/۲۰.

                    دیدگاه


                      #11
                      پاسخ : interrupt در mplab

                      بسیار سپاسگزارم جناب مرادی از اینکه وقت میذارین.
                      حالا یه سوال اگر پس تو یک برنامه فرض کنیم که چند تا وقفه فعال باشند (مثلا 4 عدد وقفه داشته باشیم) و همه اونها دارای یک اولویت باشند .تو نوشتن تابع برای هر چهار عدد از این وقفه ها نباید برای هر کدام تابع جداگانه ای نوشته بشوند و فقط داخل یک تابع نوشته شوند و داخل ان تابع فقط شروط را بررسی کنیم که ببینیم مربوط به کدام تابع باید اجرا شوند درسته؟
                      و مطلب بعدی اینکه بله درسته در مورد PIC بنده کامپایلر XC8 که مربوط به خودم شرکت میکرو چیپ هستش دارم استفاده میکنم و متاسفانه چون منابع اموزشیش خیلی کم هستش با خوندن دیتا شیت و کتب زبان اصلی میخوام انشاالله اگر بشه یه کتابی در این زمینه برای علاقه مندان هم چاپ کنم (البته همین موضوع را همین جا تو انجمن مطرح کردم ولی کسی درمورد استقبال از این کار و چاپ این کتاب نشد و فکر کردم شاید کار عبثی باشه و بیخیالش شدم)
                      جدیدترین ویرایش توسط mostafa6369; ۰۹:۳۷ ۱۳۹۸/۰۳/۲۰.

                      دیدگاه


                        #12
                        پاسخ : interrupt در mplab

                        نوشته اصلی توسط mostafa6369 نمایش پست ها
                        بسیار سپاسگزارم جناب مرادی از اینکه وقت میذارین.
                        حالا یه سوال اگر پس تو یک برنامه فرض کنیم که چند تا وقفه فعال باشند (مثلا 4 عدد وقفه داشته باشیم) و همه اونها دارای یک اولویت باشند .تو نوشتن تابع برای هر چهار عدد از این وقفه ها نباید برای هر کدام تابع جداگانه ای نوشته بشوند و فقط داخل یک تابع نوشته شوند و داخل ان تابع فقط شروط را بررسی کنیم که ببینیم مربوط به کدام تابع باید اجرا شوند درسته؟
                        بله درسته باید توی تابع اینتراپت چک کنیم ببینیم اینتراپت چه قسمتی رخ داده که کد مربوط اجرا بشه.

                        نوشته اصلی توسط mostafa6369 نمایش پست ها
                        و مطلب بعدی اینکه بله درسته در مورد PIC بنده کامپایلر XC8 که مربوط به خودم شرکت میکرو چیپ هستش دارم استفاده میکنم و متاسفانه چون منابع اموزشیش خیلی کم هستش با خوندن دیتا شیت و کتب زبان اصلی میخوام انشاالله اگر بشه یه کتابی در این زمینه برای علاقه مندان هم چاپ کنم (البته همین موضوع را همین جا تو انجمن مطرح کردم ولی کسی درمورد استقبال از این کار و چاپ این کتاب نشد و فکر کردم شاید کار عبثی باشه و بیخیالش شدم)
                        به نظر من برای شروع PIC رو بهتره با CCS کار کرد. CCS هلپ خوبی داره و شما رو با سخت افزار pic آشنا میکنه. کار با ccs با توابعی که داره خیلی راحته. بعد که کامل زیر و بم رو فهمیدیم سویچ می کنیم روی xc8 . اون موقع فقط شما باید یک سری نکات رو رعایت کنید که به طور کامل تو هلپ xc8 توضیح داده و چون سخت افزار رو کامل بلدید دیگه وقتتتون برای کانفیگ کردن هدر نمی ره.
                        این درس ها تموم بشه من هم اگه بتونم به شما کمک می کنم
                        سایت microchipdeveloper.com رو هم یه نگاهی کنین . اطلاعات خوبی داره
                        جدیدترین ویرایش توسط M. Moradi; ۱۳:۱۱ ۱۳۹۸/۰۳/۲۰.

                        دیدگاه


                          #13
                          پاسخ : interrupt در mplab

                          سلام جناب اقای مرادی تو من دنبال یه کتابخانه LCD میگردم شما میتونید کمکم کنید.

                          دیدگاه


                            #14
                            پاسخ : interrupt در mplab

                            سلام خدمت دوستان یه مشکل خیلی عجیب بهش برخوردم که هر کاری کردم درست نشد ( تو نرم افزار پرتیوس به خوبی عمل میکنه اما در عمل نه
                            میخوام هرموقع وقفه خارجی INT0 یک لبه پایین رونده بهش امد یک پین را معکوس کنه.کد زیر نوشتم اما جواب نگرفتم.و زمانیکه پین INT0 را صفر میکنم .خروجی معکوس میشه ولی به محض اینکه مجددا این پین (یعنی همان INT0 یک میشه باز تابع وقفه اجرا میشه و پین را معکوس میکنه
                            ممکنه کمکم کنید.این هم برنامه ام
                            while(1){
                            }
                            interrupt input(void)
                            if (INT0IF && INT0IE(
                            INT0IF =0;
                            PORTBbits.RB1 (1^PORTBbits.RB1) ;
                            }
                            ضمنا توی برنامه بیت INTEDG0 را هم صفر کردم تا بردار وقفه با لبه پایین رونده عمل کنه.اخه چرا وقتی بردار وقفه عمل میکنه و من تو بردار وقفه حتی امدم فلگ مربوطه یعنی INT0IF را هم صفر کردم ولی باز دستم را که از کلید برمیدارم .مجددا خروجی من معکوس میشه

                            دیدگاه

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