اطلاعیه

Collapse
No announcement yet.

مشکل با INT0 در کدویژن

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

    مشکل با INT0 در کدویژن

    سلام

    من یه برنامه ی ساده نوشتم ، در این برنامه وقفه ها به لبه ی پاین رونده حساس هستن ، وقتی که وقفه اتفاق می افته برنامه ی مربوط به LCD که داخل تابع INT0 نوشته شده کار نمی کنه ، درحالیکه برنامه ی صفر و یک شدن پورت کار می کنه. ورژن کدویژن من 2.05.0 هست. برنامه توی پروتیوس کار می کنه ولی توی عمل فقط پورت چشمک می زنه و صفحه ی LCD به کل پاک میشه! من فایل های مربوط به کدویژن و شبیه سازی رو گذاشتم. کسی می دونه قضیه از چه قراره؟

    کد و شبیه سازی

    اینم برنامه برای بررسی سریع :

    کد:
    #include <mega8.h>
    #include <stdio.h>
    #include <alcd.h>
    #include <delay.h>
    
    
    interrupt [EXT_INT0] void ext_int0_isr(void)
    {
    // Place your code here
    
     lcd_init(16);
     PORTD.4=1;
     lcd_clear();
     lcd_gotoxy(0,0);
     lcd_putsf("INT0 isr");
     delay_ms(1000);
     PORTD.4=0;
     
    }
    
    interrupt [EXT_INT1] void ext_int1_isr(void)
    {
    // Place your code here
    
    }
    
    
    void main(void)
    {
    
    char Enter=13;
    char sms[160];
    char B;
    
    char k=0;
    int j=0;
    int i=0;
    
    for (k=0;k<250;k++){
    sms[k]=0;
    };
    
    PORTB=0x00;
    DDRB=0x00;
    
    PORTC=0x00;
    DDRC=0x00;
    
    PORTD=0x00;
    DDRD=0x10;
    
    GICR|=0xC0;
    MCUCR=0x0A;
    GIFR=0xC0;
    
    UCSRA=0x00;
    UCSRB=0x18;
    UCSRC=0x86;
    UBRRH=0x00;
    UBRRL=0x26;
    
    // RS - PORTB Bit 5
    // RD - PORTB Bit 6
    // EN - PORTB Bit 4
    // D4 - PORTB Bit 3
    // D5 - PORTB Bit 2
    // D6 - PORTB Bit 1
    // D7 - PORTB Bit 0
    // Characters/line: 16
    lcd_init(16);
    
     lcd_clear();
     lcd_gotoxy(0,0);
     printf("ATE0%c",Enter);
     lcd_putsf("Get sms...");
     delay_ms(1000);
     //lcd_clear();
    
    // Global enable interrupts
    #asm("sei")
    
    
    
    while (1)
       {
       // Place your code here
    
       }
    }

    اَللّهُمَ صَلّ عَلی مُحَمَّد وَ آلِ مُحَمَّد وَ عَجّل الفَرَجَهُم

    {خلاف قوانین}
    [img width=124 height=100]http://mortezark.persiangig.com/image/Web/6_3.PNG[/img]

    #2
    پاسخ : مشکل با INT0 در کدویژن

    سلام دوست عزیز :smile:
    اولا" که تابع Lcd_init رو داخل اینتراپت ننویس و در همون اول تابع main بنویس
    روشن و خاموش کردن پورت و پاک کردن lcd رو هم غیرفعال کن و تست کن
    موفق باشید
    حضرت علی(ع):
    أَشرَفُ الخَلاَئِقِ اَلوَفَا بِالعَهد.
    شریفترین خصلتها وفاى به عهد است.

    دیدگاه


      #3
      پاسخ : مشکل با INT0 در کدویژن

      نوشته اصلی توسط مرتضی رحیمی
      کسی می دونه قضیه از چه قراره؟
      کد:
      
      void main(void)
      {
      
      char sms[160];
      .
      .
      .
      .
      
      for (k=0;k<250;k++){
      sms[k]=0;
      };
      سلام. در برنامه شما طول آرایه SMS رو برابر 160 قرار دادید ولی در حلقه for بایت های بعدی که خارج از این آرایه قرار دارن رو هم تحت تاثیر قرار دادید که کاملاً اشتباه است.
      همچنین مدت اجرای برنامه داخل روتین وقفه بسیار طولانی و غیر اصولی است . برنامه رو به صورت زیر تغییر بدید. ببینید کار میکنه:


      #include <mega8.h>

      // Alphanumeric LCD Module functions
      #include <alcd.h>

      #include <mega8.h>
      #include <stdio.h>
      #include <alcd.h>
      #include <delay.h>


      bit status=0;

      interrupt [EXT_INT0] void ext_int0_isr(void)
      {
      status=1;
      GICR&=~(1<<INT0); // Disable INT0 Interrupt

      }



      void main(void)
      {

      char Enter=13;
      char sms[160];
      char B;

      char k=0;
      int j=0;
      int i=0;

      for (k=0;k<160;k++){
      sms[k]=0;
      };

      PORTB=0x00;
      DDRB=0x00;

      PORTC=0x00;
      DDRC=0x00;

      PORTD=0x00;
      DDRD=0x10;

      GICR|=0xC0;
      MCUCR=0x0A;
      GIFR=0xC0;
      UCSRA=0x00;
      UCSRB=0x18;
      UCSRC=0x86;
      UBRRH=0x00;
      UBRRL=0x26;

      // RS - PORTB Bit 5
      // RD - PORTB Bit 6
      // EN - PORTB Bit 4
      // D4 - PORTB Bit 3
      // D5 - PORTB Bit 2
      // D6 - PORTB Bit 1
      // D7 - PORTB Bit 0
      // Characters/line: 16
      lcd_init(16);
      lcd_clear();
      lcd_gotoxy(0,0);
      printf("ATE0%c",Enter);
      lcd_putsf("Get sms..."
      delay_ms(1000);
      //lcd_clear();

      // Global enable interrupts
      #asm("sei&quot



      while (1)
      {
      ///////////////////////
      if(status==1)
      {
      PORTD.4=1;
      lcd_clear();
      lcd_gotoxy(0,0);
      lcd_putsf("INT0 isr"
      delay_ms(1000);
      PORTD.4=0;

      status=0;
      GICR|=(1<<INT0); // Enable INT0 Interrupt
      }
      ////////////////////////


      }
      }

      دیدگاه


        #4
        پاسخ : مشکل با INT0 در کدویژن

        سلام

        اولا" که تابع Lcd_init رو داخل اینتراپت ننویس و در همون اول تابع main بنویس
        منم اولش همین کارو کردم وقتی نتیجه نداد تابع lcd_init رو آوردم اونجا.

        روشن و خاموش کردن پورت و پاک کردن lcd رو هم غیرفعال کن و تست کن
        این یعنی چی؟ هدف من تست کردن وقفه با LCD هست که!


        در برنامه شما طول آرایه SMS رو برابر 160 قرار دادید ولی در حلقه for بایت های بعدی که خارج از این آرایه قرار دارن رو هم تحت تاثیر قرار دادید که کاملاً اشتباه است.
        بله حق با شماست. اون 250 مال برنامه ی اصلی بود ، بعدا که من مقدار 160 رو گذاشتم اونجارو فراموش کردم! چون مهم نبود! همونطوریکه می بینید من اصلا از هیچ کدوم اون متغیرها در برنامه اسات فاده نکردم. چون هنوز برنامه به اون مرحله نرسیده توش موندم! (از دست این LCD و وقفه)

        برنامه ای رو که نوشتید تست می کنم و نتیجه رو اعلام می کنم.

        اَللّهُمَ صَلّ عَلی مُحَمَّد وَ آلِ مُحَمَّد وَ عَجّل الفَرَجَهُم

        {خلاف قوانین}
        [img width=124 height=100]http://mortezark.persiangig.com/image/Web/6_3.PNG[/img]

        دیدگاه


          #5
          پاسخ : مشکل با INT0 در کدویژن

          با تشکر از هر دو عزیز ، مشکل من رفع شد.

          دلیلشم فقط همون متغیر SMS بود! نمی دونم چرا؟ ولی وقتیکه طول متغیر SMS برابر 160 بود و من به اشتباه درایه های اونو تا 250 برابر 0 قرار داده بودم برنامه کار نمی کرد. با تغییر عدد 250 به 160 مشکل کاملا رفع شد! خیلی جالب و عجیب بود.

          همچنین مدت اجرای برنامه داخل روتین وقفه بسیار طولانی و غیر اصولی است
          جناب perfect منظور شما از این جمله چی بود؟ بنظر من نباید اینطور باشه ، چون وقتی وقفه اتفاق می افته درواقع یه زیر تابع قراره اجرا باشه ، و اجرای یک زیر تابع نباید به طول برنامه ی داخلش یا مدت زمان اجراش یا Delayهای موجود ربطی داشته باشه ، حالا چه این زیر تابع توسط کاربر تعریف شده باشه چه اینکه بصورت سخت افزاری و یکی از امکانات میکرو باشه (مثل همین INT0).
          البته من برنامه نویسیم به زبان C بخوبی شما نیست ولی بنظرم اون چیزی که شما گفتید یه ضعفه! اگه اونطوری باشه پس تکلیف برنامه ساخت یافته چی میشه؟

          این برنامه ی جدید منه ، فرقشم در همون عدد 250 و 160 هست.

          کد:
          #include <mega8.h>
          #include <alcd.h>
          #include <stdio.h>
          #include <delay.h>
          
          interrupt [EXT_INT0] void ext_int0_isr(void)
          {
            //GICR&=~(1<<INT0); // Disable INT0 Interrupt
            
             PORTD.4=1;
           lcd_clear();
           lcd_gotoxy(0,0);
           lcd_putsf("INT0 isr");
           delay_ms(1000);
           PORTD.4=0; 
           lcd_clear();
           
           
           //GICR|=(1<<INT0);  // Enable INT0 Interrupt
          }
          
          
          
          void main(void)
          {
          
          char Enter=13;
          char sms[160];
          char B;
          
          char k=0;
          int j=0;
          int i=0;
          
          for (k=0;k<160;k++){
          sms[k]=0;
          };
          
          PORTB=0x00;
          DDRB=0x00;
          
          PORTC=0x00;
          DDRC=0x00;
          
          PORTD=0x00;
          DDRD=0x10;
          
          GICR|=0xC0;
          MCUCR=0x0A;
          GIFR=0xC0;
          UCSRA=0x00;
          UCSRB=0x18;
          UCSRC=0x86;
          UBRRH=0x00;
          UBRRL=0x26;
          
          // RS - PORTB Bit 5
          // RD - PORTB Bit 6
          // EN - PORTB Bit 4
          // D4 - PORTB Bit 3
          // D5 - PORTB Bit 2
          // D6 - PORTB Bit 1
          // D7 - PORTB Bit 0
          // Characters/line: 16
           
           lcd_init(16);
           lcd_clear();
           lcd_gotoxy(0,0);
           printf("ATE0%c",Enter);
           lcd_putsf("Get sms...");
           delay_ms(1000);
          
          
          // Global enable interrupts
          #asm("sei")
          
          while (1)
             {
              
               
             }
          }

          اَللّهُمَ صَلّ عَلی مُحَمَّد وَ آلِ مُحَمَّد وَ عَجّل الفَرَجَهُم

          {خلاف قوانین}
          [img width=124 height=100]http://mortezark.persiangig.com/image/Web/6_3.PNG[/img]

          دیدگاه


            #6
            پاسخ : مشکل با INT0 در کدویژن

            سلام.
            ببینید، روتین وقفه در واقع یک زیر تابع نیست. بلکه یک پاسخ سریع به یک در خواست فوری و مهم است.
            در برنامه ایکه نوشتید با توجه به اینکه عامل درخواست کننده (شخص خودتان) سریع نیست اشکالی ایجاد نمیشه. و برنامه کار میکنه. همچنین در این برنامه فقط یک درخواست کننده وجود داره و بقیه وقفه ها غیر فعالند.
            ولی زمانی رو در نظر بگیرید که یک واقعه بسیار مهم هر چند وقت یکبار در خواست وقفه میکنه و حتماً باید به درخواست اون پاسخ داده بشه. حال اگر این وقفه زمانی که برنامه در روتین وقفه خارجی 0 و به صورتی که شما نوشتید در حال اجرا است ،رخ بده حتی اگر خیلی مهم باشه باید زمان زیادی منتظر بمونه تا وقفه خارجی 0 به پایان برسه تا به درخواست اون رسیدگی بشه. ولی از طرفی هم ممکنه در طول این مدت با توجه به اینکه به درخواست پاسخ داده نشده ، درخواست لغو بشه. بنابر این شما یک واقعه مهم رو از دست دادید که عواقب اون به نوع واقعه بستگی داره. مثلاً چنانچه مربوط به دریافت سریال باشه شما کلی از اطلاعات رو از دست داده اید.
            پس به طور کلی سعی کنید با ترفند های مناسب سریع تر روتین وقفه رو ترک کنید. مگر اینکه ناچار باشید.

            دیدگاه


              #7
              پاسخ : مشکل با INT0 در کدویژن

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

              خیلی از لطفتون ممنونم.

              موفق باشید.

              اَللّهُمَ صَلّ عَلی مُحَمَّد وَ آلِ مُحَمَّد وَ عَجّل الفَرَجَهُم

              {خلاف قوانین}
              [img width=124 height=100]http://mortezark.persiangig.com/image/Web/6_3.PNG[/img]

              دیدگاه

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