اطلاعیه

Collapse
No announcement yet.

کار با رجیسترهای avr

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

    کار با رجیسترهای avr

    سلام به همگی :smile:

    راهی داره که من به جای متغیر از نوع unsigned int از رجیسترهای 16 بیتی (بدون استفاده) avr استفاده کنم؟
    (R0..R31)

    اصلا کامپایلر کدویژن هیچکدوم از این رجیسترها رو برا برنامه نویس خالی گذاشته؟
    ( باور کنید از رو بیکاری اینو ننوشتم کارم بد جوری گیر کرده :read


    #2
    پاسخ : کار با رجیسترهای avr

    فکر نکنم چون کامپایلر موقع کامپایل کردن از همه رجیستر های موجود استفاده می کنه ...
    حالا میشه بگی کجا گیر کردی ؟ شاید بشه مشکلتو طور دیگه ای حل کرد ...
    Share OR Die

    دیدگاه


      #3
      پاسخ : کار با رجیسترهای avr

      ممنون آقا مهدی
      من یه انکودر رو از طریق پایه وقفه خارجی به mega32 وصل کردم تو روتین وقفه یه متغیر از نوع unsigned int قرار دادم که پالسهای انکودر رو برام شمارش میکنه
      حالا من یه برنامه ساده براش نوشتم:

      unsigned int Encoder_word
      unsigned char x

      if (Encoder_word) > 400) x=0

      بهمین سادگی! ولی یه اتفاق عجیب میفته به اینصورت که بعضی وقتها با اینکه Encoder_word ( که مقدارش در روتین وقفه زیاد میشه ) از 400 کمتره ولی باز شرط اجرا میشه (X=0)
      وقتی کلی با برنامه کلنجار رفتم فهمیدم که چون Encoder_word بصورت بایت به بایت با عدد 400 مقایسه میشه بطور تصادفی ممکنه هنگامی که برنامه بایت بالا رو مقایسه کرده و هنوز سراغ بایت پایین نرفته وقفه اجرا بشه و مقدار Encoder_word تغییر کنه

      دیدگاه


        #4
        پاسخ : کار با رجیسترهای avr

        اگه این if تو خود روتین وقفه باشه ، این موضوعی که شما میگی امکان نداره اتفاق بیوفته...
        اگه میشه شما متن کامل برنامه رو اینجا کپی کن تا باهم مشکلشو پیدا کنیم ...
        Share OR Die

        دیدگاه


          #5
          پاسخ : کار با رجیسترهای avr

          آره شما درست میگین آقا مهدی اگه داخل روتین وقفه باشه مشکل حل میشه

          البته فرکانس پالسهایی که انکودر به وقفه میده به 12khz میرسه و ضمنا من 14 نقطه رو تو برنامه باید Sense کنم
          حالا با توجه به فرکانس میکرو که اجبارا 8mhz هستش فکر نمیکنین سرعت کم بیاد؟
          ضمنا همزمان با نست اون 14 نقطه همزمان برنامه باید به روال های دیگه ای مثل دور موتور و وضعیت سنسورهای دیگه
          هم سرکشی کنه

          دیدگاه


            #6
            پاسخ : کار با رجیسترهای avr

            شما میتونین از فرکانس 12مگاهرتز استفاده کنین ... اینجوری فرکانس کاری میکرو 1000 برابر فرکانس پالسهای انکودر میشه ...
            فکر کنم در بین هر دو پالس انکودر ، بتونین حدود 1000 تا دستور(اسمبلی) رو انجام بدین ...

            ولی من راجع به این توجیه شما که میگین تست شرط ناقص می مونه و میکرو میره وقفه رو اجرا می کنه موافق نیستم ... چون میکرو وقتی وقفه میاد اول دستوری که در حال انجامه رو تموم میکنه بعد میره سراغ وقفه ....
            Share OR Die

            دیدگاه


              #7
              پاسخ : کار با رجیسترهای avr

              مشکل اینه که موقعی که شما داری بیرون از روال وقفه (که وقفه ها فعال هستن) به متغیر دسترسی پیدا میکنی ممکنه بین اخذ دو بایت اطلاعات این مقدار وقفه اتفاق بیفته. برای رفع این مشکل از کد زیر استفاده کن:

              unsigned int Encoder_word;
              unsigned char x;

              unsigned int getEncoder(void)
              {
              unsigned int res;

              asm("cli"
              res = Encoder_word;
              asm("sei"

              return res;
              }

              .
              .
              .

              if (getEncoder()) > 400) x=0

              دیدگاه


                #8
                پاسخ : کار با رجیسترهای avr

                نوشته اصلی توسط Mahdi.N

                ولی من راجع به این توجیه شما که میگین تست شرط ناقص می مونه و میکرو میره وقفه رو اجرا می کنه موافق نیستم ... چون میکرو وقتی وقفه میاد اول دستوری که در حال انجامه رو تموم میکنه بعد میره سراغ وقفه ....
                وقتی وقفه میاد میکرو دستور اسمبلی جاری رو تموم میکنه و این در مورد کد زبان C یا بقیه کامپایلرها صادق نیست و مقایسه word با word در زبان سی هم فکر میکنم بیشتر از 5 خط کد اسمبلی داشته باشه


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

                دیدگاه


                  #9
                  پاسخ : کار با رجیسترهای avr

                  خب می تونی بلافاصله بعد از اجرا شدن اینتراپت این کار رو بکنی که مطمئن باشی اینتراپت بعدی نیومده ...
                  Share OR Die

                  دیدگاه


                    #10
                    پاسخ : کار با رجیسترهای avr

                    فقط یه مشکل کوچولو بوجود میاد که ممکنه همزمان با خاموش کردن و روشن شدن مجدد وقفه یه پالس انکودرم رو از دست بدم
                    خیالت راحت همچین مسئله ای پیش نمیاد چون اولا سرعت وقفه جنابعالی به اندازه زمان اجرای 12 سیکل نیست (فاصله بین دو وقفه خیلی بیش از اینهاست. اگر کمتر بود در روال قبلی هم پالس رو گم میکردی). دوما ما اینجا وقفه سخت افزاری رو فعال و غیر فعال نمیکنیم. امکان اجرای نرم افزاری روال وقفه رو موقتا غیر فعال میکنیم. اما اگر در طی این زمان وقفه ای بوجود بیاد پردازش نشده باقی میمونه تا امکان اجراش مهیا بشه و بتونه اجرا بشه. تازه همین کد یک باگ کوچیک داره و اونم اینه که نباید از داخل یک وقفه یا موقعی که یکی دیگه وقفه ها رو خفه کرده صدا زده بشه. اما اگر خیلی براتون شک برانگیزه میتونین از کد زیر استفاده کنین. البته اینو برای WinAVR نوشتم و برای میکروهای غیر XMega!


                    unsigned int read_word(void *p_var);


                    usage:
                    unsigned int value = read_word( &Encoder_word );


                    .global read_word
                    read_word:
                    movw r30,r24
                    in r0,SREG
                    cli
                    ld r24,Z+
                    ld r25,Z
                    out SREG,r0
                    ret


                    زمان خفه شدن وقفه ها فقط 8 سیکل ساعته. یعنی روی کلاک 8 مگا هرتزی فقط 1 میکرو ثانیه.

                    دیدگاه


                      #11
                      پاسخ : کار با رجیسترهای avr


                      ممنون آقا رضا و آقا مهدی عزیز

                      در نهایت فانکشن زیر رو نوشتم و مشکلم کاملا برطرف شد:

                      کد:
                       unsigned int Get_True_encoder(void) 
                        { unsigned int True_enc;    
                      
                         do {
                           True_enc = Encoder_Counter;
                          }
                           while (True_enc != Encoder_Counter);
                      
                         return True_enc; 
                        }

                      دیدگاه

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