اطلاعیه

Collapse
No announcement yet.

آموزش AVR-GCC

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

    #46
    پاسخ : آموزش AVR-GCC

    16. کار با WinAVR

    خوب اول اگه نرم افزار رو ندارید از آدرس زیر ، نرم افزار رو دانلود کنید :

    http://sourceforge.net/projects/winavr/files/


    خوب وارد بحث های فلسفی نمیشم مستقیم بریم سر اصل مطلب ، بعد از نصب، PN رو از مسیر زیر اجرا کنید :


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



    بعد روی گروه پروژه کلیک راست کلیک کنید و گزینه اول رو به صورت زیر انتخاب کنید :


    بعد از کلیک بروی گزینه فوق پنجره NEW PROJECT باز میشه ، به صورت زیر اسم پروژتون رو وارد کنید و مسیری رو به اون بدید و حتما یادتون باشه که یه فولدر جدید بهش اختصاص بدید اگه فولدر از قبل ساخته شده ندارید ، آدرس رو بنویسید و در انتها بک اسلش و اسم فولدری که میخواهید فایل های پروژتون در اون قرار بگیره رو وارد کنید بعد بروی OK کلیک کنید ، چون همچین فولدری از قبل وجود نداره از شما میپرسه که آیا فولدر جدید رو ایجاد کنه یا خیر ، به این درخواست هم پاسخ مثبت بدید ، به صورت زیر :





    حالا روی پروژه جدید کلیک راست کنید و گزینه دوم رو به صورت زیر انتخاب کنید و سه تا پوشه بسازید برای قرار دادن فایل هاس سورس ، هدر و بقیه فایل هایی که داریم، به صورت زیر :




    حالا باید فایل های پروژمون رو درست کنیم ، تو هر پروژه ای ما یه فایل سورس اصلی داریم که روال اصلی برنامه تو اون قرار نوشته میشه ، پس اول یه فایل با اسم main و پسوند c میسازیم ، برای این کار از منوی فایل نیو فولدر رو انتخاب کنید و بعد به صورت زیر در مسیر پوشه پروژه اون رو سیو کنید :




    حالا فرض کنید که ما یه فایل هدر هم داریم برای نوشتن یکسری ماکرو که بعدا میخواییم تو برنامه از اون ها استفاده کنیم ، دوباره از مسیر قبل یه فایل ایجاد میکنید ولی این بار با پسوند h ذخیره میکنید ، به این ترتیب :


    خوب ما برای کامپایل هر پروژه نیاز به یه میک فایل نیاز داریم ، این فایل رو خودمون میتونیم بنویسیم اما چون ریزه کاریهاش زیاده فعلا از template موجود استفاده میکنیم و بعد تغییرات مورد نیاز رو در اون اعمال میکنیم برای این منظور از با استفاده از گزینه open در منوی فایل از مسیر اصلی نرم افزار به صورت زیر makefile_template رو باز میکنیم و بعد اون رو با نام makefile در مسیر اصلی پروژمون سیو میکنیم ، به صورت زیر :








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






    خوب حالا یکم در مورد خود محیط PN ،تو قسمت سمت چپ میتونید با انتخاب برگه های مختلف از امکاناتی که برای کاربر فراهم شده استفاده کنید به ترتیب زیر :



    pic22



    تو محیط pn شما هر برنامه ای رو به هر زبونی که باشه میتونید بنویسید چون برای هر زبانی یه syntax highlighter در نظر گرفته شده و میشه با انتخاب به دلخواه اون برنامه نویسی رو راحت تر کرد ، اما اون سه تایی که بیشتر تو کار ما استفاده میشن به ترتیب زیر هستند :


    برای کامپایل کردن و پروگرام کردن میکرو از منوی tools سه تا گزینه معمولا تو .رژن جدید در نظر گرفته شده ، تو ورژن های قبلی این ها به صورت پیشفرض وجود نداشت و باید ایجاد میشدند .


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

    موقع کامپایل ، نتیجه عمل کامپایل و در قسمت پایین pn تو برگه output به نمایش درمیاد ، به صورت زیر :


    پایان قسمت شانزدهم

    دیدگاه


      #47
      پاسخ : آموزش AVR-GCC

      17. نحوه کار با ( MFILE( generator

      خوب همونطور که تو پست قبل اشاره شد برای کامپایل کردن برنامه نیاز به میک فایل داریم ، حالا اگه با نحوه نوشتن میک فایل آشنا باشیم میتونیم خودمون اون رو به دلخواه بنویسیم اما در غیر اینصورت میتونیم از نمونه ای توسط Eric B. Weddington, Jörg Wunsch, et al. نوشته شده استفاده کنیم و با استفاده از برنامه mfile اون رو ادیت کنیم و یا اون رو تو محیط pn باز کنیم و تغییرات رو اعمال کنیم ، خوب تغییرات دستی که مشخصه چط.ر انجام میشه اما قبل از اون باید با محتویات میک فایل آشنا باشید ، با صحبتی که با یکی از اساتید داشتم قرار بر این شد که ایشون این موارد و نحوه نوشتن میک فایل رو برای ما توضیح بدن و خودم هم نحوه کار با mfile رو تو این پست بگم.

      در ابتدا به صورت زیر برنامه mfile رو با کنید :
      pic1

      بعد به طریق زیر میک فایل نمونه رو باز کنید :
      pic2

      حالا میریم سر اصل مطلب ،
      بر روی منوی Make file کلیک کنید
      اینجا سه تا بخش داریم ، بخش اول مربوط به تنظیمات کد تولیدی هست ، به ترتیب :
      pic3

      1. فیلد اول برای وارد کردن اسم فایل سورس اصلی هست که روال اصلی برنامه تو اون نوشته شده ، روی اون کلیک کنید ، توی پنجره ای که باز میشه اسم فایل سورستون رو وارد کنید (معمولا اسم فایل سورس main انتخاب میشه اما میتونه به دلخواه به هر اسمی ذخیره شده باشه پس اینجا هم باید به همون اسم نوشته بشه)
      2. توفیلد دوم میکرو یی که برنامه برای اون نوشته شده انتخاب میشه ،روی اون کلیک کنید و از مسیر درست میکرو مورد نظرتون رو انتخاب کنید .
      3. تو فیلد سوم فرمت فایل خروجی بعد از عمل کامپایل تعیین میشه ، چون ما برای پروگرام کردن میکرو به فایل هگز نیاز داریم گزینه ihex رو انتخاب میکنیم ، روی فیلد کلیک کنید و فرمت مورد نظرتون رو انتخاب کنید .
      4. تو فیلد چهارم سطح اوپتیمایزیشن تعیین میشه که در موردش تو پست شماره فکر میکنم 4 توضیح دادم برای توضیحات بیشتر به اونجا رجوع کنید ، روی فیلد چهارم کلیک کنید و سطح اوپتیمایز مورد نظرتون رو انتخاب کنید.
      5. تو فیلد پنجم فرمت فایلی که برای دیباگ کردن برنامه تولید میشه ، تعیین میشه این گزینه رو با توجه به نرم افزاری که در دسترستون برای اینکار هست انتخاب کنید ، البته تولید این فایل مستلزم اینه که دستور ساختش صادر بشه ، یعنی کامند مورد نظر برای تولید این فایل توی میک فایل در نظر گرفته شده اما برای اجراش نیاز به یک محرک داره مثل گزینه ای که در منوی تولز برای اجرای دستور make allدر میک فایل برای تولید فایل هگز در نظر گرفته شده ، خوب برای این منظور برید به محیط pn، بعد وارد منوی tools و بعد گزینه option رو انتخاب کنید پنجره زیر باز میشه :
      pic4

      بعد از کلیک بر روی add پنجره زیر باز میشه و به ترتیب تنظیمات زیر رو در برگه های اون انجام بدید .
      pic5

      pic6

      حالا بر روی ok کلیک کنید .
      دوباره بر روی add کلیک کنید و این بار تنظیمات رو به صورت زیر اعمال کنید :
      برگه اول رو به طریق زیر تنظیم کنید و برگه دوم رو هم مثل حالت قبل .
      pic7

      بعد روی OK کلیک کنید .
      حالا برید به منوی TOOLS الان دو تا گزینه برای ایجاد فایل های مورد نیاز برای دیباگ کردن برنامه تو نرم افزارهای سیمولاتور اضافه شده به صورت زیر :
      PIC8

      6. تو فیلد ششم استاندار زبان برنامه نویسی انتخاب میشه چهار نوع استاندارد قابل انتخاب هستند که ما با همون استاندارد GNU 99 کار میکنیم.
      7. تو فیلد هفتم ،روی فیلد کلیک کنید ، اگر تو پروژتون از کتابخونه هایی استفاده میکنید که سورسشون تو دایرکتوری جاری پروژه هست باید اسم اون ها رو با پسوند c.بنویسید و بین اون ها یه اسپیس فاصله بزارید ، اگه فایلهای سورس کتابخونه هاتون داخل یه فولدر دیگه که اون فولدر در دایرکتوری جاری پروژتون هست باید اول اسم فولدر بعد فوروارد اسلش و بعد اسم فایل رو با پسوند c. وارد کنید، به عنوان مثال :
      pic9

      pic10

      8.تو فیلد هشتم هم اگه تو برنامه فایل اسمبلی استفاده کردید اسم اون رو همراه با پسوند S. وارد کنید توجه کنید که S باید به همین صورت، یعنی با حروف بزرگ نوشته بشه .

      11. تو فیلد یازدهم سه حالت برای استفاده از PRINTF در نظر گرفته شده که حالت اول که معادل کمترین کد هست برای زمانی هست که اصلا از این تابع استفاده نمیکنیم و یا اگه استفاده میکنیم برای نمایش مقادیر صحیح یا رشته های کارکتری استفاده میکنیم .
      گزینه دوم هم دقیقا نفهمیدم .
      گزینه سوم برای زمانی هست که میخواییم اعداد اعشاری رو با printf نمایش بدیم.

      12.تو فیلد دوازدهم هم مثل فیلد قبل هست این بار تنظیمات مربوط به دریافت هست که چه داده هایی قراره دریافت بشه.

      13.فیلد سیزدهم هم برای میکروهایی هست که دارای external ram هستند(مثل مگا 128) میشه و از طریق گزینه های این فیلد تنظیمات مربوطه انجام میشه.

      بخش دوم مربوط به تنظیمات پروگرامر هست :
      1. فیلد اول ، تو این فیلد نوع پروگرامری که استفاده میکنید رو باید انتخاب کنید مثلا من از avr910 استفاده میکنم پس باید گزینه avr910 رو انتخاب کنم.
      2. فیلد دوم، تو این فیلد پورتی که پروگرامرتون به اون متصل هست باد انتخاب کنید کثلا تو تنظیمات ویندوز من پروگرامرم رو روی پورت کام 2 تنظیم کردم پس باید اینجا com2 رو انتخاب کنم.
      حالا با انجام این تنظیمات میتونید با استفاده از گزینه program از منوی toolsتو محیط pn میکروتون رو از طریق رابط گرافیکی (GUI)AVRdude پروگرام کنید .
      بخش اخر هم که فقط یه فیلد داره که با کلیک بر روی اون تیک کنارش فعال میشه و با اینکار برنامه به شما این اجازه رو میده که تنظیمات دلخواه دیگتونرو همونجا به صورت دستی وارد کنید ، روش کلیک کنید تا تیکش فعال بشه .

      خوب همونطور که میدونید برخی از توابع برای عملکرد صحیحشون نیاز به مقدار صحیح فرکانس اوسیلاتور میکرو دارند یکی از این توابع delay هست ، برای این منظور بعد از فعال کردن تیک فیلد آخر برگردید به محیط mfile
      و بگریدید دنبال F_CPU ، پیداش که کردید میتونید فرکانس کاری میکروتون رو جلوش بنویسید ، مثلا فرکانس اوسیلاتور میکروی من 8 مگ هست به این ترتیب مقدار 8 مگ رو جلوی F_CPU وارد میکنم :
      pic11


      خوب حالا از طریق منوی file وگزینه save as میک فایلتون رو تو پوشه جاری برنامه تون با نام makefile سیو کنید.

      پایان قسمت هفدهم

      دیدگاه


        #48
        پاسخ : آموزش AVR-GCC

        با سلام به همه دوستان :bye
        می خاستم از آقای mojtaba_led و تمام دوستانی که برای این تاپیک مطلب تهیه کردن تشکر کنم واقعا تاپیک خوب و پر باریه . باز هم خسته نباشین
        من هم برای دوستانی که بعدا می خان توی مطالب تغییری ایجاد کنن و امکان داره که عکسهای این تاپیک بعد از مدتی حذف بشن ( مثل تاپیک USB_OBDEV و ...)
        برای همین تمام عکسها ومطالب تایک رو اینجا پلود می کنم
        http://uplod.ir/jwrixvberksk/AVR_Studio-AVR_GCC.rar.htm

        دیدگاه


          #49
          پاسخ : آموزش AVR-GCC

          نوشته اصلی توسط shinobi_63
          با سلام به همه دوستان :bye
          می خاستم از آقای mojtaba_led و تمام دوستانی که برای این تاپیک مطلب تهیه کردن تشکر کنم واقعا تاپیک خوب و پر باریه . باز هم خسته نباشین
          من هم برای دوستانی که بعدا می خان توی مطالب تغییری ایجاد کنن و امکان داره که عکسهای این تاپیک بعد از مدتی حذف بشن ( مثل تاپیک USB_OBDEV و ...)
          برای همین تمام عکسها ومطالب تایک رو اینجا پلود می کنم
          http://uplod.ir/jwrixvberksk/AVR_Studio-AVR_GCC.rar.htm
          سلام ،
          خیلی ممنون بابت کار قشنگتون ، خیلی عالی و با سلیقه .

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

          بخش اول : بررسی syntax برنامه نویسی در کامپایلر AVR-GCC

          بخش دوم : آموزش کار با AVRStudio5

          بخش سوم : آموزش کار با WinAVR

          و البته آدم همچین فایلی رو که بی اسم و نشونی تو نت پلود نمیکنه ، شاید یکی سوالی براش پیش امد یا خواست یه بد و بیرایی بگه ! خدا رو چه دیدی شاید خواست یه تشکری هم بکنه :mrgreen:
          و حتما منابعی رو که تو پست اول گفتم انتهای فایل ذکر کنید .

          بازم ممنون.

          دیدگاه


            #50
            پاسخ : آموزش AVR-GCC

            سلام دوستان
            یه سوال داشتم چطور میشه دست رسی بیتی به پورت هارو داشت؟
            تو code vision میشد با PORTA.0 مثلا
            من یه هدر lcd نوشتم موقع latch اصلا اذیتی میکنه :angry:
            البته قبلا برای arm نوشتم اما اون CLR و SET جدا داشت !!! این همه با همه رفته تو هم اصلا افتضاح شده :sad: :sad:
            اگه کسی قبلا نوشته ممنون میشم راهنمایی کنید
            اشکهایی که پس از هر شکست میریزیم همان عرقیست که برای پیروزی نریخته ایم.
            هیتلر

            دیدگاه


              #51
              پاسخ : آموزش AVR-GCC

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

              دیدگاه


                #52
                پاسخ : آموزش AVR-GCC

                18. نوشتن برنامه ترکیبی از c و اسمبلی(در WINAVR) :

                تو این حالت ما یه فایل داریم با پسوند c. که میشه همون فایل اصلی برناممون یعنی main.c که کد c مون رو توش مینویسیم و یه فایل دیگه داریم با پسوند S. (اسش کپیتال باید باشه) و کد اسمبلیمون رو توش مینویسیم .

                به عنوان مثال فرض کنیم این فایل C مون هست با اسم mainC.c :

                کد:
                #include <avr/io.h>
                
                volatile uint8_t pinbits; //define poer pins
                
                extern void InitPort(void);//init port for output
                
                extern void sendpinbits(void);//send to port
                
                int main()
                
                {
                
                	pinbits=1;//set pin 1 as output
                
                	InitPort();//call subroutine from assembler file
                
                	while(1)//repeat for ever
                
                	{
                
                	pinbits=1;//Pin High
                
                	sendpinbits();//call subroutine from assembler file
                
                	pinbits=0;//Pin Low
                
                	sendpinbits();//call subroutine from assembler file
                
                	}
                
                }


                و همینطور این هم فایل اسمبلی مون هست ، با اسم extasm.S :

                کد:
                #include <avr/io.h>				;required for register definitions
                
                .extern pinbits					;external variable
                
                .global InitPort				;make accesible globally
                
                InitPort:					;function name 
                
                	push r18				;save register value
                
                	lds r18, pinbits			;load variable to r18
                
                	out _SFR_IO_ADDR(DDRD), r18	;set pins as output
                
                	pop r18				;restore register
                
                	ret					;return from subroutine
                
                .global sendpinbits				;make global
                
                sendpinbits:					;function name
                
                	push r18				;save register value
                
                	lds r18, pinbits			;load variable to r18
                
                	out _SFR_IO_ADDR(PORTD), r18	;pins to High
                
                	pop r18				;restore register
                
                	ret					;return from subroutine


                خوب حالا نوبت اعمال تنظیمات لازمه توی Makefile هست ، به این ترتیب :


                کد:
                # Target file name (without extension).
                
                TARGET = mainC
                
                # List Assembler source files here.
                
                ASRC = extasm.S


                خوب حالا همه چی آماده است و کافیه که فقط Make All کنیم .

                چند تا نکته :

                1. توابع ای که تو فایل c نوشتیم باید توی فایل اسمبلی مون به صورت یه تابع external با استفاده از رهنمود extern. معرفی بشن ، مثلا :

                کد:
                .extern my_C_function


                2. توابعی که تو فایل اسمبلی مون نوشتیم باید به صورت global تعریف بشن با استفاده از رهنمود .global ، مثلا :

                کد:
                .global my_assembly_fct


                3. تو فایل c مون باید پروتوتایپ توابعی که تو فایل اسمبلی مون نوشتیم به فرم زیر در ابتدای برنامه بنویسیم :


                کد:
                extern unsigned char my_assembly_fct (unsigned char, unsigned int);


                4. برای دسترسی به یک متغیر سراسری به طور مشترک در فایل c و اسمبلی باید تو فایل اسمبلی مون اون متغیر رو با کلمه کلیدی .extern معرفی کنیم ، برای مثال :

                کد:
                In the C code :
                unsigned char my_value;
                
                In the assembly it would be coded:
                .extern my_value


                پیشنهاد میکنم ، برای اطلاعات بیشتر به AVR32027 مراجعه کنید.

                پایان قسمت هجدهم

                دیدگاه


                  #53
                  پاسخ : آموزش AVR-GCC

                  19.نوشتن کتابخانه

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

                  خوب کتابخونه ها به دو صورت هستند ، سورس باز و بسته ، سورس باز مثله چیزی که مورد بحث ماست و سورس بسته مثل کتابخونه هایی که مثلا همراه کدویژن ارائه میشن ، مثل کتابخونه LCD کاراکتری و گرافیکی ، SPI , MMC ,... این کتابخونه ها فقط قابل استفاده تو کامپایلر خودشون هستن چون فایل سورسشون در دسترس نیست و برای استفاده از اون ها هم باید در ابتدای برنامه فایل هدرشون به برنامه با دستور INCLUDE الصاق بشه .

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

                  خوب حالا چیزی که تو فایل سورس نوشته میشه ، تو فایل سورس تمام توابعی و ماکرو ها که میخاهیم به صورت یه کتابخونه جمع آوری کنیم نوشته میشن .

                  فایل هدر ، تو این فایل پروتوتایپ تمام توابعی که تو فایل سورس نوشته شدن رو مینویسیم . بعلاوه یکسری دیفاین هایی که احتمالا تو فایل سورس به صورت ماکرو استفاده شدند و باید متناسب با نوع کار و یا مقصد و یا میکرویی که باهاش کار میکنیم تعریف بشن .


                  پس باید دو تا فایل ایجاد کنیم و با یک اسم و با دو پسوند یکی c. و اون یکی رو با پسوند h. ذخیره کنیم .

                  به عنوان مثال modbus.c , modbus.h .

                  خوب اول باید توابع و ماکرو ها مون رو تو فایل سورس بنویسیم و البته در ابتدای اون باید فایل هدر رو هم اینکلود کنیم ، به عنوان مثال این فایل سورس کتابخانه modbus هست که جناب رستمی نوشتند :

                  کد:
                  //*****************************************************************************
                  //
                  // File Name	: 'modbus.c'
                  // Title		: modbus over serial line
                  // Author		: Hamid Rostami
                  //
                  // This code is distributed under the GNU Public License
                  //		which can be found at http://www.gnu.org/licenses/gpl.txt
                  
                  #include "modbus.h"
                  
                  const unsigned int POLYNUMERIC = 0xA001;
                  
                  void modbusInit(unsigned int baudrate){
                  	uartInit();
                  	uartSetBaudRate(baudrate);
                  
                  	MODBUS_DIRECTION_DDR |= 1 << MODBUS_DIRECTION_BIT;
                  }
                  
                  
                  int modbus_WriteSingleRegister(unsigned int slaveAddr, unsigned int registerAddr, unsigned int value){
                  	unsigned char PDU[7];
                  	unsigned int CRC = 0xFFFF;
                  	int i, j;
                  	
                  	PDU[0] = slaveAddr;							// Slave Address
                  	PDU[1] = 0x06;								// Function Code
                  	
                  	PDU[2] = (registerAddr & 0xFF00) >> 8;		// Register Address High Byte
                  	PDU[3] = registerAddr & 0x00FF;				// Register Address Low Byte
                  	
                  	PDU[4] = (value & 0xFF00) >> 8;				// Value High Byte
                  	PDU[5] = value & 0x00FF;					// Value Low Byte
                  	
                  	// Generate CRC16
                  	for(i=0; i<=5; i++){
                  		CRC ^= PDU[i];
                  		for( j=0; j<=7; j++){
                  			if( CRC & 1 ){
                  				CRC >>= 1;
                  				CRC ^= POLYNUMERIC;
                  			}else{
                  				CRC >>= 1;
                  			}
                  		}
                  	}
                  	
                  	PDU[6] = CRC & 0x00FF;						// CRC Low Byte
                  	PDU[7] = (CRC & 0xFF00) >> 8;				// CRC High Byte
                  	
                  	// Send PDU
                  	MODBUS_SEND_ENABLE;
                  	
                  	
                  	
                  	for(i=0; i<=7; i++){
                  		uartSendByte(PDU[i]);
                  	}
                  	return 0;
                  	
                  	/*
                  	// Recieve PDU
                  	PDU[0] = uartGetByte();
                  	
                  	if( PDU[0] != 
                  	for(i=0; i<=7; i++){
                  	
                  	}
                  	*/
                  	return 0;
                  }
                  
                  int modbus_ReadSingleRegister(unsigned int slaveAddr, unsigned int registerAddr, unsigned int *buff, unsigned int count){
                  	unsigned int PDU[7];
                  	unsigned int CRC=0xFFFF;
                  	int i, j;
                  	
                  	PDU[0] = slaveAddr;							// Slave Address
                  	PDU[1] = 0x04;								// Function Code
                  	PDU[2] = registerAddr & 0x00FF;				// Register Address High Byte
                  	PDU[3] = (registerAddr & 0xFF00) >> 8;		// Register Address Low Byte
                  	PDU[4] = count & 0x00FF;					// Value High Byte
                  	PDU[5] = count & 0x00FF;					// Value Low Byte
                  	
                  	// Generate CRC16
                  	for(i=0; i<=5; i++){
                  		CRC ^= PDU[i];
                  		for( j=0; j<=7; j++){
                  			if( CRC & 1 ){
                  				CRC >>= 1;
                  				CRC ^= POLYNUMERIC;
                  			}else{
                  				CRC >>= 1;
                  			}
                  		}
                  	}
                  	
                  	//CRC16 = crc16(PDU, 6);
                  	PDU[6] = CRC & 0x00FF;					// CRC High Byte
                  	PDU[7] = CRC & 0x00FF;					// CRC Low Byte
                  	
                  	// Send PDU
                  	MODBUS_SEND_ENABLE;
                  	for(i=0; i<=7; i++){
                  		uartSendByte(PDU[i]);
                  	}
                  	
                  	return TRUE;
                  }


                  حالا باید فایل هدر رو تکمیل کنید ، خوب از اونجا که امکان داره یه فایل هدر تو چند تا فایل سورس اینکلود بشه و چون کامپایلر موقع کامپایل میاد تمام سورس ها رو کامپایل میکنه ؛

                  نقل قول از استاد کی نژاد :
                  با توجه به امکان چند بار include شدن یک فایل header، از طریق نوشتن ifndef# در ابتدای فایل، در پروسه کامپایل و لینک فقط یکبار این فایل در مجموعه کدها لحاظ می شود. عبارتی هم که تعریف آن مورد بررسی قرار می گیرد می تواند هر اسم دلخواه را داشته باشد که در نامگذاری های فایل های کامپایلر، از نام های خاصی استفاده می شود که برای کامپایلر شناخته شده و دارای معنای مشخص هستند و این اسامی در بسیاری مواقع مطابق تعاریف کامپایلر بین __ __ قرار داده می شوند.
                  اما اگر خود شما قصد ساخت یک کتابخانه را دارید می توانید از نام مورد نظر خود (که بهتر است با حروف بزرگ و هم نام با فایل header باشد) استفاده کنید. مثلا:

                  کد:
                  #ifndef MY_HEADER_H
                  #define MY_HEADER_H
                  
                  //header 
                  
                  #endif


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

                  اتمام نقل قول .

                  پس به عنوان مثال میاییم در ابتدای فایل هدر کتابخونه modbus این مورد رو لحاظ و بعد از اون احتمالا اگه برای اینکه سورمون بتونه کامپایل بشه نیاز به کتابخونه های دیگه داشته باشه میاییم هدر اون ها رو در ابتدای برنامه اینکلود میکنیم و بعد دیفاین ها و بعد هم پروتوتایپ ها رو مینویسیم به این شکل :


                  کد:
                  ///*****************************************************************************
                  //
                  // File Name	: 'modbus.h'
                  // Title		: modbus over serial line
                  // Author		: Hamid Rostami
                  //
                  // This code is distributed under the GNU Public License
                  //		which can be found at http://www.gnu.org/licenses/gpl.txt
                  
                  #ifndef MODBUS
                  #define MODBUS
                  
                  #include "uart.h"
                  #include <avr/io.h>
                  
                  // Not used yet ----------------------------
                  #define MODBUS_DIRECTION_PORT		 	PORTA
                  #define MODBUS_DIRECTION_DDR 			DDRA
                  #define MODBUS_DIRECTION_BIT 			3
                  
                  #define MODBUS_SEND_ENABLE 				MODBUS_DIRECTION_PORT |= 1<<MODBUS_DIRECTION_BIT
                  #define MODBUS_RECIEVE_ENABLE 			MODBUS_DIRECTION_PORT &= ~(1<<MODBUS_DIRECTION_BIT)
                  // -----------------------------------------
                  
                  // Initial modbus
                  void modbusInit(unsigned int baudrate);
                  
                  // Write single register
                  int modbus_WriteSingleRegister(unsigned int slaveAddr, unsigned int registerAddr, unsigned int value);
                  
                  // Read single Register (not work yet !)
                  int modbus_ReadSingleRegister(unsigned int slaveAddr, unsigned int registerAddr, unsigned int *buff, unsigned int count);
                  
                  
                  #endif







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

                  حالا باید توی makefile اسم فایل سورس کتابخانه رو به صورت زیر وارد کنیم :


                  کد:
                  # List C source files here. (C dependencies are automatically generated.)
                  SRC = $(TARGET).c 
                  SRC += modbus.c


                  و بعد باید فایل هدر این کتابخونه رو در ابتدای فایل سورس اصلی پروژه اینکلود کنیم به این شکل :


                  کد:
                  #include "modbus.h"


                  البته چون خود کتابخونه modbus نیاز به یه کتابخونه دیگه یعنی کتابخونه uart ، هنوز نمیشه از این کتابخونه استفاده کرد و باید فایل های سورس و هدر مربوط به کتابخونه uart هم به پروژه اضافه و اینکلود بشن و همینطور تنظیمات لازمه اون مثل کاری که در مورد کتابخونه modbus در makefile انجام دادیم باید انجام بشه ، مثلا اگه کتابخونه uart توی ساب دایرکتوری uart باشه باید به صورت زیر در داخل makefile معرفی بشه :


                  کد:
                  # List C source files here. (C dependencies are automatically generated.)
                  SRC = $(TARGET).c 
                  SRC += modbus.c 
                  SRC += Uart/uart.c


                  پایان قسمت نوزدهم

                  دیدگاه


                    #54
                    پاسخ : آموزش AVR-GCC

                    دو تا سوال داشتم از خدمتون
                    1-علامت «<-» در win avr به چه معناست؟
                    2-در مورد اشاره گرها:

                    کد:
                    xclass *var;
                    var = (xclass*)data;
                    خط دوم دیگه متوجه نمی شم منظورش چیه .اگهxclass یه کلاس باشه .توپرانتز data یعنی چی؟ بعضی اوقات هم قبل dataیه علامت &iهم هست.dataهم یه آرایه با اعضا یک بایتیه.

                    دیدگاه


                      #55
                      پاسخ : آموزش AVR-GCC

                      با سلام
                      1-علامت «<-» در win avr به چه معناست؟
                      خوب این مربوط به زبان سی هست ، قبل از اینکه جواب بدم آیا با ساختمان داده (استراکچر) آشنا هستید ؟


                      2-در مورد اشاره گرها:

                      کد: [انتخاب]

                      xclass *var;
                      var = (xclass*)data;


                      خط دوم دیگه متوجه نمی شم منظورش چیه .اگهxclass یه کلاس باشه .توپرانتز data یعنی چی؟ بعضی اوقات هم قبل dataیه علامت &iهم هست.dataهم یه آرایه با اعضا یک بایتیه.
                      تو خط اول یه اشاره گر از نوع ساختمان داده xclass تعریف شده.
                      تو خط دوم هم اول یه type casting صورت میگیره و محتوای متغیر data در غالب ساختمان داده از نوع xclass در میاد ( نوع اشاره گری (اینجا var هست) که آدرس data باید در اون قرار بگیره) و آدرس اش تو اشاره گر var قرار میگیره.

                      احتمالا علامت & با توجه به نوع برخورد شما با اون ، عملگر & هست که برای دسترسی به آدرس یه متغیر استفاده میشه و تو این موردی هم که بهش اشاره کردید داره آدرس متغیر data (آدرس اولین بایت متغیر data) رو بر میگردونه.

                      دیدگاه


                        #56
                        پاسخ : آموزش AVR-GCC

                        نوشته اصلی توسط mojtaba_led
                        با سلام خوب این مربوط به زبان سی هست ، قبل از اینکه جواب بدم آیا با ساختمان داده (استراکچر) آشنا هستید ؟
                        سلام خدمت شما
                        تشکر از بابت پاسخی که دادید
                        والا از لحاظ برنامه نویسی در فقر به سر می برم. درمورد ساختمان داده هم فقط در حد شنیدن بلدم و به صورت کاربردی نه.اگه یه توضیحی در موردش بدید خیلی ممنون میشم.یه سوال درهمین مورد؛ ساختمان داده همون کلاسه؟یا کلاس یه مفهوم دیگه داره؟
                        نوشته اصلی توسط mojtaba_led
                        تو خط اول یه اشاره گر از نوع ساختمان داده xclass تعریف شده.
                        تو خط دوم هم اول یه type casting صورت میگیره و محتوای متغیر data در غالب ساختمان داده از نوع xclass در میاد ( نوع اشاره گری (اینجا var هست) که آدرس data باید در اون قرار بگیره) و آدرس اش تو اشاره گر var قرار میگیره.

                        احتمالا علامت & با توجه به نوع برخورد شما با اون ، عملگر & هست که برای دسترسی به آدرس یه متغیر استفاده میشه و تو این موردی هم که بهش اشاره کردید داره آدرس متغیر data (آدرس اولین بایت متغیر data) رو بر میگردونه.
                        یه مقدار گیج شدم. اول درموردtype casting معنیش چیه؟
                        قسمت دومی هم که گفتید"محتوای متغیر data در غالب ساختمان داده از نوع xclass در میاد"یعنی اگه ارایه data قبلا اگه از هر نوعی تعریف شده بوده الان نوعش از نوع ساختمان داده xclass در میاد؟
                        " آدرس متغیر data (آدرس اولین بایت متغیر data) رو بر میگردونه."چرا بایت اول؟
                        ببخشید یه مقدار سوادم کمه.

                        دیدگاه


                          #57
                          پاسخ : آموزش AVR-GCC


                          خوب اول ،
                          20.مختصری در مورد Structure

                          خوب ببینید ما تو زبان سی انواع داده داریم مثل char, int , float ,unsigned char,unsigned iint,long in و ... که همونطور که میدونید میتونیم با استفاده از پیشوندها ترکیبات جدید بسازیم اما اینها همگی به یک نوع داده خاص دلالت میکنند ، یعنی ما نمیتونیم تو یه داده از نوع int هم کاراکتر بریزیم هم عدد !

                          خوب فرض کنید که سازمان ثبت احوال میخواد اطلاعات هر نفر رو اعم از نام ، نام خانوادگی ، نام پدر ، تاریخ تولد ، محل صدور، شماره شناسنامه، کد ملی و ... رو تو یه متغیر ذخیره کنه .
                          خوب اگه بخواد این ها رو ذخیره کنه باید برای اون هایی که به صورت کارکتر هستند بیاد یه آرایه دو بعدی که بعد اولش تعداد کاراکتر های مورد نیاز برای هر نفر و آرایه دومش تعداد آدم ها هستند رو از نوع char تعریف کنه و برای اون هایی که از نوع عدد هستند باید برای یه ارایه دوبعدی تعریف کنه که تو بعد اول تعداد درایه مورد نیاز برای اون اطلاعات خاص و تو بعد دوم تعداد آدم ها رو از نوع مثلا int تعریف کنه .

                          خوب حالا این به خودش میگه چی میشد من یه متغیر داشتم که به اندازه آدم ها آرایه داشت و تو همون متغیر اطلاعات رو وارد میکردم . خوب این آقا چیزی که میخواد اینه که یه نوع داده باشه ، 120 بایتی ، که تو مثلا 100 بایت اولش بشه کارکتر گذاشت تو 20 بایت بعدش عدد بعد هم به صورت آرایه تک بعدی باشه و بعدش هم به اندازه تمام آدم ها باشه .

                          خوب همونطور که میدونید ما همچین چیزی تو زبان سی نداریم ، پس باید این "نوع داده جدید رو ایجاد کنیم " این کار با استفاده از دستور struct به فرم کلی زیر انجام میشه :


                          کد:
                          struct "اسم نوع داده جدید"{
                          
                          لیست عناصر داده ;
                          };


                          مثلا فرض کنید میخواییم همین نوع داده ای که سازمان ثبت احوال لازم داره رو ایجاد کنیم ،مینویسیم :

                          کد:
                          struct personal{
                          
                          char first_name[20];
                          char last_name[20];
                          char father_name[20];
                          int date_of_birth;
                           
                          };


                          خوب این از نوع داده جدید .

                          اما ما که صرفا نمیخواییم فقط یه نوع داده تعریف کنیم ،مگه نه !؟

                          چیزی که سازمان ثبت احوال میخواست "یه متغیر با یه نوع داده جدید" بود.

                          پس باید متغیر هامون رو هم با نوع داده جدید تعریف کنیم تا بتونیم ازشون برای کاری که می خواهیم استفاده کنیم .

                          فرم کلی تعریف متغیر مثل تعریف متغیر های معمولی هست که به قرار زیر هست :

                          struct "اسم متغیر" "اسم نوع داده جدید"


                          یا مثلا همون موقع که نوع رو ایجاد میکنیم ، پشت بندش متغیر ها مون رو هم تعریف میکنیم ، تو این حالت در صورت عدم نیاز به این نوع داده جدید برای تعریف متغیر هایی از این جنس داده در مکان های دیگه میتونیم از اسم نوع داده جدید فاکتور بگیریم و حذفش کنیم ، به صورت زیر :

                          کد:
                          struct {
                          
                          لیست عناصر داده ;
                          } "اسم متغیر"


                          خوب حالا میتونیم یه متغیر با اون نوع داده ای که سازمان ثبت احوال میخواست ایجاد کنیم ، اسم متغیر رو هم person میزاریم و از نوع personal(که قبلا این توع داده رو تعریفش کردیم) رو به صورت یه متغیر مثلا 1000 درایه ای که قراره تو هر داریه مشخصات یه نفر قرار بگیره ، به صورت زیر تعریف میکنیم :

                          struct personal person[1000];


                          یا :


                          struct {

                          char first_name[20];
                          char last_name[20];
                          char father's_name[20];
                          int date_of_birth;

                          }person[1000];


                          خوب حالا برای دسترسی به هر کدوم از عناصر متغیر جدید مون که به صورت ساختمان داده هست باید از "." استفاده کنیم .

                          مثلا فرض کنید که میخواییم اطلاعات شخص شماره 20 رو برای سازمان ثبت احوال ثبت کنیم ، داریم :


                          person[20].first_name="ali";
                          person[20].last_name="taghipour";
                          person[20].father_name="hasan";
                          person[20].date_of_birth=1370;



                          حالا فرض کنید ما میخواهیم یه داده از این رو به صورت اشاره گر تعریف کنیم ، اسم اون دادمون هم مثلا person هست ، باید به صورت زیر عمل کنیم :

                          کد:
                          struct personal *person;


                          حالا ما اگه بخواهیم به اعضای این داده جدیدمون دسترسی داشته باشیم باید از عملگر "<-" استفاده کنیم ، مثلا فرض کنید میخواهیم به اسم کوچیکش دسترسی پیدا کنیم باید به این صورت عمل کنیم :

                          کد:
                          person->first_name="mojtaba";


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

                          خوب به نظرتون باید اینجا چه کار کرد !؟

                          خوب یه راه حل اینه که بیاییم از ساختمان داده به صورت لانه ای استفاده کنیم ، یعنی چی؟
                          ببینید همونطور که دید تا اینجا عناصرساختمان نوع داده های جدید که تعریف کردیم از نوع داده های استاندارد زبان سی بود ، حالا این عناصر میتونند از نوع یه ساختمان داده جدید که قبلا ایجادشون کرده بودیم باشند .

                          خوب پس برای این مورد آخر یعنی اعمال آدرس و تاریخ تولد بر حسب روز ماه و سال کاری که به نظر من میرسه ، میشه از این تکنیک تعریف ساختمان ها به صورت لانه ای استفاده کرد به ترتیب زیر :

                          1. بیاییم اول ساختمان داده آدرس که شامل عناصر : استان ، شهر خیابان ، کوچه و پلاک هست به صورت زیر تعریف کنیم :

                          کد:
                          struct address {
                          char town[20];
                          char city[20];
                          char street[20];
                          char alley[20];
                          int no;
                           
                           };


                          2. بیاییم ساختمان داده تاریخ رو با عناصر روز ، ماه و سال به صورت زیر تعریف کنیم :

                          کد:
                           struct date{
                           
                           int day;
                           int month;
                           int year;
                           
                           };


                          3. حالا بیاییم ساختمان داده اصلی که متغیر مشخصات افراد از اون نوع تعیین میشه به صورت زیر بنویسیم :

                          کد:
                          struct {
                          
                          char first_name[20];
                          char last_name[20];
                          char father_name[20];
                          struct address addr;
                          struct date birth; 
                          }person[1000];


                          حالا بجای اینکه بیاییم جدا جدا ساختمان داده رو تعریف کنیم و بعد بیاییم از اون ساختمان دادهذ برای تعریف یه متغیر جدید داخل یه ساختمان داده دیگه استفاده کنیم اون ساختمان داده و متغیر از اون جنس رو هم داخل همون ساختمان داده اصلی تعریف میکنیم مثلا برای مثال قبل داریم :

                          کد:
                          struct {
                          
                          	char first_name[20];
                          	char last_name[20];
                          	char father_name[20];
                          
                          		struct {
                          			char town[20];
                          			char city[20];
                          			char street[20];
                          			char alley[20];
                          			int no;
                          			}addr;
                          		
                          		struct{ 
                          			int day;
                          			int month;
                          			int year;
                          			}birth; 
                           
                          }person[1000];

                          خوب حالا بیایید مثلا مشخصات همون نفر 20 ام رو دوباره وارد کنیم :

                          کد:
                          person[20].first_name="ali";
                          person[20].last_name="taghipour";
                          person[20].father_name="hasan";
                          person[20].birth.day=31;
                          person[20].birth.month=6;
                          person[20].birth.year=1370;
                          person[20].addr.town="Tehran";
                          person[20].addr.city="Eslamshahr";
                          person[20].addr.street="Emam khomyni";
                          person[20].addr.alley="Shahid kazemi";
                          person[20].addr.no=51;



                          پایان قسمت بیستم

                          دیدگاه


                            #58
                            پاسخ : آموزش AVR-GCC

                            جناب استاد مجتبی سلام
                            واقعا مطالب راه گشایی بود .
                            خدا قوت
                            یه سوال :
                            توهمون مثالی که زدید؛
                            فرض کنید که ،همون ساختمان داده Personal رو ایجاد کردیم و یه داده هم به اسم person ازاین ساختمان تعریف کردیم . آیا حالا می شه یه اشاره گر از این داده که از جنس ساختمان Personal هست ، ساخت؟

                            دیدگاه


                              #59
                              پاسخ : آموزش AVR-GCC

                              بله میشه!
                              آقا اون وسط اش یه مثال در این مورد زدما!

                              دیدگاه


                                #60
                                پاسخ : آموزش AVR-GCC

                                نوشته اصلی توسط mojtaba_led
                                بله میشه!
                                آقا اون وسط اش یه مثال در این مورد زدما!
                                باسلام
                                اون قسمتو خوندم. ولی منظورم یه مقدار با توضیحی که دادید فرق داره :
                                کد:
                                }struct personal
                                
                                ;[char first_name[20
                                ;[char last_name[20
                                ;[char father_name[20
                                ;int date_of_birth
                                 
                                ;[person[1000{
                                 
                                ; person *Ptrperson
                                یعنی بجای اینکه اشاره گر از نوع ساختمان Personalباشه از نوع Person
                                اگر این طوری بشه دلیلش چیه ؟ آیا این روش کاربرد خاصی داره؟

                                دیدگاه

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