اطلاعیه

Collapse
No announcement yet.

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

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

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

    بله درسته. توضیح خوبی بود

    اما انصافا در موردی که من گفتم کامپایلر بی شعوره دیگه! :mrgreen: چه معنی داره وقتی یه متغیر رو به عنوان شرط می ذاریم، کامپایلر میاد شرط رو با عدد جایگزین میکنه و درنهایت شرط همیشه درست یا نادرست میشه!
    (البته پست قبلی شوخی کردم...)
    https://www.linkedin.com/in/mohammadhosseini69

    http://zakhar.blog.ir

    دیدگاه


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

      انصافا حرفتون راجع به بیشعوری کامپایلر درسته! چون اون یک برنامه ساده (از لحاظ عملیاتی) هست.
      اما مشکل از من و شماست که بدون شناخت کامل یک ابزار میخواییم ازش استفاده کنیم.
      از بابت delay که دارین راجع بهش اینجا بحث میکنین یاد حرفی از آرت بوخوالد افتادم. میگفت (نقل از مضمون):

      وقتی در یک هتل به صحبت های مسافر ها گوش میدین خیلی وقتها میتونین بفهمین که طرف اهل کدوم کشور یا فرهنگه. مثلا خیلی ها عادت دارن از مسئول هتل بخوان اونا رو صبح بیدار کنه. اما نحوه درخواستشون فرق میکنه. یک اسپانیایی نهایتا میگه: "لطف کنین منو صبح بیدار کنین." در صورتی که آمریکایی عموما میگه "منو ساعت 8 یا مثلا 8 و پنج دقیقه بیدار کنین".

      اینجا فقط مسئله درخواست مطرح نیست بلکه این فرم درخواست دادن نشون میده طرف نگاهش به یک موضوع ولو از نظر من و شمای نزدیک به فرهنگ اسپانیایی چقدر باریک یا دقیقه. البته خیلی وقتها میگیم: بی خیال! تو دیگه شورشو درآوردی یا شبیه اینا. ولی همین "اینا" باعث پیشرفت میشه. وگرنه بابا و بابابزرگ من و شما هم همینجوری با موضوعات متفاوت برخورد میکردن. ولی هیچ کدوم ادیسون نشدن.

      بگذریم.
      اما مشکل delay شما!!
      یکی از مواردی که قاعدتا بایستی در کار با سیستم های embedded لحاظ بشه غیر از مسئله سرعت و بهینه بودن اجرا و غیرهم؛ مسئله کاهش توان مصرفی دستگاهها هست. البته این هم مال جایی هست که میگن the time is gold نه جایی که "وقت از پهن هم بی ارزشتره" چون در همین جا انرژی چیزی هست که باید دخلشو آورد. از طرف دیگه همین انرژی که ما اغلب هیچش میگیریم باعث دردسر های جنبی هم میشه که دقتی نداریم. سیستمی که مدام برای تاخیر دادن از اجرای کد بهره میبره مسلما دارای توان تلفاتی بالاتری هم هست و این یعنی منبع تغذیه بزرگتر و گرانتر به همراه یک هیت سینک بهتر و قیمت بالاتر. غیر از این مسئله زمانی که شما در حال ایجاد تاخیر به این فرم هستین امکان انجام کار دیگه ای رو در عرض این کار ندارین بلکه در طول این کار انجام میشه. و شما از حالت موازی کار کردن به حالت سریال کار کردن پیش رفتین.

      البته بعضی موارد ممکنه احتیاج باشه که شما اینجوری کد بنویسین. اما این جا فکر نکنم از اون سری جاها باشه.
      من حتی زمانی که به تاخیرات در حد چند میکرو ثانیه دارم (مثلا بعضی جاها برای کار روی LCD گرافیکی روی یک سیستم سریع) از یک تایمر سخت افزاری برای زمانگیری استفاده میکنم تا در حین تاخیر بتونم یک سری کارهای دیگه ای هم انجام بدم. "برای توشیح بهتر این ایده میتونین با چیزایی مثل OverlappedIO در WindowsSDK سری بزنین."

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

      n = n + 1

      این کد ممکنه یک سیکل ساعت طول بکشه یا 50 سیکل. تازه به شرطی که وقفه ها خفه باشن. وگرنه ممکنه حتی بسته به حجم وقفه هایی که پیش میاد یا عملیاتی که در وقفه ها انجام میشه 5000 سیکل هم بشه.
      ممکنه این متغیر در یک رجیستر موجود باشه یا بایستی حتما از ram به داخل رجیستر آورده بشه و بعد سر جاش بره. این دیگه به شرایط ایجاد کد توسط کامپایلر در اون لحظه زمانی خاص برمیگرده. ممکنه احتیاج به اجرای روالی برای این increment داشته باشه. و خیلی چیزای دیگه.

      دیدگاه


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

        سلام
        در صورتی که نیاز به تاخیر با for دارید که البته کار خوبی نیست که از این روش استفاده کنید با توجه به توضیحات دوستان و بی شعور بودن کامپایلر که کد را تغییر می دهد و به صورت بهینه پیاده سازی می کند می توان برای جلوگیری از این کار کامپایلر در حلقه for یک رجیستر را بخوانید این کار را هم می توانید از رجیسترهای فقط خواندنی استفاده کنید و هیچ تاثیری بر روی کار میکرو نذارید به طور مثال تاخیر زیر حتما ایجاد می شود و کامپایلر ... نمی تواند کد آنرا تغییر دهد :biggrin:
        کد:
        void delay (void)
        {
        unsigned int i,j;
        for (i=0;i<0xfffff;i++)
         j=AT91C_BASE_PMC->PMC_SCSR;
        }

        دیدگاه


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

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

          دیدگاه


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

            من یه هدر برای ایجاد تاخیر با PIT نوشتم. فکرمیکنم دقت خیلی خوبی داره. این کد باهاش امتحان کردم :


            کد:
            	while (1){
            		delaypit_us(500);
            		*AT91C_PIOB_CODR = (1 << 20);
            		delaypit_us(500);
            		*AT91C_PIOB_SODR = (1 << 20);
            	}


            مولتیمتر، فرکانس پایه خروجی رو 0.999 کیلوهرتز نشون داد!!
            البته هنوز جا واسه کار داره. کدهای اسمبلیش رو بررسی میکنم تا چند سیکل اضافه رو هم درنظر بگیره.
            کد:


            کد:
            //	PITDELAY.h
            //	Delay using periodic interval timer (PIT) for AT91SAM7 series
            //	Written by Seyed Mohammad Hoseini
            //////////////////////////////////////////////////
            
            
            #ifndef	PIT_DELAY_HEADER
            #define	PIT_DELAY_HEADER
            
            #include <AT91SAM7X256.h>			//replace with other definitions header if necessary
            
            #define MCK_MHZ		(47.9232)		//master clock frequency	*(IMPORTANT)*
            #define	PIT_CLK		(MCK_MHZ/16)
            #define	PIT_PRD		(1/PIT_CLK)
            
            int volatile ResumeDelay;
            
            void init_delaypit(void);					//initialize
            __inline void delaypit_us(int delayval);	//delay microseconds
            __inline void delaypit_ms(int delayval);	//delay milliseconds
            
            
            __irq	void irq_PIT(void)
            {
            	int volatile tmp;
            	*AT91C_PITC_PIMR &= 0;
            	tmp = *AT91C_PITC_PIVR;
            	ResumeDelay = 1;
            
            	*AT91C_AIC_EOICR = 0;
            }
            
            void init_delaypit(void)
            {
            	AT91S_AIC *pAIC = AT91C_BASE_AIC;
            	pAIC->AIC_SMR[AT91C_ID_SYS] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | 7;
            	pAIC->AIC_SVR[AT91C_ID_SYS] = (unsigned long) irq_PIT;
            	pAIC->AIC_IECR = (1<<AT91C_ID_SYS);
            }
            
            __inline void delaypit_us(int delayval)
            {
            	ResumeDelay = 0;
            	delayval = (delayval/PIT_PRD);
            	*AT91C_PITC_PIMR = delayval | AT91C_PITC_PITEN | AT91C_PITC_PITIEN;
            	
            
            	while(!ResumeDelay);
            }
            
            __inline void delaypit_ms(int delayval)
            {
            	for (;delayval;delayval--)
            		delaypit_us(1000);
            }
            
            #endif


            اینو تاکید کنم باید فرکانس MCK رو اول هدر مشخص کنید.
            طبیعتا وقفه شماره یک یعنی وقفه سیستم استفاده شد. (گفتم حواستون باشه...)
            نظری برای بهتر شدنش دارین بدین
            استفاده م میکنین دعا فراموش نشه! :mrgreen:
            https://www.linkedin.com/in/mohammadhosseini69

            http://zakhar.blog.ir

            دیدگاه


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

              نوشته اصلی توسط حامد AT91
              سلام
              در صورتی که نیاز به تاخیر با for دارید که البته کار خوبی نیست که از این روش استفاده کنید با توجه به توضیحات دوستان و بی شعور بودن کامپایلر که کد را تغییر می دهد و به صورت بهینه پیاده سازی می کند می توان برای جلوگیری از این کار کامپایلر در حلقه for یک رجیستر را بخوانید این کار را هم می توانید از رجیسترهای فقط خواندنی استفاده کنید و هیچ تاثیری بر روی کار میکرو نذارید به طور مثال تاخیر زیر حتما ایجاد می شود و کامپایلر ... نمی تواند کد آنرا تغییر دهد :biggrin:
              کد:
              void delay (void)
              {
              unsigned int i,j;
              for (i=0;i<0xfffff;i++)
               j=AT91C_BASE_PMC->PMC_SCSR;
              }
              این زمان تاخیر به شدت هنگامی که شما از بهینه سازی استفاده کنید و مخصوصا کد برنامه زیاد بشه تغییر می کند(امتحان کردم چندین بار)
              برای این کار باید بهینه سازی را غیر فعال کنید و گرنه با تغییر کد این زمان هم تغییر می کند
              { خلاف قوانین - پاک شد }

              دیدگاه

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