اطلاعیه

Collapse
No announcement yet.

مشکل با نوشتن تابع delay

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

    مشکل با نوشتن تابع delay

    سلام
    من با AT91SAM7X256 کار میکنم
    و با کامپایلر IAR

    می خواهم یه تابع تاخیر بنویسم(یه چیزی مثل تابع کتابخونه AVR-GCC)

    من با استفاده از دستورات زیر کلاک میکرو را روی 48 مگا هرتز تنطیم میکنم
    کد:
    *AT91C_CKGR_MOR = 0xF01;
     *AT91C_CKGR_PLLR = 0x2903FFC; 
     *AT91C_PMC_MCKR = 0x3;    
     *AT91C_PMC_SCER = 0x1;
    بعد می خواهم یک تاخیر فرضا 1 ثانیه ایجاد کنم
    پس تابعی به این صورت می نویسم :nerd:
    کد:
    void delay(void){
     unsigned long m , n;
     unsigned long MCKLCD=48054857;
      for (m=0;m <MCKLCD;m++);
    }
    ولی این تاخیر خیلی کمتر از 1 ثانیه است
    من با نوشتم کد زیر حدود 0.2 ثانیه تاخیر میگیرم
    کد:
    void delay(void){
     unsigned long m , n;
     for (n=0;n<1000000;n++)
      for (m=0;m <MCKLCD;m++);
    }
    چرا ؟
    کجای کار من اشتباه است؟
    { خلاف قوانین - پاک شد }

    #2
    پاسخ : مشکل با نوشتن تابع delay

    سلام
    این مشکل رو هم من داشتم ولی با تنظیم optimizations به صورت شکل زیر این مشکل حل شد. من وقتی در حالت speed و balanced تنظیم می کردم انگار اصلا این تاخیرهایی که با for ایجاد می کردم کامپایلر در نظر نمی گرفت ولی وقتی در حالت size می گذاشتم تاخیر ایجاد می شد . اینو تست کن ببین درست می شود یا نه ؟ خبرشو بهمون بده.

    دیدگاه


      #3
      پاسخ : مشکل با نوشتن تابع delay

      من با تنظیمات پیش فرض به نوشتن کد زیر در حد میلی ثانیه تاخیر ایجاد کردم
      کد:
      void delay_ms(unsigned int time){
       unsigned long m , n ,o, i =0,p;
       for (p=0;p<time;p++){
        for (m=0;m <(MCKLCD/100000);m++){
         for (n=0;n <25;n++){
          for (o=0;o <121;o++){
           i++;
          }
         }
        }
       }
      }
      که حدودا دقیق است
      ولی به صورت تجربی به دست آوردم

      الان راه حل شما را تست میکنم

      راستی من ایمیل زدم به IAR و پلاگین کار با Eclipse رو برام فرستادن
      خیلی توپه
      حیف که output converter نداره
      فکر کنم از قصد براش نذاشتن
      کسی دیگم با این کارکرده؟
      { خلاف قوانین - پاک شد }

      دیدگاه


        #4
        پاسخ : مشکل با نوشتن تابع delay

        نوشته اصلی توسط Mohpooria
        راستی من ایمیل زدم به IAR و پلاگین کار با Eclipse رو برام فرستادن
        خیلی توپه
        حیف که output converter نداره
        فکر کنم از قصد براش نذاشتن
        کسی دیگم با این کارکرده؟
        اینو من نشنیده بودم . کاربردش چیه؟ اگه میشه پلودش کنید تا دانلودش کنیم.

        دیدگاه


          #5
          پاسخ : مشکل با نوشتن تابع delay

          optimizations را تغییر دادم ، من امتحان کردم با یه کد مشابه کد زیر که به تعداد فرکانس میکرو کلاک میخوره حداد 11 ثانیه طول میکشه!
          واقعا جالبه!
          کد زیر را نوشتم
          کد:
          void delay(void){
           unsigned long m;
            for (m=0;m <(MCKLCD/100);m++);
          }
          موندم چی کار کنم ؟؟؟؟؟؟!!!!!!!!

          Eclipse یه IDE هست و چون من خیلی باهاش کار می کنم(زبان C و پردازش تصویر و AVR) می خواستم ARM هم با این کار کنم
          خیلی بهتر از IDE خود IAR است
          اینم لینک دانلودش:
          ftp://files.iar.com/pub/eclipse/arm55_update_site_5.5.1.201008021520.zip
          { خلاف قوانین - پاک شد }

          دیدگاه


            #6
            پاسخ : مشکل با نوشتن تابع delay

            نوشته اصلی توسط Mohpooria
            موندم چی کار کنم ؟؟؟؟؟؟!!!!!!!!
            خوب این تاخیرو می توانی با تایمر انجام بدی که به طور دقیق انجام بشود و تاخیری که می خواهید ایجاد کنید. مثال 8-5 صفحه 223 کتاب را نگاه کن تاخیر برای 1 ثانیه می باشد.

            دیدگاه


              #7
              پاسخ : مشکل با نوشتن تابع delay

              Periodic Interval Timer برای ایجاد تاخیر یه پریفرال خیلی خوب و جمع و جوره. بد نیست یه نگاه بهش بندازین.
              https://www.linkedin.com/in/mohammadhosseini69

              http://zakhar.blog.ir

              دیدگاه


                #8
                پاسخ : مشکل با نوشتن تابع delay

                پس میریم سراغ تایمر!
                البته من زمان دقیق نمی خواهم!
                از روی کنجکاوی!
                من تو ذهنم است که هر خط برنامه باید مدت زمانه مشخصی طول بکشه تا اجرا بشه
                ولی جالبه که در اینجا ابنجوری نیست!
                کامپایلر کاری میکنه که این زمان تغییر کنه
                جالبه برای من !
                کسی می تونه اطلاعات بیشتری بده؟
                { خلاف قوانین - پاک شد }

                دیدگاه


                  #9
                  پاسخ : مشکل با نوشتن تابع delay

                  نوشته اصلی توسط محمد حسینی
                  Periodic Interval Timer برای ایجاد تاخیر یه پریفرال خیلی خوب و جمع و جوره. بد نیست یه نگاه بهش بندازین.
                  برای استفاده از تایمر وقفه متناوب (PIT) هم می توانی مثال 15-1 صفحه 399 را ببین تاخیر برای 1 ثانیه می باشد.

                  دیدگاه


                    #10
                    پاسخ : مشکل با نوشتن تابع delay

                    کامپایلر کاری نمیکنه که "زمان تغییر کنه" بلکه کاری میکنه که بسته به نوع بهینه سازی درخواستی کد نهایی کوچکتر بشه یا سریعتر کار کنه. وقتی یک حلقه میذارین که قراره متغیر a از صفر شروع کنه و به عدد n برسه و کار خاصی هم توی حلقه انجام نمیشه یک کامپایلر خوب بایستی دقیقا این حلقه رو با عبارت a = n جابجا کنه. چون اصلا این قضیه تاخیر با اجرای حلقه کار درستی نیست. درست مثل اینه که یک ماشین فرمول یک بخرین. راننده فرمول یک هم استخدام کنین و بهش بگین: "وسط راه نگهدار من یه بستنی بخرم". اونم پیش خودش میگه: "خوب عزیز من همون اول پیست بستنی بخر" چون کسی قاعدتا وسط پیست اتوموبیلرانی بستنی نمیخره. اگه میخوای بری گردش و خرید از پیست برو بیرون!
                    (حالا ممکنه ربط زیادی هم نداشته باشه. ولی شما هم لطفی کنین یه جوری به هم ربطش بدین!!)

                    دیدگاه


                      #11
                      پاسخ : مشکل با نوشتن تابع delay

                      برای جلوگیری از بهینه سازی یه متغیر میشه از کلمه volatile استفاده کرد. البته تا بحال واسه حلقه استفاده نکردم. اما همچین مشکلی تو توابع وقفه زیاد پیش میاد و باید از volatile استفاده کرد.
                      ضمنا احتمالا حلقه رو با اسمبلی بنویسیم دیگه کامپایلر بهش کاری نداشته باشه...
                      https://www.linkedin.com/in/mohammadhosseini69

                      http://zakhar.blog.ir

                      دیدگاه


                        #12
                        پاسخ : مشکل با نوشتن تابع delay

                        توی گروه LPC2000 یه فایل گذاشته بودن که نویسنده اش نوشته بود تاخیر دقیق هست و به زبان اسبملی هست ولی من در کامپایلش به خطا بر خوردم و نتونستم درست کنمش
                        پیوست پست می کنم ببین شما یا بقیه بچه ها می تونن باهاش کار کنن ( پیوست هم که برای من بسته است اپلود می کنم جای دیگه)

                        http://ifile.it/mv9l14p

                        دیدگاه


                          #13
                          پاسخ : مشکل با نوشتن تابع delay

                          نوشته اصلی توسط Mohpooria

                          حیف که output converter نداره
                          ساخت خرو جی هم برای این نوشتم
                          کار زیاد سختی نیست
                          با قایل ielftool.exe و آرگومان ها ورودی خیلی راحت میشه باینری یا هگز ساخت
                          من داخل Eclipse اضافش کردم
                          پرگرامر SAMBA رو هم اضافه کردم به Eclipse
                          اگر کسی در این مورد ها مشکلی داشت بگه توضیح می دهم
                          فعلا وقت آموزش درست کردن ندارم انشالا به زودی یه آموزش کامل می گذارم برای همه قسمت ها

                          نوشته اصلی توسط محمد حسینی
                          برای جلوگیری از بهینه سازی یه متغیر میشه از کلمه volatile استفاده کرد. البته تا بحال واسه حلقه استفاده نکردم. اما همچین مشکلی تو توابع وقفه زیاد پیش میاد و باید از volatile استفاده کرد.
                          ضمنا احتمالا حلقه رو با اسمبلی بنویسیم دیگه کامپایلر بهش کاری نداشته باشه...
                          دقیقا تو وقفه چه مشکلی پیش میاد؟
                          کلمه volatile هنگام تعریف متغیر به کار میره دیگه؟

                          بله فکر کنم با اسمبلی نوشته بشه مشکلی نداره
                          چون کتابخانه avr-gcc هم همینجوریه
                          { خلاف قوانین - پاک شد }

                          دیدگاه


                            #14
                            پاسخ : مشکل با نوشتن تابع delay

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

                            تو بحث multi threading خیلی مطرح میشه...
                            https://www.linkedin.com/in/mohammadhosseini69

                            http://zakhar.blog.ir

                            دیدگاه


                              #15
                              پاسخ : مشکل با نوشتن تابع delay

                              مسئله شعور کامپایلر نیست. مسئله اینه که شما یا با قرار دادهای معمول کامپایلر کار میکنین یا باید برای هر موردی به کامپایلر حالی کنین که چجوری با هرچیزی برخورد کنه.
                              کامپایلر خوب؛ وظیفه اش اینه که کدی تولید کنه که هم کم حجم باشه و هم سریع. بنا براین یکی از سطوح بهینه سازی حذف کردن عملیاتیه که حذف اونها تغییری در نتایج نهایی کد نمیده. بنا براین اگر یک لوپ بنویسین و یک متغیر عمومی مثل i رو در اون اینجوری استفاده کنین:


                              for(i=0; i<1000; i++)
                              a = 5;


                              یک کامپایلر خوب باید بتونه این کد رو تولید کنه:

                              i = 1000;
                              a = 5;


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

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

                              تازه مورد دیگه ای که معمولا دردسر پیش میاره. اگر متغیری 16 بیتی داشته باشین و این متغیر در یک میکروی 8 بیتی مورد دسترسی قرار بگیره ممکنه در دسترسی به این متغیر از روال وقفه و روتین اصلی همزمانی پیش بیاد. مثلا فرض کنین این متغیر در وقفه یکی اضافه بشه. و در روتین اصلی مرتبا چاپ بشه. یک متغیر 16 بییتی در دو سیکل بار میشه و بعد از تغییر در دو سیکل مجدد پدیت میشه. حالا اگه متغیر در روال اصلی یکی از بایتهاش در رجیستری قرار بگیره و در همین حین وقفه کذایی پیش بیاد احتمال اینکه روال جاری شما عدد اشتباهی در رجیستر هاش بار کنه زیاده.

                              فرض کنیم متغیر مقدار 0xffff داشته باشه. در حینی که یک بایت از این متغیر در روال اصلی برنامه در یک رجیستر بار میشه وقفه ای پیش میاد و در اون وقفه این متغیر یکی اضافه میشه. و به روال اصلی برمیگرده. حالا تکلیف مقدار بار شده چی میشه؟ یا مقدار 0xff00 چاپ میشه یا مقدار 0x00ff که هر دو غلطه. اینجا از نظر من و شما دسترسی به مقدار این متغیر اصطلاحا atomic هست در صورتی که اینطوری نیست. حالا وقتی این مورد رو باهاش برخورد میکنیم چی باید بگیم؟ باگ کامپایلره؟ مسلما نه! اینجا دیگه مشکل از خودمونه که همه جوانب کارمون رو ندیدیم.

                              در این موارد دیگه از volatile هم کاری بر نمیاد.

                              دیدگاه

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