اطلاعیه

Collapse
No announcement yet.

کد نویسی تحت avr gcc

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

    کد نویسی تحت avr gcc

    سلام

    دیشب برای اولین بار توی نت پد winavr داشتم مثلا کد می نوشتم
    یه سوالی برام پیش اومد
    اکثر برنامه های نوشته شده تحت winavr دیدم که وقتی می خواند وضعیت از بیت رو تغییر بدن مثلا می خوان بیتی رو 1 بکند این کار رو به شکل زیر انجام می دن
    PORTB&=~(1<<1)
    یا
    PORTB|=1<<1
    خوب همون کاری رو که خواسته میشه انجام می ده یعنی بیت مشخصی رو تغییر می ده
    در حالیکه این کار رو که عملگرهای شیفت و نسبت دهی انجام شده میشه ساده تر از اون انجام داد
    القصه ما فکر کردیم ما خلیم یا بالا نسبت ملت برنامه نویس
    ولی دیدم نه اینم نیست

    حالا سوالی دارم ایا این کار توی مرحله کامپایل کردن ( یا کارهای مشابه همین توی برنامه نویسی ) باعث میشه که کامپایلر کدهای ماشین سر راستی رو تولید بکنه ؟؟؟

    نمی دونم ولی واقعا واسم سوال شد یعنی نمیشد اینا رو بیتی رو راحت دستکاری کرد چرا بایتی روی اونا کار کرده البته من منظورم واسه تغییر بیتی بود
    صد البته اگه این کار رو برای چند بیت باهم انجام می داد صلاح بود
    ممنونم :mrgreen:

    #2
    پاسخ : کد نویسی تحت avr gcc

    سلام :smile:

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

    کد:
    [left]UCSRB = (1<<RXEN)|(1<<TXEN)[/left]
    عملوند اپراتور شیفت که که مقدار شیفت رو تعیین می کنه در Header File به صورت Macro تعریف شده و با مقدار خودش جایگزین خواهد شد و این فقط کار شما رو راحت می کنه یعنی نیاز نیست حفظ باشید که مثلا RXEN و TXEN بیت چندم از رجیستر UCSRB است
    There is nothing so practical as a good theory. — Kurt Lewin, 1951

    دیدگاه


      #3
      پاسخ : کد نویسی تحت avr gcc

      همونطور که دوستمون گفتن اونها ماکرو ها هستند .

      به اصتلاح Pre Processoring . یعنی کامپایلر قبل از اینکه کد شما رو کامپایل کنه یه سری تغییرات روی کد شما انجام میده .

      مثلا میتونی این ماکرو هارو تو یه فایل header قرار بدی و اونو include کنی

      کد:
      #ifndef BV
      	#define BV(bit)			(1<<(bit))
      #endif
      #ifndef cbi
      	#define cbi(reg,bit)	reg &= ~(BV(bit))
      #endif
      #ifndef sbi
      	#define sbi(reg,bit)	reg |= (BV(bit))
      #endif
      نمیدونم C PP بلدید یا نه اما یه توضیح کوچک میدم .

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

      ماکرویی با نام BV تعریف شود با ان مشخصات .

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

      حالا اگر من جایی از BV به این شکل استفاده کنم :

      PORTB = BV(3)

      کامپایلر در مرحله CPP کد مارو به این صورت تغییر میده :

      PORTB = (1<<(3))

      که البطه عبارت بالا غلط است ولی هدف شناسوندن ماکرو ها بود .

      حالا مثلا من اگر ماکرویی تعریف کنم به این صورت

      #define UCRLF uprintf("\r\n\&quot

      و هرجا در کد از UCRLF; استفاده کنم در مرحله CPPآ‌ کد به uprintf("\r\n\&quot تغییر میکنه .


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

      ---

      ماکرو های بالا رو میتونید به این صورت استفاده کنید

      sbi(PORTB,1) ; // set portb , pin 1 to 1
      cbi(PORTB,1); // set portb, pin 1 to 0

      sbi(DDRB,0); // set portb , pin 0 to output

      تمام این رجیستر ها هم ماکرو هستند .

      وقتی شما در makeFile میکرو رو Atmega X معرفی میکنید کامپایلر بطور خودکار فایل atmegaX.h رو در کد شما انکلود میکنه که شامل

      ...

      #define PINB _SFR_IO8(0x01)

      #define DDRB _SFR_IO8(0x02)

      ...

      هست .

      درضمن فکر میکنم منظور شما این است که چرا از عبارتی مانند PORTB1 یا PORTB.1 استفاده نمیکنیم ،آ‌اگر این است بگویید تا جوابش رو بدهم .
      فتو بلاگ من
      کاردستی ها :
      روبات شطرنج باز ( یادگار دوران جوانی )
      فارسی نویسی مستقیم در نمایشگر های گرافیکی
      کتابچه خود آموز زبان توصیف سخت افزار Verilog

      دیدگاه


        #4
        پاسخ : کد نویسی تحت avr gcc

        وا این فروم چرا اینقدر مشکلات نمایش داره ؟! مدیر جان درستش کن . :rolleyes:
        فتو بلاگ من
        کاردستی ها :
        روبات شطرنج باز ( یادگار دوران جوانی )
        فارسی نویسی مستقیم در نمایشگر های گرافیکی
        کتابچه خود آموز زبان توصیف سخت افزار Verilog

        دیدگاه


          #5
          پاسخ : کد نویسی تحت avr gcc

          با سلام
          ممنونم از توضیحاتتون
          دوست عزیز اقای shankimout دقیقا
          سوال من همینه که فرمودید :
          درضمن فکر میکنم منظور شما این است که چرا از عبارتی مانند PORTB1 یا PORTB.1 استفاده نمیکنیم ،آ‌اگر این است بگویید تا جوابش رو بدهم .
          خوب واسه تغییرات نمیشد ساده تر از این کاری کرد
          منتظر هستم

          دیدگاه


            #6
            پاسخ : کد نویسی تحت avr gcc

            اون رجیستر هارو ( اگه بشه اسمشو گزاشت ) فقط bascom و CV میشناسن . چون از خودشون در آوردن . در اصل باید شما بر روی بیت های یک بایت++ تغییرات انجام بدید . هالا اونا اومدند کار شمارو یکم راحت تر کردند . شرمنده بهتر از این نمیتونم توضیح بدم .

            اگه واقعا به اونا عادت کردی و میخوایی تو GCCآ‌ هم اونارو داشته باشی باید Macro بنویسی . برای تک تک پورت ها ، تک تک بیت ها . میتونی برای PORTB یه ماکرو یی بنویسی که مثل CV یا بسکام بتونی حد اقل از اون برای خروجی استفاده کنی ولی خوب مثل اون در نمیاد .

            دلیل اینکه GCC اینهارو نداره اینه که GCC ، کد هارو بر اساس استاندارد آ‌C 99 یا Gnu99 ( همون ANSI ) تفسیر میکنه و اینها رو نمیشه در این استاندارد ها گنجوند . تنها راهش همون ماکرو نویسیه .

            درکل توصیه میکنم به اینا عادت کنی .

            [tt]

            // first we must kill bascom & cv

            #undef CodeVision
            #undef Bascom

            #define GCC[/tt]
            فتو بلاگ من
            کاردستی ها :
            روبات شطرنج باز ( یادگار دوران جوانی )
            فارسی نویسی مستقیم در نمایشگر های گرافیکی
            کتابچه خود آموز زبان توصیف سخت افزار Verilog

            دیدگاه


              #7
              پاسخ : کد نویسی تحت avr gcc

              با سلام
              ممنونم از توضیحاتتون
              بله امروز وقتی داشتم فایل های Include IO چند تا از میکرو ها رو نگاه می کردم دیدم که رجسیترها رو باید بایتی دستکاری کردولی خوب اینم فرقی نمی کنه من بد عادت نیستم :mrgreen:
              خوب بله همون طوری که عرض کردید میشه توی ماکروها هم این کار رو انجام داد
              خوب واقعیتش جواب سوالمو کامل گرفتم



              دیدگاه


                #8
                پاسخ : کد نویسی تحت avr gcc

                مگه تو gcc نمیشه بیت رو تغییر داد ! اگه نشه که بدرد نمیخوره .

                با همون روشی که بالا گفتم میتونید بیتی تغییر بدید .
                فتو بلاگ من
                کاردستی ها :
                روبات شطرنج باز ( یادگار دوران جوانی )
                فارسی نویسی مستقیم در نمایشگر های گرافیکی
                کتابچه خود آموز زبان توصیف سخت افزار Verilog

                دیدگاه


                  #9
                  پاسخ : کد نویسی تحت avr gcc

                  بله شما فرمودی میشه تغییر داد ولی با اون روشی که توی CV هست با اون روش نه
                  بلکه به یه صورت دیگه همین مسله منو به اشتباه انداخت وقتی شما گفتی که چون سی استاندارده من اون موقع فهمیدم که یعنی چی :applause:
                  ممنونم

                  دیدگاه


                    #10
                    پاسخ : کد نویسی تحت avr gcc

                    جمله زیر را از دیتاشیت megaAVR آورده ام به این معنی که :
                    درسته که برای تغییر بیتی ظاهرا با بایت کار میکنیم ولی کل این دستور در یک سیکل ماشین انجام میشه
                    و این دستورات مشابه آن است که یک رجیستر را با یک مقدار and یا or بکنیم
                    All AVR ports have true Read-Modify-Write functionality when used as general digital I/O ports

                    دیدگاه


                      #11
                      پاسخ : کد نویسی تحت avr gcc

                      با سلام
                      شاید این پست پریدن با دمپایی وسط صحبت باشه ولی به نظرم اینجا اشتباه داره در نظر گرفته میآ‌شه

                      اگر دوستان منظورشون از پیش پردازش همون PreProcessor است که کار define کردن و ماکرو و includeها و ... رو انجام میآ‌ده، باید گفت که معلوم بودن مقدار شیفتآ‌ها که آقای سپاسیار به درستی به آن اشاره کردند کار pp نیست. درواقع pp توان تشخیص این موضوع رو نداره بلکه این وظیفه در حقیقت جزو اولین مراحل optimize کردن است که در کامپایلر انجام میآ‌شه. کامپایلر در جایی کار رو شروع میآ‌کنه که کار PP تمام شده و تمام تغییرات لازم در کد انجام گرفته است.
                      برای مطالعه بیشتر: http://en.wikipedia.org/wiki/C_preprocessor

                      بازهم شرمنده اگر با دمپایی پریدم وسط!
                      من دوست دارم آزاد فکر کنم، نرمآ‌افزارآ‌ و سختآ‌افزارهای آزاد را به کار ببرم و اگر توانستم نرمآ‌افزار، سختآ‌افزار و محتوای آزاد درست کنم!

                      دیدگاه


                        #12
                        پاسخ : کد نویسی تحت avr gcc

                        این مطلب رو یه نگاه بندازین بد نیست:
                        http://www.4shared.com/file/55928516...ified=2fbd5356

                        دیدگاه


                          #13
                          پاسخ : کد نویسی تحت avr gcc

                          نوشته اصلی توسط yek_doost
                          جمله زیر را از دیتاشیت megaAVR آورده ام به این معنی که :
                          درسته که برای تغییر بیتی ظاهرا با بایت کار میکنیم ولی کل این دستور در یک سیکل ماشین انجام میشه
                          و این دستورات مشابه آن است که یک رجیستر را با یک مقدار and یا or بکنیم
                          All AVR ports have true Read-Modify-Write functionality when used as general digital I/O ports
                          خوب برای برسی این مساله نیاز به دانستن زبان ماشین avr داریم
                          اگه بخوایم یه رجیستر I/O رو به صورت بیتی دستکاری کنیم مثل portb.1=1 برای این کار تمام avr ها دو دستور ویژه به نام sbi , cbi دارن که فقط روی رجیستر های port * ,pin * ,ddr * عمل میکنند 1=portb.1 به دستور اسمبلی sbi portb,1 تبدیل خواهد شد

                          خوب سه حالت دیگه وجود داره که برای اونها با یک دستور و یک پالس ساعت نمیشه این کار رو انجام داد
                          حالت بعدی اینه رجیستر ما جز رجیسترهای تنظیمات باشه (مثل timsk tifr tccrX tcntX,...) که در این حالت با سه پالس این عمل انجام میشه
                          in r16,tifr
                          andi r16,0b11111101
                          out tifr,r16
                          که ما بیت شماره 1 tifr رو 0 کردیم و برای 1 کردنش باید همین دستورات رو و به جای andi از دستور ori r16,0b00000010 استفاده کنیم هیچ راه دیگه ای هم نداره!.
                          دو دستور دیگه هم وجود دارن به نام sbr , cbr که به ترتیب معادل ori ,andi هستند و حتی کد ماشین یکسانی هم تولید میکنن.

                          حالت بعدی اینه که یکی از رجیسترهای working(R0-R31) باشه که دیدید با andi , ori برای
                          رجیستر های (r16-r31) انجام میشه و برای r0-r15 باید از or , and استفاده کرد
                          (به طور کلی دستوراتی که i دارن رو نمیشه با رجیسترهای نیمه پایینی به کار برد)

                          حالتی که الان میخام بگم بدترین حالته(از نظر سرعت) و اون اینه که جایی رو که میخوایم دستکاری کنیم یه مکان از حافظه باشه (یه متغیر تو حافظه ram) مثل این
                          lds r16,0x60
                          ori r16,0b00000010
                          sts 0x60,r16
                          (بیت شماره 1 از متغیری که در ادرس 0x0060 تعریف شده 1 کردیم)
                          خوب هر دسترسی به ram با هر دستوری 2 پالس نیاز داره
                          که در مجموع 5 پالس لازمه
                          این کار رو نه فقط برای تغییز بیتی بلکه برای هر عمل دیگه ای مثل i++ باید انجام داد و عملیات ریاضی و منطقی فقط روی رجیسترهای working انجام میشه :surprised:
                          اینجاست که اهمیت استفاده از رجیستر به جای ram در قسمتهایی که دستیابی زیاد دارن مثل شمارنده حلقه مشخص میشه.
                          مثل اینکه خیلی طولانی شد.


                          Qt - A cross-platform application and UI framework

                          با کامپایلرهای قدرتمند GCC در Linux و MinGw در Windows

                          دیدگاه

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