اطلاعیه

Collapse
No announcement yet.

کوچ کردن از کدویژن به AtmelStudio

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

    پاسخ : کوچ کردن از کدویژن به AtmelStudio

    تاکنون فرصت نشده بود محتوای این تاپیک را ببینم و در همینجا از جناب مرتضوی بابت صرف زمان و قرار دادن پاسخ های بسیار مفید تشکر می کنم. در فرصت جاری، چند صفحه ابتدایی تاپیک را مرور کردم و در پست شماره 44، پاسخی داده شده که تا حدی نیاز به تجدید نظر و توضیح بیشتر دارد. سوال شده:

    تفاوت این دو چیه

    کد:
    UCSRA=(1<<MPCM)
    UCSRA|=(1<<MPCM)
    (در متن سوال UCSRB نوشته شده که UCSRA صحیح است). در پاسخ نوشته شده:

    نوشته اصلی توسط RubeuS
    دستور اول بیت MPCM را یک و بقیه بیت ها را صفر میکنه.

    دستور دوم بیت MPCM را یک میکنه و بقیه بیت ها را دست نمیزنه و مقدار قبلیشون میمونن.
    هرچند پاسخ داده شده بصورت عمومی صحیح است. اما برای رجیسترهایی که flag هایی در آنها وجود دارد که با نوشتن 1 پاک می شوند (از جمله TXC در UCSRA ) باید به یک مسئله مهم توجه شود. اگر این flag از قبل یک شده باشد، اجرای دستور
    کد:
    UCSRA|=(1<<MPCM)


    علاوه بر یک کردن MPCM باعث صفر شدن و تغییر وضعیت بیت TXC هم می شود. در حالیکه هدف از اجرای این دستور فقط مقداردهی به MPCM بوده و نه تغییر وضعیت TXC.
    این یک قاعده کلی برای مقدار دهی به رجیستر های محتوای flag ها است که اگر احتمال یک بودن هر یک از آن flag ها وجود داشته باشد و از نوعی باشند که نوشتن 1 در محل آنها باعث پاک شدن بیت متناظر در رجیستر شود، نباید از اپراتور =| برای مقدار دهی برای این نوع رجیسترها استفاده شود. زیرا اگر این بیت از قبل 1 شده باشد، خواندن و OR کردن آن بیت با خود باعث 0 شدن ناخواسته flag می شود (مگر اینکه چنین منظوری بصورت عمدی وجود داشته باشد). برای چنین رجیسترهایی در صورت وجود چنین شرایطی فقط باید از اپراتور = استفاده شود و در محل بیت هایی که احتمال 1 بودن آنها وجود دارد، باید 0 نوشته شود تا تغییری در وضعیت این نوع بیت ها بوجود نیاید.
    بنابراین در این مورد به خصوص، دستور اول MPCM را یک و U2X را صفر می کند، اما بقیه بیت هایی که از نوع flag هستند، بدون تغییر باقی می مانند. دستور دوم هم می تواند بنا به توضیحات داده شده باعث تغییر TXC شود. (از جهت دیگری هم استفاده از اپراتور =| برای این رجیستر مجاز نیست و آن لزوم نوشتن 0 در برخی بیت های آن بنا به تصریح datasheet است.)
    اوژن: به معنای افکننده و شکست دهنده است
    دانایی، توانایی است-Knowledge is POWER
    برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
    وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
    قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
    اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
    ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

    دیدگاه


      پاسخ : کوچ کردن از کدویژن به AtmelStudio

      با اجازه ی دوستان به ادامه ی بحث در رابطه با حافظه ی فلش می پردازم:

      در قسمت قبل دیدیم که چطور به کامپایلر بگیم که دیتا آبجکت ما را درون حافظه ی فلش قرار دهد:

      در این قسمت قصد دارم به نحوه ی خواندن( read ) اطلاعات از حافظه ی فلش بپردازم:

      برای اینکار توابعی در فایل pgmspace اعلان شده که به ما کمک میکند:

      به عنوان مثال توسط کد زیر دیتا آبجکتی درون حافظه ی فلش قرار میدهیم:
      کد:
      #include <avr/pgmspace.h>
      static const int i PROGMEM = 0x076f;
      int main()
      {
      	
      	while(1);
      }

      شما میتوانید با استفاده از دیباگ کردن برنامه که در پست اول توضیح داده شد ، کاملا محتویات حافظه ی فلش را بررسی کنید.

      بریم سراغ خوندن دیتا آبجکتمون:
      اینجاست که باید به یک مساله ی مهم در رابطه با میکرویی که کار میکنید اشاره کنم:
      شما اگر از میکرویی استفاده میکنید که حافظه ی فلش آن بیش از 64 کیلو بایت است، این یعنی برای آدرس بندی به اشاره گر بزرگتر از 16 بیتی نیاز دارید.
      و به اصلاح باید با اشاره گر های far به دیتا آبجکتهای داخل فلش دسترسی پیدا کنید.

      با فرض اینکه مقدار حافظه ی فلش کوچکتر از 64 کیلو بایت باشه و به اصطلاح آدرس بندی در اون near باشه ، میریم سراغ توابع خواندن از حافظه ی فلش:

      لیست توابع به صورت زیر است که باید متناسب با دیتا آبجکتی که میخواهیم بخونمش ، از تابع مناسب استفاده کنیم(البته بنده به اینها شبه تابع میگم):

      کد:
      	pgm_read_byte_near(); 
      	pgm_read_word_near(); 
      	pgm_read_dword_near(); 
      	pgm_read_float_near();
      البته اگر near هم برداشته شود ، به صورت پیشفرض از توابع near استفاده میشود.


      خوب ما دیتا آبجکتمون چی بود؟؟
      اره یک int دوبایتی بود. پس باید از تابع pgm_read_word_near استفاده کنیم.

      پس کد زیر مقدار موجود در دیتا آبجکتمون را میخونه و داخل متغییر x که یک دیتا آبجکت درون حافظه ی SRAM است میریزه:

      کد:
      static const int i PROGMEM = 0x076f;
      int main()
      {
      	int x;
      	x=pgm_read_word_near(&i);
      	 
      	while(1);
      }
      فقط توجه شود که این توابه آدرس میگیرند و من با قرار دادن عملگر & قبل از i ،آدرس دیتا آبجکت موجود در فلش را به تابع دادم

      والسلام

      راه اندازی ماژول nrf24l01p برای codevision (ارتباط بیسیم بین دو میکرو) : http://www.eca.ir/forum2/index.php?topic=78587.0
      کوچ کردن از کدویژن به http://www.eca.ir/forum2/index.php?topic=81025.0 : AtmelStudio
      نحوه نوشتن اصولی یک لایبرری و درایور نرم افزاری( بصورت ساده) : http://www.eca.ir/forum2/index.php?topic=81071
      http://www.eca.ir/forum2/index.php?topic=82130.0 سفارش راه انداز ماژول های مختلف توسط اعضای انجمن
      انشالله به زودی تاپیک ها به روز رسانی خواهد شد،

      دیدگاه


        پاسخ : کوچ کردن از کدویژن به AtmelStudio

        اول از هر چیز خیلی خیلی ممنونم از تو سید که واقعا برای این تاپیک وقت میذاری.
        یه سوال داشتم از خدمتت:
        در تابع lcd.c من به یک همچین شرطی برخوردم:
        کد:
        while(inb(LCD_DATA_PIN) & 1<<LCD_BUSY) // LCD_BUSY=7
        میخاستم بدونم کی شرط حلقه برقرار میشه و چطوری و کی برقرار نیست؟
        پیشاپیش از لطفی که خواهی کرد ممنوم.




        دیدگاه


          پاسخ : پاسخ : کوچ کردن از کدویژن به AtmelStudio

          نوشته اصلی توسط طراح
          تاکنون فرصت نشده بود محتوای این تاپیک را ببینم و در همینجا از جناب مرتضوی بابت صرف زمان و قرار دادن پاسخ های بسیار مفید تشکر می کنم. در فرصت جاری، چند صفحه ابتدایی تاپیک را مرور کردم و در پست شماره 44، پاسخی داده شده که تا حدی نیاز به تجدید نظر و توضیح بیشتر دارد. سوال شده:

          (در متن سوال UCSRB نوشته شده که UCSRA صحیح است). در پاسخ نوشته شده:

          هرچند پاسخ داده شده بصورت عمومی صحیح است. اما برای رجیسترهایی که flag هایی در آنها وجود دارد که با نوشتن 1 پاک می شوند (از جمله TXC در UCSRA ) باید به یک مسئله مهم توجه شود. اگر این flag از قبل یک شده باشد، اجرای دستور
          کد:
          UCSRA|=(1<<MPCM)


          علاوه بر یک کردن MPCM باعث صفر شدن و تغییر وضعیت بیت TXC هم می شود. در حالیکه هدف از اجرای این دستور فقط مقداردهی به MPCM بوده و نه تغییر وضعیت TXC.
          این یک قاعده کلی برای مقدار دهی به رجیستر های محتوای flag ها است که اگر احتمال یک بودن هر یک از آن flag ها وجود داشته باشد و از نوعی باشند که نوشتن 1 در محل آنها باعث پاک شدن بیت متناظر در رجیستر شود، نباید از اپراتور =| برای مقدار دهی برای این نوع رجیسترها استفاده شود. زیرا اگر این بیت از قبل 1 شده باشد، خواندن و OR کردن آن بیت با خود باعث 0 شدن ناخواسته flag می شود (مگر اینکه چنین منظوری بصورت عمدی وجود داشته باشد). برای چنین رجیسترهایی در صورت وجود چنین شرایطی فقط باید از اپراتور = استفاده شود و در محل بیت هایی که احتمال 1 بودن آنها وجود دارد، باید 0 نوشته شود تا تغییری در وضعیت این نوع بیت ها بوجود نیاید.
          بنابراین در این مورد به خصوص، دستور اول MPCM را یک و U2X را صفر می کند، اما بقیه بیت هایی که از نوع flag هستند، بدون تغییر باقی می مانند. دستور دوم هم می تواند بنا به توضیحات داده شده باعث تغییر TXC شود. (از جهت دیگری هم استفاده از اپراتور =| برای این رجیستر مجاز نیست و آن لزوم نوشتن 0 در برخی بیت های آن بنا به تصریح datasheet است.)
          قبل از همه چیز از استاد گرامی ، جناب کی نژاد تشکر میکنم.


          در رابطه با اون پست در رابطه با بیت MPCM بله حق با شماست و این از کم دقتی بنده بوده ( البته فکر میکنم دلیلش اینبوده که کلا منظور از سوال ایشون محل وجود این بیت نبوده ولی در هر صورتی این یک کم دقتی بوده و دلیلی نداره)

          در رابطه با قسمت دوم هم : ممنون برای تذکرتون .
          بله همین طور که می فرمایید در صورتی که فلگی یک باشد و این دستور اجرا شود باعث صفر شدن فلگ میشود.

          پست مربوطه ویرایش شد.

          با اجازه جناب کی نژاد برای اینکه توضیحات ایشون را کامل کنم در رابطه با طراحی فلگ ها در میکرو عکس زیر را قرار میدهم(از یک jk فیلیپ فلاپ برای اینکار استفاده شده)(به خاطر بدخط بودن عذر خواهی میکنم):

          http://mortazavi91.persiangig.com/image/DSC_0810.jpg

          جناب کی نژاد دنبال کردن این تاپیک توسط شما و تحلیلتون باعث دلگرمی بنده میشود ، از این مهم بسیار خوشحال میشوم.
          با کمال تشکر -
          راه اندازی ماژول nrf24l01p برای codevision (ارتباط بیسیم بین دو میکرو) : http://www.eca.ir/forum2/index.php?topic=78587.0
          کوچ کردن از کدویژن به http://www.eca.ir/forum2/index.php?topic=81025.0 : AtmelStudio
          نحوه نوشتن اصولی یک لایبرری و درایور نرم افزاری( بصورت ساده) : http://www.eca.ir/forum2/index.php?topic=81071
          http://www.eca.ir/forum2/index.php?topic=82130.0 سفارش راه انداز ماژول های مختلف توسط اعضای انجمن
          انشالله به زودی تاپیک ها به روز رسانی خواهد شد،

          دیدگاه


            پاسخ : کوچ کردن از کدویژن به AtmelStudio

            نوشته اصلی توسط سینا_80
            اول از هر چیز خیلی خیلی ممنونم از تو سید که واقعا برای این تاپیک وقت میذاری.
            یه سوال داشتم از خدمتت:
            در تابع lcd.c من به یک همچین شرطی برخوردم:
            کد:
            while(inb(LCD_DATA_PIN) & 1<<LCD_BUSY) // LCD_BUSY=7
            میخاستم بدونم کی شرط حلقه برقرار میشه و چطوری و کی برقرار نیست؟
            پیشاپیش از لطفی که خواهی کرد ممنوم.
            خواهش میکنم.
            بنده هم از همه ی دوستانی که سوال می پرسند و نظر میدهند ، تشکر میکنم.

            -----------------------------

            خوب بریم سراغ تحلیل شرط حلقه ای که قرار دادید:

            قبلش باید 3 چیز معین شود :
            1- ()inb: که با توجه به هدرفایل deprecated.h و دیفاین زیر بررسی میشود(البته هر تعریف دیگه ای میتونه باشه ولی میشه حدس زد به شکل زیره) :
            کد:
            #define inb(port) (port)
            2- LCD_DATA_PIN : معلومه که اول فایل هدر مربوط به کتابخانه ی استفاده شده ، با استفاده یک تعریف ، یکی از رجیسترهای به شکل PINX به این شکل تعریف میشود. من به عنوان مثال دیفایت زیر را فرض میگیرم:
            کد:
            #define LCD_DATA_PIN  PIND
            3- LCD_BUSY : این هم فکر میکنم همون طور که جلوش کامنت شده برابر 7 است.

            خوب با این فرضیات میریم سرغ تحلیلش:
            همیشه برای تحلیل اینجوری عمل کنید:
            مرحله 1:
            کد:
            while(inb(LCD_DATA_PIN) & 1<<LCD_BUSY)
            البته یه چیز بگم:
            بهتره اون شیفت تو چرانتز قرار گیرد ولی اینجا چون اولویت عملگر شیفت منطقی بیشتر از AND منطقی ( & ) است ، مشکلی بوجود نمی آید . ولی بهتره پرانتز گذاری رعایت شود(به خوانایی برنامه هم کمک میکند)
            ------------

            مرحله 2:
            کد:
            while(inb(PIND) & 1<<7)
            ------------

            مرحله 3:
            کد:
            while(PIND & 0x80)
            ------------

            خوب حالا تحلیل نهایی:
            موقعی که بیت شماره ی 7 ( msb ) از رجیستر PIND یک باشد شرط حلقه برقرار است و وقتی صفر باشد پردازنده وارد حلقه نمیشود.
            یعنی اگر پورت D میکرو به عنوان ورودی بگیریم : در صورتی که روی پایه ی 7 آن یک باشد(ولتاژ باشد) شرط حلقه برقرار میشود و در صورتی که صفر باشد شرط برقرار نمیشود.

            البته به نظر میرسه این برای خواندن status چیپ کنترلر السیدی است و بیت 7 از اطلاعات دریافت شده نشان دهنده آزاد بودن یا مشغول بودن چیپ است .


            راه اندازی ماژول nrf24l01p برای codevision (ارتباط بیسیم بین دو میکرو) : http://www.eca.ir/forum2/index.php?topic=78587.0
            کوچ کردن از کدویژن به http://www.eca.ir/forum2/index.php?topic=81025.0 : AtmelStudio
            نحوه نوشتن اصولی یک لایبرری و درایور نرم افزاری( بصورت ساده) : http://www.eca.ir/forum2/index.php?topic=81071
            http://www.eca.ir/forum2/index.php?topic=82130.0 سفارش راه انداز ماژول های مختلف توسط اعضای انجمن
            انشالله به زودی تاپیک ها به روز رسانی خواهد شد،

            دیدگاه


              پاسخ : کوچ کردن از کدویژن به AtmelStudio

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

              البته من قبلا در پست اول در این رابطه نوشته بودم ولی به دلیل اشتباه هنگام ویرایش پست ، مطالب پاک شد:

              قبلش توصیه میکنم برای درک مفهوم پست های زیر را بخونید:
              http://www.eca.ir/forum2/index.php?topic=81025.msg505301#msg505301

              http://www.eca.ir/forum2/index.php?topic=81025.msg505353#msg505353

              خوب چون من تو این تاپیک میخوام بیشتر به نحوه ی برنامه نویسی در محیط اتمل استادیو بپردازم و با فرض اینکه شما دوستان با یه سری اصول توسط برنامه نویسی در محیط کدویژن آشنایید، خیلی مختصر توضیح میدم:
              در اینجا ما فایل هدری به این منظور داریم که باید اینکلود شود:
              کد:
              #include <avr/interrupt.h>
              این هدر توابع خوبی را برای اینکار فراهم میکنند.
              اولین گروه برای فعال و غیر فعال کردن وقفه های سراسری است( صفر و یک کردن فلگ مربوطه ( بیت شماره 7 از رجیستر SREG ) )
              کد:
              sei(); 
              
              cli();
              همون طور که میدونید در کدویژن برای نوشتن روتین یک وقفه از کلمه ی کلیدی interrupt استفاده میشد. ولی اینجا میتونید برای اینکار از تابع ()ISR استفاده کنید.
              چجوری؟
              بتون میگم ... عجله نداشته باشید

              یادتونه تو کدویژن بعد از interrupt چی مینوشتید؟
              اره آفرین... برای مشخص کردن نوع وقفه اسم یا آدرس مربوط به وقفه را در بین دو کروشه مشخص میکردیم.
              برای اینکار در اینجا باید اسم یا آدرس مربوط به وقفه مورد نظر را به عنوان اولین پارامتر به تابع ISR بدید.
              او او ... صبر کنید .. کجا؟ اینجا اسم ها یکم متفاوته!!
              ولی نگران نباشید... برید در فایل هدر مربوط به میکروتون و اسم مربوط به وقفه ی مورد نظرتون رو بدست آورید.
              چی؟ فایل هدر مربوط به میکروتون کجاست؟
              خوب تو پست اول توضیح دادم تو هدر avr/io.h باید بگردید دنبالش .
              من در اینجا هدر مربوط به میکرو مگا32 رو مثال میزنم که هدر مربوطه میشه: avr/iom32.h

              خوب یک قسمتش به صورت کامنت گفته: Interrupt vectors
              من دقیقا دیفاین های زیرش رو براتون میزارم:
              کد:
              /* Interrupt vectors */
              
              /* External Interrupt Request 0 */
              #define INT0_vect_num		1
              #define INT0_vect			_VECTOR(1)
              #define SIG_INTERRUPT0			_VECTOR(1)
              
              /* External Interrupt Request 1 */
              #define INT1_vect_num		2
              #define INT1_vect			_VECTOR(2)
              #define SIG_INTERRUPT1			_VECTOR(2)
              
              /* External Interrupt Request 2 */
              #define INT2_vect_num		3
              #define INT2_vect			_VECTOR(3)
              #define SIG_INTERRUPT2			_VECTOR(3)
              
              /* Timer/Counter2 Compare Match */
              #define TIMER2_COMP_vect_num	4
              #define TIMER2_COMP_vect		_VECTOR(4)
              #define SIG_OUTPUT_COMPARE2		_VECTOR(4)
              
              /* Timer/Counter2 Overflow */
              #define TIMER2_OVF_vect_num		5
              #define TIMER2_OVF_vect			_VECTOR(5)
              #define SIG_OVERFLOW2			_VECTOR(5)
              
              /* Timer/Counter1 Capture Event */
              #define TIMER1_CAPT_vect_num	6
              #define TIMER1_CAPT_vect		_VECTOR(6)
              #define SIG_INPUT_CAPTURE1		_VECTOR(6)
              
              /* Timer/Counter1 Compare Match A */
              #define TIMER1_COMPA_vect_num	7
              #define TIMER1_COMPA_vect		_VECTOR(7)
              #define SIG_OUTPUT_COMPARE1A		_VECTOR(7)
              
              /* Timer/Counter1 Compare Match B */
              #define TIMER1_COMPB_vect_num	8
              #define TIMER1_COMPB_vect		_VECTOR(8)
              #define SIG_OUTPUT_COMPARE1B		_VECTOR(8)
              
              /* Timer/Counter1 Overflow */
              #define TIMER1_OVF_vect_num		9
              #define TIMER1_OVF_vect			_VECTOR(9)
              #define SIG_OVERFLOW1			_VECTOR(9)
              
              /* Timer/Counter0 Compare Match */
              #define TIMER0_COMP_vect_num	10
              #define TIMER0_COMP_vect		_VECTOR(10)
              #define SIG_OUTPUT_COMPARE0		_VECTOR(10)
              
              /* Timer/Counter0 Overflow */
              #define TIMER0_OVF_vect_num		11
              #define TIMER0_OVF_vect			_VECTOR(11)
              #define SIG_OVERFLOW0			_VECTOR(11)
              
              /* Serial Transfer Complete */
              #define SPI_STC_vect_num		12
              #define SPI_STC_vect			_VECTOR(12)
              #define SIG_SPI				_VECTOR(12)
              
              /* USART, Rx Complete */
              #define USART_RXC_vect_num		13
              #define USART_RXC_vect			_VECTOR(13)
              #define SIG_USART_RECV			_VECTOR(13)
              #define SIG_UART_RECV			_VECTOR(13)
              
              /* USART Data Register Empty */
              #define USART_UDRE_vect_num		14
              #define USART_UDRE_vect			_VECTOR(14)
              #define SIG_USART_DATA			_VECTOR(14)
              #define SIG_UART_DATA			_VECTOR(14)
              
              /* USART, Tx Complete */
              #define USART_TXC_vect_num		15
              #define USART_TXC_vect			_VECTOR(15)
              #define SIG_USART_TRANS			_VECTOR(15)
              #define SIG_UART_TRANS			_VECTOR(15)
              
              /* ADC Conversion Complete */
              #define ADC_vect_num		16
              #define ADC_vect			_VECTOR(16)
              #define SIG_ADC				_VECTOR(16)
              
              /* EEPROM Ready */
              #define EE_RDY_vect_num		17
              #define EE_RDY_vect			_VECTOR(17)
              #define SIG_EEPROM_READY		_VECTOR(17)
              
              /* Analog Comparator */
              #define ANA_COMP_vect_num		18
              #define ANA_COMP_vect			_VECTOR(18)
              #define SIG_COMPARATOR			_VECTOR(18)
              
              /* 2-wire Serial Interface */
              #define TWI_vect_num		19
              #define TWI_vect			_VECTOR(19)
              #define SIG_2WIRE_SERIAL		_VECTOR(19)
              
              /* Store Program Memory Ready */
              #define SPM_RDY_vect_num		20
              #define SPM_RDY_vect			_VECTOR(20)
              #define SIG_SPM_READY			_VECTOR(20)
              
              #define _VECTORS_SIZE 84
              شما فقط از دیفاین هایی که آخرش نوشته vect استفاده کنید .

              مثال:
              کدی برای نوشتن روتین وقفه مربوط به سرریز تایمر/کانتر 0 :
              کد:
              ISR(TIMER0_OVF_vect)
              {
              	
              }
              اگه گفتید معادلش تو کدویژن چی بود؟
              آره آفرین . یه چی تو این مایه ها بود:
              کد:
              interrupt[TIM0_OVF] void tim0_ovf_isr()
              {
              	
              	
              	
              }
              راه اندازی ماژول nrf24l01p برای codevision (ارتباط بیسیم بین دو میکرو) : http://www.eca.ir/forum2/index.php?topic=78587.0
              کوچ کردن از کدویژن به http://www.eca.ir/forum2/index.php?topic=81025.0 : AtmelStudio
              نحوه نوشتن اصولی یک لایبرری و درایور نرم افزاری( بصورت ساده) : http://www.eca.ir/forum2/index.php?topic=81071
              http://www.eca.ir/forum2/index.php?topic=82130.0 سفارش راه انداز ماژول های مختلف توسط اعضای انجمن
              انشالله به زودی تاپیک ها به روز رسانی خواهد شد،

              دیدگاه


                پاسخ : کوچ کردن از کدویژن به AtmelStudio

                پست اول پدیت شد .
                به دوستانی که تا اینجا همراه با تاپیک بودن هم توصیه میکنم حتما پست اول را مجددا مشاهده کنند.( به نظر خودم که خیلی منسجم و خوب دراومده )

                همچنین اگر پیشنهادی در رابطه با پست اول دارید حتما اعلام کنید ، بسیار خوشحال میشم.

                با تشکر
                راه اندازی ماژول nrf24l01p برای codevision (ارتباط بیسیم بین دو میکرو) : http://www.eca.ir/forum2/index.php?topic=78587.0
                کوچ کردن از کدویژن به http://www.eca.ir/forum2/index.php?topic=81025.0 : AtmelStudio
                نحوه نوشتن اصولی یک لایبرری و درایور نرم افزاری( بصورت ساده) : http://www.eca.ir/forum2/index.php?topic=81071
                http://www.eca.ir/forum2/index.php?topic=82130.0 سفارش راه انداز ماژول های مختلف توسط اعضای انجمن
                انشالله به زودی تاپیک ها به روز رسانی خواهد شد،

                دیدگاه


                  پاسخ : کوچ کردن از کدویژن به AtmelStudio

                  نوشته اصلی توسط RubeuS
                  با توجه به درخواست جناب سعید دلشاد منور مبنی بر توضیح در رابطه با نحوه ی ارتباط با اینترفیس USART از طریق روش دریافت وقفه یک توضیحات مختصری در این رابطه میدهم:
                  قبل از اون در این پست قصد دارم به نحوه نوشتن برنامه ای که در اون از وقفه استفاده شده بپردازم.

                  البته من قبلا در پست اول در این رابطه نوشته بودم ولی به دلیل اشتباه هنگام ویرایش پست ، مطالب پاک شد:

                  قبلش توصیه میکنم برای درک مفهوم پست های زیر را بخونید:
                  http://www.eca.ir/forum2/index.php?topic=81025.msg505301#msg505301

                  http://www.eca.ir/forum2/index.php?topic=81025.msg505353#msg505353

                  خوب چون من تو این تاپیک میخوام بیشتر به نحوه ی برنامه نویسی در محیط اتمل استادیو بپردازم و با فرض اینکه شما دوستان با یه سری اصول توسط برنامه نویسی در محیط کدویژن آشنایید، خیلی مختصر توضیح میدم:
                  در اینجا ما فایل هدری به این منظور داریم که باید اینکلود شود:
                  کد:
                  #include <avr/interrupt.h>
                  این هدر توابع خوبی را برای اینکار فراهم میکنند.
                  اولین گروه برای فعال و غیر فعال کردن وقفه های سراسری است( صفر و یک کردن فلگ مربوطه ( بیت شماره 7 از رجیستر SREG ) )
                  کد:
                  sei(); 
                  
                  cli();
                  همون طور که میدونید در کدویژن برای نوشتن روتین یک وقفه از کلمه ی کلیدی interrupt استفاده میشد. ولی اینجا میتونید برای اینکار از تابع ()ISR استفاده کنید.
                  چجوری؟
                  بتون میگم ... عجله نداشته باشید

                  یادتونه تو کدویژن بعد از interrupt چی مینوشتید؟
                  اره آفرین... برای مشخص کردن نوع وقفه اسم یا آدرس مربوط به وقفه را در بین دو کروشه مشخص میکردیم.
                  برای اینکار در اینجا باید اسم یا آدرس مربوط به وقفه مورد نظر را به عنوان اولین پارامتر به تابع ISR بدید.
                  او او ... صبر کنید .. کجا؟ اینجا اسم ها یکم متفاوته!!
                  ولی نگران نباشید... برید در فایل هدر مربوط به میکروتون و اسم مربوط به وقفه ی مورد نظرتون رو بدست آورید.
                  چی؟ فایل هدر مربوط به میکروتون کجاست؟
                  خوب تو پست اول توضیح دادم تو هدر avr/io.h باید بگردید دنبالش .
                  من در اینجا هدر مربوط به میکرو مگا32 رو مثال میزنم که هدر مربوطه میشه: avr/iom32.h

                  خوب یک قسمتش به صورت کامنت گفته: Interrupt vectors
                  من دقیقا دیفاین های زیرش رو براتون میزارم:
                  کد:
                  /* Interrupt vectors */
                  
                  /* External Interrupt Request 0 */
                  #define INT0_vect_num		1
                  #define INT0_vect			_VECTOR(1)
                  #define SIG_INTERRUPT0			_VECTOR(1)
                  
                  /* External Interrupt Request 1 */
                  #define INT1_vect_num		2
                  #define INT1_vect			_VECTOR(2)
                  #define SIG_INTERRUPT1			_VECTOR(2)
                  
                  /* External Interrupt Request 2 */
                  #define INT2_vect_num		3
                  #define INT2_vect			_VECTOR(3)
                  #define SIG_INTERRUPT2			_VECTOR(3)
                  
                  /* Timer/Counter2 Compare Match */
                  #define TIMER2_COMP_vect_num	4
                  #define TIMER2_COMP_vect		_VECTOR(4)
                  #define SIG_OUTPUT_COMPARE2		_VECTOR(4)
                  
                  /* Timer/Counter2 Overflow */
                  #define TIMER2_OVF_vect_num		5
                  #define TIMER2_OVF_vect			_VECTOR(5)
                  #define SIG_OVERFLOW2			_VECTOR(5)
                  
                  /* Timer/Counter1 Capture Event */
                  #define TIMER1_CAPT_vect_num	6
                  #define TIMER1_CAPT_vect		_VECTOR(6)
                  #define SIG_INPUT_CAPTURE1		_VECTOR(6)
                  
                  /* Timer/Counter1 Compare Match A */
                  #define TIMER1_COMPA_vect_num	7
                  #define TIMER1_COMPA_vect		_VECTOR(7)
                  #define SIG_OUTPUT_COMPARE1A		_VECTOR(7)
                  
                  /* Timer/Counter1 Compare Match B */
                  #define TIMER1_COMPB_vect_num	8
                  #define TIMER1_COMPB_vect		_VECTOR(8)
                  #define SIG_OUTPUT_COMPARE1B		_VECTOR(8)
                  
                  /* Timer/Counter1 Overflow */
                  #define TIMER1_OVF_vect_num		9
                  #define TIMER1_OVF_vect			_VECTOR(9)
                  #define SIG_OVERFLOW1			_VECTOR(9)
                  
                  /* Timer/Counter0 Compare Match */
                  #define TIMER0_COMP_vect_num	10
                  #define TIMER0_COMP_vect		_VECTOR(10)
                  #define SIG_OUTPUT_COMPARE0		_VECTOR(10)
                  
                  /* Timer/Counter0 Overflow */
                  #define TIMER0_OVF_vect_num		11
                  #define TIMER0_OVF_vect			_VECTOR(11)
                  #define SIG_OVERFLOW0			_VECTOR(11)
                  
                  /* Serial Transfer Complete */
                  #define SPI_STC_vect_num		12
                  #define SPI_STC_vect			_VECTOR(12)
                  #define SIG_SPI				_VECTOR(12)
                  
                  /* USART, Rx Complete */
                  #define USART_RXC_vect_num		13
                  #define USART_RXC_vect			_VECTOR(13)
                  #define SIG_USART_RECV			_VECTOR(13)
                  #define SIG_UART_RECV			_VECTOR(13)
                  
                  /* USART Data Register Empty */
                  #define USART_UDRE_vect_num		14
                  #define USART_UDRE_vect			_VECTOR(14)
                  #define SIG_USART_DATA			_VECTOR(14)
                  #define SIG_UART_DATA			_VECTOR(14)
                  
                  /* USART, Tx Complete */
                  #define USART_TXC_vect_num		15
                  #define USART_TXC_vect			_VECTOR(15)
                  #define SIG_USART_TRANS			_VECTOR(15)
                  #define SIG_UART_TRANS			_VECTOR(15)
                  
                  /* ADC Conversion Complete */
                  #define ADC_vect_num		16
                  #define ADC_vect			_VECTOR(16)
                  #define SIG_ADC				_VECTOR(16)
                  
                  /* EEPROM Ready */
                  #define EE_RDY_vect_num		17
                  #define EE_RDY_vect			_VECTOR(17)
                  #define SIG_EEPROM_READY		_VECTOR(17)
                  
                  /* Analog Comparator */
                  #define ANA_COMP_vect_num		18
                  #define ANA_COMP_vect			_VECTOR(18)
                  #define SIG_COMPARATOR			_VECTOR(18)
                  
                  /* 2-wire Serial Interface */
                  #define TWI_vect_num		19
                  #define TWI_vect			_VECTOR(19)
                  #define SIG_2WIRE_SERIAL		_VECTOR(19)
                  
                  /* Store Program Memory Ready */
                  #define SPM_RDY_vect_num		20
                  #define SPM_RDY_vect			_VECTOR(20)
                  #define SIG_SPM_READY			_VECTOR(20)
                  
                  #define _VECTORS_SIZE 84
                  شما فقط از دیفاین هایی که آخرش نوشته vect استفاده کنید .

                  مثال:
                  کدی برای نوشتن روتین وقفه مربوط به سرریز تایمر/کانتر 0 :
                  کد:
                  ISR(TIMER0_OVF_vect)
                  {
                  	
                  }
                  اگه گفتید معادلش تو کدویژن چی بود؟
                  آره آفرین . یه چی تو این مایه ها بود:
                  کد:
                  interrupt[TIM0_OVF] void tim0_ovf_isr()
                  {
                  	
                  	
                  	
                  }
                  خیلی خیلی ممنون .
                  خب تو این isr چی اجرا میشه؟
                  فرستادن رشته؟
                  از استاد گرامی هم تقاضا میکنم کمک کنن.یه نمونه کد رو هم پیدا نکردم
                  تکاور شدن جرات افزون کند.....هراس از دل مرد بیرون کند....


                  تا تکاور به تن زخمی خود جان دارد....مرز اسلام در این ملک نگهبان دارد.........

                  دیدگاه


                    پاسخ : کوچ کردن از کدویژن به AtmelStudio

                    با سلام مجدد

                    خوب بریم سراغ یک مثال از استفاده ی وقفه در برنامه هامون(این پست ادامه ی پست شماره 142 میباشد) :

                    با احترام به نظر دوستان :
                    مثال را در رابطه با ارسال یک رشته توسط یکی از ماژول های اینترفیس سریال موجود در میکرو ( USART ) که یک ماژول i/o است ، قرار میدهم.

                    هدف:
                    هدف ارسال رشته ی "eca.ir" که یک آرایه ای از کاراکترها موجود در حافظه ی SRAM میباشد.



                    خوب قبل از همه چیز برنامه را به چند بلوک زیر تقسیم میکنیم و طرح کلی و استخون بندی برنامه را مینویسیم:


                    کد:
                    #include <avr/io.h> // MCU = Mega32
                    #define F_CPU 8000000UL 
                    #include <avr/interrupt.h>
                    
                    
                    char str[]="eca.ir";
                    
                    
                    
                    ISR(USART_TXC_vect)
                    {
                    
                    
                    		
                    }
                    
                    
                    
                    int main(void)
                    {
                      
                    	
                    	while(1);
                    }
                    خوب این یک نگاه و یک برنامه ی اصولی است.

                    قبل از ادامه ی کار سوالی ازتون دارم:

                    رشته ی "eca.ir" شامل چند بایت یا کاراکتر می باشد؟
                    .
                    .
                    .
                    او او ... نه اشتباه کردید ( البته اینو برای کسانی که اشتباه گفتند ، گفتم )

                    اره قبول دارم تو ظاهر این رشته 6 بایته ولی در باطن نه ...
                    این رشته شامل 7 بایته .
                    6بایت اول اون شامل کد اسکی کاراکترهای 'e' و 'c' و 'a' و '.' و 'i' و 'r' میباشد ولی یک بایت دیگه هم همیشه موجود دارد که نشان دهنده پایان رشته می باشد و اون چیزی نیست جز بایت 0x00 .

                    چی؟ از کجا اینرو میگم؟ سندم کو؟
                    به پست اول مراجعه کنید و در بخش دیباگینگ توضیحاتی در رابطه با پنجره های watch و memory داده شده که میتونید راحت امتحان کنید.

                    من برای ارسال دیگه اون بایت آخر یعنی بایت 0 را نمیفرستم ، ولی یک بایت اضافه میفرستم که در اصطلاح به اون preamble میگویند و برای اینکار اول بایت 0xAA فرستاده میشه و سپس رشته را پشت سر هم میفرستیم .

                    -----------------------
                    باید در اینجا ماژول سریال پیکربندی و initialization شود :
                    برای این ارسال من تنظیمات زیر را قرار میدهم:
                    سرعت = 9600bps - ارتباط 8 بیتی - بدون parity - یک stop bit - فقط ارسال - استفاده از وقفه
                    این تنظیمات باید در اول تابع main قرار داده شود، (برای اطلاع بیشتر به فیلم آموزشی معرفی شده در پست اول ( آموزش AVR ) بخش USART مراجعه شود)
                    به شکل زیر:

                    کد:
                    #include <avr/io.h> // MCU = Mega32
                    #define F_CPU 8000000UL 
                    #include <avr/interrupt.h>
                    
                    
                    char str[]="eca.ir";
                    
                    
                    
                    ISR(USART_TXC_vect)
                    {
                    	
                    	
                    	
                    }
                    
                    
                    
                    int main(void)
                    {
                    	UCSRB |= (1<<TXCIE) | (1<<TXEN) ;
                    	UCSRC |= (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) ;
                    	UBRRL = 51;
                    	sei(); 
                    	
                    	
                    	while(1);
                    }

                    خوب حالا تو main باید بایت مقدمه(preamble) را بفرستیم و دیگه بقیه رشته به روتین وقفه واگذار میشه. برای اینکار باید یک اشاره گر static داخل روتین وقفه اعلان شود و به رشته اشاره داده شود و در هر بار درصورتی که به آخر رشته نرسیدیم بایتی که این اشاره گر بهش اشاره میکنه را میفرستیم:
                    پس کل برنامه میشه به شکل زیر:
                    کد:
                    #include <avr/io.h> // MCU = Mega32
                    #define F_CPU 8000000UL 
                    #include <avr/interrupt.h>
                    
                    
                    char str[]="eca.ir";
                    
                    
                    
                    ISR(USART_TXC_vect)
                    {
                    	static char *ptr = str;
                    	if (!(*ptr)) return;
                    	UDR = *ptr;
                    	ptr++;	
                    }
                    
                    
                    
                    int main(void)
                    {
                    	UCSRB |= (1<<TXCIE) | (1<<TXEN) ;
                    	UCSRC |= (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) ;
                    	UBRRL = 51;
                    	sei(); 
                    	
                    	UDR = 0xAA; //send preamble
                    	
                    	while(1);
                    }
                    فقط باید بگم حتما در هنگام پروگرام کردن میکرو کلاک روی 8 مگاهرتز تنظیم شود.
                    البته برای ارسال با درصد خطای کمتر میتونید از کریستال خارجی دقیق مثل 11.0592 مگاهرتز استفاده کنید و مناسب با اون UBRR را تنظیم کنید.
                    راه اندازی ماژول nrf24l01p برای codevision (ارتباط بیسیم بین دو میکرو) : http://www.eca.ir/forum2/index.php?topic=78587.0
                    کوچ کردن از کدویژن به http://www.eca.ir/forum2/index.php?topic=81025.0 : AtmelStudio
                    نحوه نوشتن اصولی یک لایبرری و درایور نرم افزاری( بصورت ساده) : http://www.eca.ir/forum2/index.php?topic=81071
                    http://www.eca.ir/forum2/index.php?topic=82130.0 سفارش راه انداز ماژول های مختلف توسط اعضای انجمن
                    انشالله به زودی تاپیک ها به روز رسانی خواهد شد،

                    دیدگاه


                      پاسخ : کوچ کردن از کدویژن به AtmelStudio

                      نوشته اصلی توسط RubeuS
                      با سلام مجدد

                      خوب بریم سراغ یک مثال از استفاده ی وقفه در برنامه هامون(این پست ادامه ی پست شماره 142 میباشد) :

                      با احترام به نظر دوستان :
                      مثال را در رابطه با ارسال یک رشته توسط یکی از ماژول های اینترفیس سریال موجود در میکرو ( USART ) که یک ماژول i/o است ، قرار میدهم.

                      هدف:
                      هدف ارسال رشته ی "eca.ir" که یک آرایه ای از کاراکترها موجود در حافظه ی SRAM میباشد.



                      خوب قبل از همه چیز برنامه را به چند بلوک زیر تقسیم میکنیم و طرح کلی و استخون بندی برنامه را مینویسیم:


                      کد:
                      #include <avr/io.h> // MCU = Mega32
                      #define F_CPU 8000000UL 
                      #include <avr/interrupt.h>
                      
                      
                      char str[]="eca.ir";
                      
                      
                      
                      ISR(USART_TXC_vect)
                      {
                      
                      
                      		
                      }
                      
                      
                      
                      int main(void)
                      {
                        
                      	
                      	while(1);
                      }
                      خوب این یک نگاه و یک برنامه ی اصولی است.

                      قبل از ادامه ی کار سوالی ازتون دارم:

                      رشته ی "eca.ir" شامل چند بایت یا کاراکتر می باشد؟
                      .
                      .
                      .
                      او او ... نه اشتباه کردید ( البته اینو برای کسانی که اشتباه گفتند ، گفتم )

                      اره قبول دارم تو ظاهر این رشته 6 بایته ولی در باطن نه ...
                      این رشته شامل 7 بایته .
                      6بایت اول اون شامل کد اسکی کاراکترهای 'e' و 'c' و 'a' و '.' و 'i' و 'r' میباشد ولی یک بایت دیگه هم همیشه موجود دارد که نشان دهنده پایان رشته می باشد و اون چیزی نیست جز بایت 0x00 .

                      چی؟ از کجا اینرو میگم؟ سندم کو؟
                      به پست اول مراجعه کنید و در بخش دیباگینگ توضیحاتی در رابطه با پنجره های watch و memory داده شده که میتونید راحت امتحان کنید.

                      من برای ارسال دیگه اون بایت آخر یعنی بایت 0 را نمیفرستم ، ولی یک بایت اضافه میفرستم که در اصطلاح به اون preamble میگویند و برای اینکار اول بایت 0xAA فرستاده میشه و سپس رشته را پشت سر هم میفرستیم .

                      -----------------------
                      باید در اینجا ماژول سریال پیکربندی و initialization شود :
                      برای این ارسال من تنظیمات زیر را قرار میدهم:
                      سرعت = 9600bps - ارتباط 8 بیتی - بدون parity - یک stop bit - فقط ارسال - استفاده از وقفه
                      این تنظیمات باید در اول تابع main قرار داده شود، (برای اطلاع بیشتر به فیلم آموزشی معرفی شده در پست اول ( آموزش AVR ) بخش USART مراجعه شود)
                      به شکل زیر:

                      کد:
                      #include <avr/io.h> // MCU = Mega32
                      #define F_CPU 8000000UL 
                      #include <avr/interrupt.h>
                      #include <avr/iom32.h>
                      
                      
                      char str[]="eca.ir";
                      
                      
                      
                      ISR(USART_TXC_vect)
                      {
                      	
                      	
                      	
                      }
                      
                      
                      
                      int main(void)
                      {
                      	UCSRB |= (1<<TXCIE) | (1<<TXEN) ;
                      	UCSRC |= (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) ;
                      	UBRRL = 51;
                      	sei(); 
                      	
                      	
                      	while(1);
                      }

                      خوب حالا تو main باید بایت مقدمه(preamble) را بفرستیم و دیگه بقیه رشته به روتین وقفه واگذار میشه. برای اینکار باید یک اشاره گر static داخل روتین وقفه اعلان شود و به رشته اشاره داده شود و در هر بار درصورتی که به آخر رشته نرسیدیم بایتی که این اشاره گر بهش اشاره میکنه را میفرستیم:
                      پس کل برنامه میشه به شکل زیر:
                      کد:
                      #include <avr/io.h> // MCU = Mega32
                      #define F_CPU 8000000UL 
                      #include <avr/interrupt.h>
                      #include <avr/iom32.h>
                      
                      
                      char str[]="eca.ir";
                      
                      
                      
                      ISR(USART_TXC_vect)
                      {
                      	static char *ptr = str;
                      	if (!(*ptr)) return;
                      	UDR = *ptr;
                      	ptr++;	
                      }
                      
                      
                      
                      int main(void)
                      {
                      	UCSRB |= (1<<TXCIE) | (1<<TXEN) ;
                      	UCSRC |= (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) ;
                      	UBRRL = 51;
                      	sei(); 
                      	
                      	UDR = 0xAA; //send preamble
                      	
                      	while(1);
                      }
                      فقط باید بگم حتما در هنگام پروگرام کردن میکرو کلاک روی 8 مگاهرتز تنظیم شود.
                      البته برای ارسال با درصد خطای کمتر میتونید از کریستال خارجی دقیق مثل 11.0592 مگاهرتز استفاده کنید و مناسب با اون UBRR را تنظیم کنید.
                      قسم به جدت من شرمندت شدم سید جان :"> :"> :"> :"> :">
                      خب این برنامه رو تو عمل جواب گرفتم فقط یک رشته رو میفرسته.
                      من اگه بخوام رشته رو هی بفرسته و تو مکان مورد نظر من چطوری میشه؟
                      راستی یه سوال دیگه.کی وقفه اتفاق میفته و isr اجرا میشه؟
                      ما خودمون میتونیم زمان اتفاق افتادن وقفه رو کنترل بکنیم یا بگیم اگه فلان کار شد برو isr رو اجرا بکن؟
                      تکاور شدن جرات افزون کند.....هراس از دل مرد بیرون کند....


                      تا تکاور به تن زخمی خود جان دارد....مرز اسلام در این ملک نگهبان دارد.........

                      دیدگاه


                        پاسخ : کوچ کردن از کدویژن به AtmelStudio

                        نوشته اصلی توسط سعید دلشاد منور
                        قسم به جدت من شرمندت شدم سید جان :"> :"> :"> :"> :">
                        خب این برنامه رو تو عمل جواب گرفتم فقط یک رشته رو میفرسته.
                        من اگه بخوام رشته رو هی بفرسته و تو مکان مورد نظر من چطوری میشه؟
                        راستی یه سوال دیگه.کی وقفه اتفاق میفته و isr اجرا میشه؟
                        ما خودمون میتونیم زمان اتفاق افتادن وقفه رو کنترل بکنیم یا بگیم اگه فلان کار شد برو isr رو اجرا بکن؟
                        خیلی سوالهای خوبی پرسیده میشه. تبریک میگم

                        تا جایی که بتونم سعی میکنم نکته ای را دریغ نکنم و پاسخ کامل داده بشه:

                        من اگه بخوام رشته رو هی بفرسته و تو مکان مورد نظر من چطوری میشه؟

                        برای اینکه رشته را در مکان مورد نظرتون بفرستید ، کافیه بایت preamble را در آن مکان به رجیستر UDR بدید.
                        به عنوان مثال : برنامه ی زیر ( البته این برنامه درست کار نمیکند و یک مشکل محلک دارد که در ادامه بهش اشاره میکنم)

                        کد:
                        #include <avr/io.h> // MCU = Mega32
                        #define F_CPU 8000000UL 
                        #include <avr/interrupt.h>
                        #include <avr/iom32.h>
                        
                        
                        char str[]="eca.ir";
                        
                        
                        
                        ISR(USART_TXC_vect)
                        {
                        	static char *ptr = str;
                        	if (!(*ptr)) return;
                        	UDR = *ptr;
                        	ptr++;	
                        }
                        
                        
                        
                        int main(void)
                        {
                        	UCSRB |= (1<<TXCIE) | (1<<TXEN) ;
                        	UCSRC |= (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) ;
                        	UBRRL = 51;
                        	sei(); 
                        	
                        	while(1)
                        	{
                        		UDR = 0xAA; //send preamble	
                        	}
                        }
                        الان حس میشه که پشت سر هم رشته فرستاده میشه.
                        ولی اینطور نیست.
                        اشکال:
                        یک نکته ی بسیار مهم وجود دارد که خیلی جاها دیدم رعایت نمیشه:
                        و اون هم محافظت از مقدار دهی به رجیستر UDR توسط یک سمافور است.(سمافور بحثش در سیستم عامل وجود دارد و بسیار بحث پیچیده و بزرگی است ( دو فصل از کتاب ویلیام استالینگز به این قضیه و در کل به انحصار متقابل پرداخته شده است)(اصل کرنل سیستم عامل ها بر مبنای سمافورها بنا نهاده شده) )
                        اصلا جای ترس نیست : در میکروهای ازاین دست به دلیل عدم وجود سیستم عامل ، سمافور میتواند به یک بایت خلاصه شود.
                        پس فهمیدیم سمافور کارش حفاظت است(از اجرای یک سری دستور و عمل باهمدیگر)

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

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

                        کد زیر را پیش خودتون تحلیل کنید. (تحلیل این کد را به همه ی دوستان توصیه میکنم)

                        کد:
                        #include <avr/io.h> // MCU = Mega32
                        #define F_CPU 8000000UL 
                        #include <avr/interrupt.h>
                        #include <avr/iom32.h>
                        
                        
                        char str[]="eca.ir";
                        
                        unsigned char semaphore=1;
                        
                        ISR(USART_TXC_vect)
                        {
                        	static char *ptr = str;
                        	if (!(*ptr)) 
                        	{
                        		semaphore =1 ; // vaghti CPU be inja mirese yani reshteye morede nazar besoorat kamel ferestade shode . pas dige halle va bayad semaphore ra baz ****m 
                        		return;
                        	}		
                        	UDR = *ptr;
                        	ptr++;	
                        }
                        
                        
                        
                        int main(void)
                        {
                        	UCSRB |= (1<<TXCIE) | (1<<TXEN) ;
                        	UCSRC |= (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) ;
                        	UBRRL = 51;
                        	sei(); 
                        	
                        	while(1)
                        	{
                        		if(semaphore)
                        		{
                        			UDR = 0xAA; //send preamble
                        			semaphore=0; // inja semaphore baste mishe ... yani ta moghei ke baste bashe dige nemitavan ersal reshteye jadid shoroo kard
                        		}			
                        	}
                        }
                        خوب الان مشکلمون حل شد :wow:

                        من یه درخواستی از شما دارم:
                        یادتونه یه کد گذاشته بودید که میخواستید رشته را با یک تاخیر مشخصی بفرستید ؟ تابع delay گذاشته بودید؟
                        ازتون میخوام همین کد بالا را جوری تغییر بدید که eca.ir با تاخیر 100 میلی ثانیه پشت سر هم فرستاده شود.
                        مهم نیست که جواب درست بدید ، فقط همین که تحلیل کنید و یک جواب بدید کافیه .


                        خوب بقیه ی سوالات را انشالله تو پست های بعدی جواب میدم.( البته چون برای تحلیل کد بالا نیاز به جوابه سوال دوم دارید ، حتما قبل از جواب دادن بهش پست بعدیم را بخونید)
                        راه اندازی ماژول nrf24l01p برای codevision (ارتباط بیسیم بین دو میکرو) : http://www.eca.ir/forum2/index.php?topic=78587.0
                        کوچ کردن از کدویژن به http://www.eca.ir/forum2/index.php?topic=81025.0 : AtmelStudio
                        نحوه نوشتن اصولی یک لایبرری و درایور نرم افزاری( بصورت ساده) : http://www.eca.ir/forum2/index.php?topic=81071
                        http://www.eca.ir/forum2/index.php?topic=82130.0 سفارش راه انداز ماژول های مختلف توسط اعضای انجمن
                        انشالله به زودی تاپیک ها به روز رسانی خواهد شد،

                        دیدگاه


                          پاسخ : کوچ کردن از کدویژن به AtmelStudio

                          کی وقفه اتفاق میفته و isr اجرا میشه؟

                          وقفه زمانی اتفاق میفته که فلگ مربوط به اون که در اینجا فلگ TXC است ، یک شود .

                          خوب کی TXC یک میشه؟
                          موقعی که ارسال یک بایت توسط ماژول به اتمام برسه و شیفت رجیستر مربوطه در آن کاملا خالی بشه( بیتها کامل از میکرو خارج بشه) در این صورت فلگ یک میشه و وقفه اتفاق میفته.

                          البته بگم که بعد از خارج شدن از روتین وقفه خودبه خود و سخت افزاری فلگ مربوطه( TXC ) صفر میشه و دیگه نیاز نیست خودمون با یک دادن به اون صفرش(پاکش) کنیم.
                          راه اندازی ماژول nrf24l01p برای codevision (ارتباط بیسیم بین دو میکرو) : http://www.eca.ir/forum2/index.php?topic=78587.0
                          کوچ کردن از کدویژن به http://www.eca.ir/forum2/index.php?topic=81025.0 : AtmelStudio
                          نحوه نوشتن اصولی یک لایبرری و درایور نرم افزاری( بصورت ساده) : http://www.eca.ir/forum2/index.php?topic=81071
                          http://www.eca.ir/forum2/index.php?topic=82130.0 سفارش راه انداز ماژول های مختلف توسط اعضای انجمن
                          انشالله به زودی تاپیک ها به روز رسانی خواهد شد،

                          دیدگاه


                            پاسخ : کوچ کردن از کدویژن به AtmelStudio

                            ما خودمون میتونیم زمان اتفاق افتادن وقفه رو کنترل بکنیم یا بگیم اگه فلان کار شد برو isr رو اجرا بکن؟

                            این سوال ها واقعا جای بحث داره . ولی در اینجا .... نه بزارید بحث دربارش بشه ، حیفه.

                            ما کلا چند نوع وقفه داریم:

                            1- وقفه خارجی ( وقفه ای که دستگاه های i/o تایمر ها و هر چی خارج از پردازنده باشه میده)

                            2- وقفه نرم افزاری

                            3- وقفه داخلی( یا استثنا ( exception ) )


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

                            مورد 1 وجود دارد ...

                            مورد 2 ، اونچه تو ذهنم هست فقط با یک حالت میشه ایجادش کرد ، سوال شما هم در همین مورد است)

                            مورد 3 ، وجود ندارد. ( فقط در سیستم عامل و در صورت یک اتفاقات ناگوار این مورد پیش میاد ، مثالش میتونه page fault یا عمل تقسیم بر صفر و... باشه) ( در رابطه با مواجه شدن میکرو با عمل تقسیم بر صفر تاحالا امتحان نکردم ، میتونید امتحان کنید و خبرش را بهم بدید ، جالبه - به نظر باید ریست بشه ، نمیدونم والله)


                            خوب بریم سراغ وقفه نرم افزاری که سوال کرده بودید:
                            با اینتراپت خارجی در میکرو آشنا هستید؟ همون که اگر در یک پین خارجی تغییری صورت بگیرد ، در صورت تنظیم وقفه میده و میره تو isr وقفه.
                            اگر اون را تنظیم کنید و با مقدار دهی به پین مورد نظر از طریق رجیستر PORTX شما میتوانید یک وقفه ی شبه نرم افزاری داشته باشید.

                            در سیستم عامل این نوع وقفه بسیار بسیار مهم است و یک جور رابطه بین برنامه نویس سطح پایین(منظور کسی که خیلی نزدیک به سخت افزار برنامه نویسی میکنه --- سخت ترین نوع برنامه نویسی است) و سیستم عامل. با دستور اسمبلی INT در پردازنده های اینتل و ... که روشون سیستم عامل نصب میشه میشه این نوع وقفه را ایجاد کرد. ( کسانی که با این نوع برنامه نویسی آشنایی داشته باشند میدونند چقدر طاقت فرساست(البته الان مثلا برا ویندوز زبان #C و ... ( دات نت فریم ورک) اومده که برنامه نویس اصلا نیاز نیست اینچیزا را بدونه )


                            راه اندازی ماژول nrf24l01p برای codevision (ارتباط بیسیم بین دو میکرو) : http://www.eca.ir/forum2/index.php?topic=78587.0
                            کوچ کردن از کدویژن به http://www.eca.ir/forum2/index.php?topic=81025.0 : AtmelStudio
                            نحوه نوشتن اصولی یک لایبرری و درایور نرم افزاری( بصورت ساده) : http://www.eca.ir/forum2/index.php?topic=81071
                            http://www.eca.ir/forum2/index.php?topic=82130.0 سفارش راه انداز ماژول های مختلف توسط اعضای انجمن
                            انشالله به زودی تاپیک ها به روز رسانی خواهد شد،

                            دیدگاه


                              پاسخ : کوچ کردن از کدویژن به AtmelStudio

                              سلام سید جان اینم کد
                              کد:
                              #include <avr/io.h> // MCU = Mega32
                              #define F_CPU 8000000UL
                              #include <avr/interrupt.h>
                              #include <avr/iom32.h>
                              #include <util/delay.h>
                              
                              
                              char str[]="eca.ir";
                              unsigned char semaphore=1;
                              
                              
                              ISR(USART_TXC_vect)
                              {
                              	static char *ptr = str;
                              	if (!(*ptr)) {
                              		semaphore =1;
                              		return;
                              	}
                              	UDR = *ptr;
                              	ptr++;
                              }
                              
                              
                              
                              int main(void)
                              {
                              	UCSRB |= (1<<TXCIE) | (1<<TXEN) ;
                              	UCSRC |= (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) ;
                              	UBRRL = 51;
                              	sei();
                              	
                              	UDR = 0xAA; //send preamble
                              	
                              	while(1);
                              	{
                              		if(semaphore)
                              		{
                              			UDR = 0xAA;
                              			semaphore=0;
                              			_delay_ms(100);
                              	}
                              	}
                              }
                              سوال دارم زیاد
                              این قسمت رو زیاد توضیح بدین به خصوص قسمت if رو
                              کد:
                              while(1);
                              	{
                              		if(semaphore)
                              		{
                              			UDR = 0xAA;
                              			semaphore=0;
                              			_delay_ms(100);
                              	}
                              	}
                              یه سوال دیگه.یعنی میشه با تغییرات پین خارجی به این وقفه سر زد؟
                              تکاور شدن جرات افزون کند.....هراس از دل مرد بیرون کند....


                              تا تکاور به تن زخمی خود جان دارد....مرز اسلام در این ملک نگهبان دارد.........

                              دیدگاه


                                پاسخ : کوچ کردن از کدویژن به AtmelStudio

                                نوشته اصلی توسط سعید دلشاد منور
                                سلام سید جان اینم کد
                                کد:
                                #include <avr/io.h> // MCU = Mega32
                                #define F_CPU 8000000UL
                                #include <avr/interrupt.h>
                                #include <avr/iom32.h>
                                #include <util/delay.h>
                                
                                
                                char str[]="eca.ir";
                                unsigned char semaphore=1;
                                
                                
                                ISR(USART_TXC_vect)
                                {
                                	static char *ptr = str;
                                	if (!(*ptr)) {
                                		semaphore =1;
                                		return;
                                	}
                                	UDR = *ptr;
                                	ptr++;
                                }
                                
                                
                                
                                int main(void)
                                {
                                	UCSRB |= (1<<TXCIE) | (1<<TXEN) ;
                                	UCSRC |= (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) ;
                                	UBRRL = 51;
                                	sei();
                                	
                                	UDR = 0xAA; //send preamble
                                	
                                	while(1);
                                	{
                                		if(semaphore)
                                		{
                                			UDR = 0xAA;
                                			semaphore=0;
                                			_delay_ms(100);
                                	}
                                	}
                                }
                                سوال دارم زیاد
                                این قسمت رو زیاد توضیح بدین به خصوص قسمت if رو
                                کد:
                                while(1);
                                	{
                                		if(semaphore)
                                		{
                                			UDR = 0xAA;
                                			semaphore=0;
                                			_delay_ms(100);
                                	}
                                	}
                                یه سوال دیگه.یعنی میشه با تغییرات پین خارجی به این وقفه سر زد؟
                                سلام

                                در رابطه با کد اصلا توقعی در رابطه با درست بودن نبوده چون این مبحث یکم پیچیده است و نیاز به کارکردن و تمرین داره. ولی برا دفعه اول خیلی خوبه :applause:

                                ولی یه جا سهوا اشتباه شده:
                                تو تابع main قبل از حلقه بینهایت ، برای چی preamble فرستادید؟

                                بزارید تحلیلش کنیم ، پردازنده شروع به اجرا از تابع میکنه ،
                                1- رجیسترها را مقداردهی میکنه.

                                2- حالا هنوز وارد حلقه نشده دستور فرستادن 0xAA را میده. ( فقط دستور به کارگره میده ، نیاز نیست خودش بره نظارت کنه ) خودش میره برای اجرای ادامه کد.

                                3- میره تو حلقه بینهایت و چون از اول سمافور 1 بوده وارد if میشه و دوباره دستور ارسال 0xAA را میده . ولی کارگر بدبخت که هنوز داره کار میکنه و کارش تموم نشده . وای وای وای وای قاتی پاتی شد.

                                .............. خوب من اون فرستادن 0xAA که قبل از حلقه بینهایته رو حذفش میکنم و دوباره تحلیلش میکنم.

                                پس شد:
                                مهم: بنده در کدهایی که در پست مربوطه دادم iom32.h را اینکلود کرده بودم که نباید اینکار صورت میگرفت. همون اینکلود کردن io.h کافی است.
                                کد:
                                #include <avr/io.h> // MCU = Mega32
                                #define F_CPU 8000000UL
                                #include <avr/interrupt.h>
                                #include <util/delay.h>
                                
                                
                                char str[]="eca.ir";
                                unsigned char semaphore=1;
                                
                                
                                ISR(USART_TXC_vect)
                                {
                                	static char *ptr = str;
                                	if (!(*ptr)) {
                                		semaphore =1;
                                		return;
                                	}
                                	UDR = *ptr;
                                	ptr++;
                                }
                                
                                
                                
                                int main(void)
                                {
                                	UCSRB |= (1<<TXCIE) | (1<<TXEN) ;
                                	UCSRC |= (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) ;
                                	UBRRL = 51;
                                	sei();
                                	
                                	
                                	while(1);
                                	{
                                		if(semaphore)
                                		{
                                			UDR = 0xAA;
                                			semaphore=0;
                                			_delay_ms(100);
                                	}
                                	}
                                }
                                خوب بریم از اول تحلیلش کنیم:

                                1- رجیسترها را مقداردهی میکنه.

                                2- میره تو حلقه بینهایت و چون از اول سمافور 1 بوده وارد if میشه و دستور ارسال 0xAA را میده . کارگر میره رد کارش و پردازنده ادامه میده.

                                3- هنوز تو شرط if هستیم: سمافور را میبنده ( صفر میکنه)

                                4-هنوز تو شرط if هستیم: تابع delay اجرا میشه . این تابع 100 میلی ثانیه پردازنده را الاف میکنه ( دور خودش میچرخونه - دیدی میری یک اداره میگه برو این اتاق بعد میگه برو اون اتاق و... ؟ همون جوریه)

                                صد میلی ثانیه تو دیجیتال زمان خیلی زیادیه و در این زمان مطمئنا کارگره کار خودش را انجام میده.
                                یعنی چی؟
                                یعنی در حین این که پردازنده داره دور خودش میچرخه و الافه کارگره(اینترفیس سریال) میاد میگه من کارم تموم شده . همین که اینو میگه پردازنده میره تو روتین وقفه خیلی سریع روتین وقفه انجام میشه و برمیگرده به تابع delay . راستی تو اون فرصت که میره تو روتین وقفه به کارگر دستور ارسال بایت بعدی را میده. همینجوری تا آخر .
                                اگه از رشته چیزی باقی نموند ، پردازنده وقتی میره تو روتین فقط سمافور را باز میکنه ( 1 میکنه ) و میاد بیرون.

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

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

                                حالا یک کد میزارم برو تحلیلش کن:

                                کد:
                                #include <avr/io.h> // MCU = Mega32
                                #define F_CPU 8000000UL
                                #include <avr/interrupt.h>
                                #include <util/delay.h>
                                
                                
                                char str[]="eca.ir";
                                unsigned char semaphore=1;
                                
                                
                                ISR(USART_TXC_vect)
                                {
                                	static char *ptr = str;
                                	if (!(*ptr)) {
                                		semaphore =1;
                                		return;
                                	}
                                	UDR = *ptr;
                                	ptr++;
                                }
                                
                                
                                
                                int main(void)
                                {
                                	UCSRB |= (1<<TXCIE) | (1<<TXEN) ;
                                	UCSRC |= (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) ;
                                	UBRRL = 51;
                                	sei();
                                	
                                	
                                	while(1);
                                	{
                                		if(semaphore)
                                		{
                                			_delay_ms(100);
                                			UDR = 0xAA;
                                			semaphore=0;
                                		}
                                	}
                                }
                                ا فقط جای تابع delay عوض شد .
                                بله همین تغییر کل کار را درست میکنه . تحلیل کنی میفهمی. ( گفتم یه مقدار قلق داره ، چندتا کد تحلیل کنی ، چشمت که به کد بیفته میفهمی چه اتفاق هایی قراره بیفته ... فقط تو تحلیل باید حواست باشه که پردازنده الان کجای کد هست ) ( باید تو ذهنت برنامه را اجرا کنی.)

                                --------------------------------------------------------------------
                                ادامه دارد...

                                راه اندازی ماژول nrf24l01p برای codevision (ارتباط بیسیم بین دو میکرو) : http://www.eca.ir/forum2/index.php?topic=78587.0
                                کوچ کردن از کدویژن به http://www.eca.ir/forum2/index.php?topic=81025.0 : AtmelStudio
                                نحوه نوشتن اصولی یک لایبرری و درایور نرم افزاری( بصورت ساده) : http://www.eca.ir/forum2/index.php?topic=81071
                                http://www.eca.ir/forum2/index.php?topic=82130.0 سفارش راه انداز ماژول های مختلف توسط اعضای انجمن
                                انشالله به زودی تاپیک ها به روز رسانی خواهد شد،

                                دیدگاه

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