اطلاعیه

Collapse
No announcement yet.

آموزش winavr و avrlib

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

    #61
    پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc

    ولله اینجور مواقع شاید زیاد وسواسی بنظر برسم. ولی تا بحال چندین و چند بار رعایت اینگونه موارد کارم رو راه انداخته. فعلا براتون بگم که این مسئله هفت هشت سیکل نیست. بعضی وقتها ممکنه حتی یک سیکل هم مسئله ساز باشه.
    دقیقا به خاطر همین مسئله هست که روی آرم با اون سرعتش چیزی بنام FIQ کنار IRQ داریم. البته من خودم تا بحال با FIQ کار نکردم ولی موردی که چند سال پیش بهش برخوردم این بود که میخواستم بدون استفاده از سخت افزار کمکی از سیستمی اطلاعات بگیرم که اون امکانی برای ارسال اطلاعاتش به من نداشت ولی هر 100 میلی ثانیه یکبار اطلاعاتی رو با فرکانس 20 کیلو هرتز روی یک سخت افزار دیگه ارسال میکرد. کنار اون خط سریالی هم داشتم که میبایستی پاسخ زمانی تقریبی 3 میلی ثانیه ای داشته باشه. اونجا مجبور شدم روال وقفه رو به اسمبلی بنویسم و دقیقا روی میکرو ثانیه هایم هم حساب باز کنم. چون در زمان پیک چیزی حدود 20 درصد وقت میکرو برای اسکن سیگنالها حروم میشد. برای پیاده سازی پروتکل سریال هم از ماشین حالت استفاده کردم. نتجه کار عالی بود. یعنی میکروی mega64 من با فرکانس کلاک 7.3728 خیلی از مواقع وقت زیادی برای تلف کردن داشت.

    یا جای دیگه ای برای پردازش گرافیکی اطلاعات برای شبیه سازی یک پرینتر مجبور شدم کلیه ترکیبات قرار دهی یک بیت پترن 8 بیتی رو داخل یک بیت پترن 128 بیتی دیگه به اسمبلی بنویسم تا حداکثر زمان اجرا برای بدترین ترکیبات حداکثر یک میکروثانیه باشه. با ذکر تمامی این موارد میشد کار رو انجام داد.

    حرف من اینه: اغلب موارد به این چیزا برنمیخوری اما باید دید درستی داشته باشی درست مثل قضیه PSTR که اشاره شد. چون ممکنه مین زیر پای خودت رها کنی. بعد تا بیای مشکلت رو حل کنی بقولی دم گاو بزمین اومده.

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

    نمیدونم تجربه سروکله زدن با سخت افزارهای متفاوت رو داشتی یا نه؟ اما بذار چیزی برات تعریف کنم. آمیگا 500. سیستمی تک با چند پروسسور. 68000 - agnes - denis - paula - clipper و غیره. اینا اسامی تجاری پروسسورهاشه. 512 کیلو بایت اول حافظه بطور مشترک توسط همه این پروسسورها مورد دسترسی قرار میگیره. معمولا برای هماهنگی مکانیسم buslock استفاده میشه. ولی در آمیگا برای حداکثر قدرت اینجوری نیست. 68000 در سیکل های زوج و بقیه در سیکل های فرد به این حافظه دسترسی پیدا میکنن. اصل کار با 68000 انجام میشه پس اون نباید سرعتش کاهش پیدا کنه. ولی بقیه با هم باید هماهنگ باشن. اگر قرار بود راه حل های به اصطلاح استاندارد استفاده بشه همون مکانیسم برای هماهنگی تمام پروسسورها استفاده میشد و آمیگا 500 این چیزی که حالا هست نبود. اینو میگن: the ART of computer programming

    دیدگاه


      #62
      پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc

      راستی اصل موضوع یادم رفت. کد اولیه!
      شما این کد رو مینویسی:


      static volatile int tmo;

      SIGNAL(SIG_OVERFLOW0)
      {
      if(tmo) tmo--;
      }



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


      //prolog code
      push r1
      push r0
      in r0,0x3f
      push r0
      clr r1
      push r24
      push r25

      // function code
      lds r24,tmo+0
      lds r25,tmo+1
      sbiw r24,0
      breq .L1
      sbiw r24,1
      sts tmo+0,r24
      sts tmo+1,r25
      .L1

      // epilog code
      pop r25
      pop r24
      pop r0
      out 0x3f,r0
      pop r0
      pop r1
      reti


      کد تولیدی سه قسمت داره. اول کد اولیه یا prolog که سیستم برای اجرای کد شما آماده میشه. که آماده سازی اولیه پشته و ذخیره رجیستر های رزرو در این قسمت انجام میشه. کد اصلی شما که قراره اجرا بشه و کد پایانی که همه چی رو مثل پشته به وضعیت اولیه برمیگردونه مثلا بازیابی مقادیر قبلی رجیستر های رزرو و همینطور برگشت به کدی که از اونجا این کد صدا زده شده (ret یا reti). که بهش کد پایانی یا epilog میگن. اگر قرار باشه کامپایلر این کد ها رو تولید نکنه (که بعضی جاها نیاز میشه) باید بهش اطلاع بدی کد اش برهنه یا naked است.

      دیدگاه


        #63
        پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc

        مثال یک کد اصطلاحا لخت (naked):

        کد:
        void exit_program(void) __attribute__((naked))
        {
          for(;;);
        }
        
        exit_program:
          rjmp exit_program
        
        void exit_program(void)
        {
          for(;;);
        }
        
        exit_program:
          rjmp exit_program
          ret <<----------- see, epilog code exists


        دیدگاه


          #64
          پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc

          راستی من متوجه نشدم در مورد PSTR چی می خواستی بگی
          یکم بیشتر توضیح میدی؟ من تا جایی که فهمیدم و امتحان کردم اگه یه رشته رو مستقیم به تابع بفرستیم (مثلا برای نوشتن رو LCD)، این رشته تو flash ذخیره نمیشه! اما با PSTR میره تو flash . نفهمیدم اشکالش کجا بود؟ یکم ساده تر بگو!
          راستی شما چند سالته؟ بنظر خیلی با تجربه میرسی!! ضمنا من سال دوم دانشگاهم و البته چیزایی هم که بلدم با سرچ و اینترنت و آزمون و خطا و ... تجربه کارای حرفه ای ندارم و حتی اسم سخت افزارها و سیستم هایی که نام بردی رو هم نشنیدم!!

          nacked رو هم متوجه شدم. جالب بود! ولی برام عجیبه که کجا ممکنه ما متوجه بشیم که لازم به ذخیره و بازیابی اطلاعات در استک نیست!؟ باید بریم کد اسمبلی رو ببینیم؟ اصلا اگه ret پاک بشه که دیگه برنمیگرده! (البته تابع exit دیگه خیلی تابلو ...)

          https://www.linkedin.com/in/mohammadhosseini69

          http://zakhar.blog.ir

          دیدگاه


            #65
            پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc

            من پست اول تاپیک رو ویرایش کردم و موضوعات مختلف رو همراه با لینک اولین پست قرار دادم. امیدوارم بقیه دوستان هم به کاملتر شدن تاپیک کمک کنند ...
            https://www.linkedin.com/in/mohammadhosseini69

            http://zakhar.blog.ir

            دیدگاه


              #66
              پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc

              من تا چند ساعت دیگه منزل هستم.جلال آل احمد میگفت: قرار بود نامه ای برای پدرم بنویسم. مختصر. اما کلی طول کشید. یک عمر کار در محضر ارزش حقوقی کلمات رو بهش آموخته بود. حالا نقل حال ماست. در اسمبلی همه چیز به عینه پیش چشم من و شماست ولی در یک زبان سطح بالا خیلی از مواقع نمیدونیم یک کامپایلر چگونه با کد ما برخورد میکنه. و این ندانستن ها باعث بروز خطر میشه. ببین در زمان کامپایل ما دو نوع هشدار داریم. error و warning. میدونی کدومشون خطرناکه؟ معلومه warning. چیزی که اغلب برنامه نویس ها براحتی ازش رد میشن. error رو تا رفع نکنی برنامه ات به اجرا نمیرسه. اما warning رو اگر رفع نکنی باگ بالقوه در زمان اجرا ایجاد میشه که فهمیدنش و رفعش خیلی بیشتر از دقت در نوشتن درست کدبرات هزینه داره. پس ما میخواییم اینجا بیشتر گاهی بدیم تا با دید باز از روی چاله چوله های توی راه رد بشیم. اما راجع به PSTR.

              این ماکرو چیزی رو در جایی قرار نمیده. اما اینکه شما میبینی با این ماکرو puts روی lcd کار میکنه بخاطر اینه که این رشته یک مقدار ثابت محسوب میشه. بنا بر این در جایی باید ذخیره بشه که بعدا بشه ازش استفاده کرد. خوب توی میکرو اینجا کجاست؟ معلومه....فلش. اما ماکروی PSTR <<<آدرس رشته رو به صورت یک اشاره گر به کاراکتری که در فلش ذخیره شده برمیگردونه>>> یعنی اگر شما این رشته رو در رم قرار بدی هم این ماکرو تعبیر خودش رو به کامپایلر <<<تفهیم>>> میکنه. مثلا تابعی مثل memcpy_P دارای فرم نمادین زیره:


              void * memcpy_P (void *, PGM_VOID_P, size_t)


              یعنی آرگومان دومش یک <<اشاره گر به هر چیزی در فلش هست>>. اگر من به جاش آدرس مثلا یک متغیر محلی int رو قرار بدم برای میکرو فرقی نمیکنه ولی برای من فرق میکنه. PSTR دید صحیح رو القاء میکنه.

              بذار یه جور دیگه بگم. شما بنظر میاد دانشجوی سخت افزاری. پس مسلما باید بدونی فرق بین 74244 و 74245 چیه. اما خیلی جاها دوستان از 74245 که یک bus driver هست بجای بافر 74244 استفاده میکنن و پایه dirشو مستقیما به vcc یا gnd وصل میکنن. این مسئله از لحاظ تکنیکی مشکلی نداره و کار میکنه. اما از لحاظ استاندارد سازی تا حدودی غلطه. چون من که بعدا این شماتیک رو میبینم اینجوری تعبیر میکنم:

              74245 یک line driver هست پس منطقا ممکنه سیگنالها از طرف a به b برن یا بالعکس. اما اگر جهت عکس باشه که اونطرفش یک خروجی هست پس باید یکی از آی سی ها بره تو آسمون. تازه بعد از کلی نگاه کردن روی شماتیک متوجه تکنیک بکار رفته میشم. اما شاید تا موقعی که یکی این مورد رو به من گوشزد نکنه متوجه نمیشم.
              توجه داشته باشین که <<<در شرایط ایده آل>>> نبایستی اینجوری و بدتر از اون کلیشه ای طراحی و پیاده سازی سخت افزار یا نرم افزار انجام داد. اما اگر دیدتون درست باشه و با گاهی کامل صورت بگیره...خوب...کار شماست. به کسی ربطی نداره.

              ضمنا شما روی یک سیستم از هر نظری فوق العاده محدود دارین کار میکنین. باید <<< حواستون به خیلی چیزا جمع باشه>>>.

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

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

              فعلا برای امروز زیادی هم هست.
              با اجازه.

              دیدگاه


                #67
                پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc

                دوستان یه سوال خیلی ساده: میگین با progmem یه متغیری رو توی flash ذخیره میکنین. منظورتون همون حافظه فلشی هست که برنامه میکرو (همون هگز) رو توش می ریزیم؟

                میشه یکم توضیح بدین؟

                ممنونم
                http://ceworld.ir/images/ads/dornablogcom_ads.gif

                دیدگاه


                  #68
                  پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc

                  نوشته اصلی توسط behnam_kh2002
                  دوستان یه سوال خیلی ساده: میگین با progmem یه متغیری رو توی flash ذخیره میکنین. منظورتون همون حافظه فلشی هست که برنامه میکرو (همون هگز) رو توش می ریزیم؟
                  میشه یکم توضیح بدین؟
                  بله. از اونحایی که تو حافظه فلش ذخیره میشن، دیگه قابل تغییر نیستن و اصطلاحا بهشون میگیم ثابت (constant)
                  https://www.linkedin.com/in/mohammadhosseini69

                  http://zakhar.blog.ir

                  دیدگاه


                    #69
                    پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc

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

                    http://ceworld.ir/images/ads/dornablogcom_ads.gif

                    دیدگاه


                      #70
                      پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc

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

                      http://zakhar.blog.ir

                      دیدگاه


                        #71
                        پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc

                        آخیییییش!!! بالاخره از جهنم اهواز برگشتم!

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

                        اصولا فلش برای قرار دادن کد برنامه یا مقادیر ثابتی که به صورت عادی امکان تغییرشون وجود نداره استفاده میشه.
                        eeprom هم برای مقادیری که مثل flash هست ولی اولا امکان تغییر داره ثانیا نبایستی در هنگام قطع برق مقادیرش از بین بره. و ثالثا خیلی زیادتر از محتویات فلش ممکنه مورد دسترسی برای تغییر صورت بگیره. چون همونطور که میدونین محتوای فلش رو هم میشه با spm تغییر داد اما میزان تغییراتش از eeprom کمتره.

                        کلا فلش برای ذخیره مقادیر ثابت - کد اجرایی و مقادیر اولیه متغیر های برنامه استفاده میشه. این یکی آخری رو بایستی توضیح بدم. فرض کنین داریم:

                        int i=17;

                        اگر این یک متغیر محلی باشه این دستور منجر به تولید دستوری میشه که مقدار این متغیر رو در ابتدای اجرای تابع مربوطه مساوی با 17 قرار بده. اما اگه متغیر عمومی باشه مقدار عددی 17 در فلش قرار داده میشه تا قبل از اجرای تابع main از فلش به داخل متغیر i ریخته بشه.

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

                        دیدگاه


                          #72
                          پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc

                          راستی حالا که دارین راجع به WinAVR بحث میکنین یه کمی هم میشه راجع به نحوه نوشتن بلوک های اسمبلی در WinAVR یه چیزایی نوشت. اگر هم امکانش باشه میتونم pdf اش رو برای یکی email کنم. راسیتش من با 4share و اینجور چیزا بلد نیستم کار کنم.

                          دیدگاه


                            #73
                            پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc

                            اینم کتابی که آقا رضا میگفتند:
                            http://www.4shared.com/document/auWpYJN3/GCCAVR_Inline_Assembler_Cook_B.html

                            [img width=477 height=100]http://www.eca.ir/pic/upload/agazade.png[/img]

                            دیدگاه


                              #74
                              پاسخ : آموزش winavr و avrlib - مهاجرت از codevision به winavr avr gcc

                              عجب غلطی کردم!!
                              پس بذارین از جند تا چیز اولیه شروع کنم. توضیح واضحات!

                              32 تا رجیستر داریم. 16 تای اول قابلیت مقدار دهی بصورت مستقیم ندارن ولی اون 16 تای دیگه میتونن مستقیما با دستور ldi مقدار دهی بشن. 3 زوج آخر یعنی رجیستر های 26 الی 31 میتونن دو تا دو تا در عملیات word based استفاده بشن و ایضا برای ایندکس هم استفاده بشن. اگر از خاصیت indexing شون بگذریم رجیستر های 24 و 25 هم همینطوری هستن.

                              موارد استفاده در کدهای تولید شده توسط WinAVR:
                              رجیستر r0 برای استفاده temporary استفاده میشه. مثلا برای عملیات دم دستی و دسترسی به اطلاعات داخل فلش در شرایطی که از atmega استفاده نمیشه. (توضیح: lpm و elpm در atmega میتونه روی هر رجیستری کار کنه ولی در بقیه موارد این دستورات مقدار برگشتی رو در r0 قرار میدن.
                              مقدار صفر مقدار پر کاربردیه. برای پرهیز از صفر کردن یک رجیستر با clr یا eor یا ldi از رجیستر r1 برای نگهداری مقدار صفر استفاده میشه.
                              رجیستر های r16 تا r31 برای استفاده های عمومی استفاده میشه بنا براین فرض بر اینه که ممکنه مقدارشون در هر تابع عوض شده باشه. ولی بقیه رجیستر ها بایستی مقدار شون قبل و بعد از اجرای یک تابع ذخیره و سپس بازیابی بشه.

                              حالا یک نگاهی به پست های قبلی میندازیم: کد آغازین و پایانی روال وقفه:


                              //prolog code
                              push r1
                              push r0
                              in r0,0x3f
                              push r0
                              clr r1
                              push r24
                              push r25

                              // function code
                              ...

                              // epilog code
                              pop r25
                              pop r24
                              pop r0
                              out 0x3f,r0
                              pop r0
                              pop r1
                              reti


                              تفسیر:
                              این یک روتین وقفه است پس ممکنه در هر موقعی (هر جای روال در حال اجرایی) اجرا بشه. ضمنا معلوم نیست که شرایط رجیستر ها در اون لحظه چطوری بوده. اما چون میخواییم کد C بنویسیم باید شرایط دلخواه کامپایلر WinAVR رو ایجاد کنیم (در کد ویژن رجیستر ها استفاده های متفاوتی دارن). خوب:

                              مقدار قبلی رجیستر های r0 و r1 رو ذخیره میکنیم. با استفاده از r0 مقدار status word رو گرفته و ذخیره میکنیم. و r1 رو مساوی با صفر قرار میدیم. از این به بعد هر رجیستری که مورد استفاده قرار گرفته شده باشه بایستی ذخیره بشه و در هنگام بازگشت مقدارش بازیابی بشه. که اینجا فقط r24 و r25 استفاده شده بوده.

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

                              اگر غیر از این فرض کنیم شاید کد ما کار کنه ولی مطمئنا جایی پیش میاد که اجرای برنامه مختل میشه.
                              ضمنا این مسئله همیشه باید آویزه گوشمون باشه (خیلی ادبی شد!) که در شرایط مساوی کدی که کامپایلر تولید میکنه از بابت بهینه بودن عمدتا به پای کدی که ما مینویسیم نمیرسه.

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

                              ..... ادامه داره.... (اما کی بشه نمیدونم!!!)

                              دیدگاه


                                #75
                                پاسخ : آموزش winavr و avrlib

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

                                #include <avr/io.h>
                                #include <avr/interrupt.h>
                                #include <util/delay.h>
                                #include "lcd_lib.c"

                                int n=0;
                                int r=0;
                                ISR(SIG_OUTPUT_COMPARE1A)
                                {
                                n++;
                                if (n==20)
                                {
                                r = 1;
                                }
                                }

                                int main()
                                {
                                sei();
                                DDRB=0xff;
                                _delay_ms(1000);
                                PORTB=0xff;
                                //Timer1: CTC
                                TIMSK |= (1<<OCIE1A);
                                TCCR1A= 0b00000000;
                                TCCR1B =0b00001001;
                                OCR1A = 50000;

                                while(1)
                                {
                                if (r==1)
                                {
                                PORTB=0x00;
                                }
                                }
                                return 0;
                                }



                                میخوام با تایمر یه تاخیر 50 میلی ثانیه ای ایجاد کنم...
                                بعد از 20 بار اجرای وقفه، متغیر r باید 1 بشه و تو حلقه تابع main ، پورت b خاموش بشه... اما نمیشه !! خیلی عجیبه! وقفه اجرا میشه. دستور صفر کردن پورت B رو بردم تو تابع وقفه و بجای r=1 نوشتم جواب داد!! اما اینطوری که میبینین جواب نمیده!! مشکل چیه؟
                                https://www.linkedin.com/in/mohammadhosseini69

                                http://zakhar.blog.ir

                                دیدگاه

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