اطلاعیه

Collapse
No announcement yet.

آموزش winavr و avrlib

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

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

    در تعریف s اومده:

    char s[sizeof("4294967295&quot];


    این عدد 4294967295 همون عدد 0xFFFFFFFF هست در مبنای دهدهی و این یعنی بزرگترین عددی که میتونه یک نوع unsigned long در خودش نگهداری کنه. از طرفی وقتی یک عدد رو با تابع ultoa به آسکی تبدیل میکنین این تابع نمیتونه چک کنه که آیا بافر شما جا به اندازه کافی داره یا نه. بنا براین اون کسی که این کد رو نوشته به خیال خودش زرنگی کرده و میخواسته برای بد ترین حالت (یعنی وقتی عدد ورودی به تابع بزرگترین باشه) s دارای جا باشه. بنا براین اومده بزرگترین عدد این نوع رو به رشته تبدیل کرده و به اندازه اون حجم رشته رو برای s حافظه تخصیص داده. اما فراموش نکنیم که بعد از تمام کاراکتر ها در یک رشته حرفی عددی در زبان C یک کاراکتر '0\' هم احتیاجه. بنابراین strlen اینجا بدرد نمیخوره و بایستی از sizeof استفاده بشه. ضمنا strlen یک تابع زمان اجرا هست در صورتی که sizeof یک تابع مجازی زمان کامپایل هست. و این sizeof هست که اون '0\' انتهایی رو هم حساب میکنه (در این کیس بخصوص).

    در مورد کذایی پورت مربوطه فرض کنیم شما میخوای بیت سوم از PINA رو چک کنی. میتونی بگی:


    if(PINA & (1<<3))
    {
    }


    و همینطور که میبینی احتیاجی به استفاده از متغیر هم نیست.

    دیدگاه


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

      سلام.
      من منظورتون رو متوجه نمیشم!!
      مثلا با دستور char s[sizeof("4294967295&quot]; مقدار s برابر چند میشه؟؟
      من مقدار s رو کمتر از 100 که میزارم روی lcd هیچی نشون نمیده!!!
      لطفا در حد زبون بیسیک توضیح بدید :biggrin:
      در ضمن:
      چطور میتونم چند تا متغییر رو روی lcd نشون بدم مثل ساعت؟؟به این صورت :
      HH:MM:SS

      دیدگاه


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

        مرده شور این ادیتور رو ببرن. هر چی تایپ کرده بودم پرید. این دفعه چهارم پنجمه. اگه بازم پیش بیاد دیگه جواب نمیدم!


        ببین آقا جون!
        من خونواده ام چهار نفره هست.
        من میتونم بگم:
        "یه اتوموبیلی میخوام که خونواده من توش جا بشه" و خونواده خودم رو پیش ماشین فروش ببرم.
        میتونم بگم:
        "یه اتوموبیل 4 نفره میخوام"

        حالا در بیسیک میتونم بگم:
        آرایه ای میخوام داشته باشم که بشه متنی مثل "Hassan" رو درش جا داد.
        میتونم بگم:
        آرایه ای میخوام که بشه متنی 6 حرفی رو توش جا داد.

        عینا میتونم بگم:
        میخوام s بتونه عددی مثل "4294967295" توش جا بشه.
        میتونم بگم:
        میخوام s بتونه عددی 10 رقمی توش جا بشه.

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

        حالا چرا توی C گفتیم sizeof؟ چون این یک تابع مجازی هست که در زمان کامپایل اجرا میشه. یعنی اگه گفتین:

        int a = sizeof(char);


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

        mov a,1


        اما برای یک رشته کاراکتری ما دو قسمت داریم. یکی خود متنی که میبینیم. و یکی اون کاراکتری که انتهای رشته رو مشخص میکنه. یعنی حجم رشته "100" برابر با 4 بایته. نه سه بایت. طول این رشته سه بایت هست. و این تابع sizeof حجم رو برمیگردونه.

        برای نمایش چند تا متغیر مثل ساعت میتونین از چیزی مثل این استفاده کنین:


        char s[30];

        sprintf(s, "%02u:%02u:%02u", hour, minute, seconds);
        lcd_puts(s);


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

        ضمنا در حالت اول که s رو قید کرده بودین. چون اپراتور = نیومده عمل مقدار دهی به s صورت نگرفته و فقط تعریف آرایه بوده و بس. دلیل نمیشه چون متغیر آرایه کاراکتری هست یک جایی هم یک ثابت کاراکتری به چشمتون خورده پس اون ثابت مقدار اولیه این آرایه هست.

        دیدگاه


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

          سلام.
          خیلی ممنون که جواب میدید.
          یه مشکل دیگه برام پیش اومده !!
          وقتی میخوام روی lcd یه جمله 16 کاراکتری نشون بدم (lcd 16*2) دو تا کاراکتر آخر روشن نمیشه یعنی چیزی نشون نمیده به نظر شما مشکل از چی میتونه باشه؟؟(هم خط اول و هم خط دوم اینجوریه!!)
          lcd از نوع 20*2 انتخاب کردم ولی باز هم همین مشکل روداشتم!!
          یه سوال دیگه:
          چرا کد هگز خروجی این همه حجمش زیاده؟؟
          با بیسکام مقایسه کردم حدود 4 کیلو حجمش بیشتره!!!
          یکی از دلیلهایی که اومدم سمت winavr این بود که گفتن حجم کد خروجی کمتره!!!
          مشکل از کجاست؟؟

          دیدگاه


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

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

            دیدگاه


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

              سلام
              این چند مدته به کاری گیر کردم که مجبورم چند تا کارو هم زمان انجام بدم ، همون Muti Tasking
              البته با میکرو منظورمه :mrgreen:
              کارایی از نوشتن از روی LCD ، خوندن از تاچ پد ، اجرای یک فیلتر دیجیتال ، PWM اونم چند تا در آخر گرفتن دیتا که البته سریال و با ماژول هست
              حالا شایدم یه چند تایی هم اضافه و کم شد
              بعضی از بالایی ها رو میشه با وقفه یه جورایی درستشون کرد ولی در کل یه جایه کار گیر میکنه
              حالا می خواستم اگر منبع و رفرنسی دارید معرفی کنید (یه تاپیک داخل AVR Freaks بود که برا شروع بد نیست)

              یکمی هم اینجا در رابطه اش بحث کنیم و استفاده کنیم از محضر بزرگواران
              به طور مثال از این جا شروع کنیم که می خواهیم 4 تا PWM تولید کنیم و راه اندازی LCD
              { خلاف قوانین - پاک شد }

              دیدگاه


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

                با تمام این احوالات بازم الزامی به multi-tasking ندارین. میتونین از تکنیکهایی مشابه message pumping در ویندوز یا حتی ماشین وضعیت استفاده کنین.
                منتهی باید منطق برنامه تون بیشتر بر اساس رویداد باشه و ضمنا منطق های مورد استفاده بر اساس اطلاعات داخل پشته کار نکنن. یا اصطلاحا context free باشن.

                دیدگاه


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

                  ببنید برای کار با LCD مشکل شما دقیقا چیه؟
                  برای نوشتم روی LCD باید از کد اسکی استفاده کرد که برای مثال برای حرف 'A' برابر است با 65 یعنی از نظر ارزش 65='A' و یک نوع داده ای char است
                  حالا اگر بخواهیم خود عدد 65 را روی LCD نشان بدیم چه باید کرد؟
                  می خواهم بگم که عدد 6 با کاراکتر '6' با هم تفاوت دراد مقدار اسکی '6' برابر 56 است
                  خوب برای اینکه هر عدد رو به رشته تبدیل کنیم ، میتوانیم از تابع هایی مثل itoa و.... استفاده کنیم و یا اگر نخواستیم بنویسیم 6+'0'
                  یعنی مقدار اسکی '6' را اینطوری به دست آوردیم '6' = '0' +6

                  در بیسیک می نویسیم برای چک کردن مقدار یک پایه از میکرو
                  [pre]if PINX.2=1 then 'your code'[/pre]

                  در زبان سی می تونی بنویسی
                  if (PINX & 2) {'your code'}
                  یا
                  if (PINX&(1<<2){'your code'}

                  حالا مشکل شماچیه؟
                  { خلاف قوانین - پاک شد }

                  دیدگاه


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

                    نوشته اصلی توسط reza_agha
                    با تمام این احوالات بازم الزامی به multi-tasking ندارین. میتونین از تکنیکهایی مشابه message pumping در ویندوز یا حتی ماشین وضعیت استفاده کنین.
                    منتهی باید منطق برنامه تون بیشتر بر اساس رویداد باشه و ضمنا منطق های مورد استفاده بر اساس اطلاعات داخل پشته کار نکنن. یا اصطلاحا context free باشن.
                    خوب من زیاد با این چیزایی که گفتید آشنایی ندارم
                    قضیه یه آدم کوره که به جای دیدن با دست کشیدن می خواد بفهمه :rolleyes: فهم منم الان در اون حده

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

                    فرض کنیم که می خواهیم 4 تا پالس PWM روی 4 تا پایه میکرو ایجاد کنیم
                    فعلا به PWM سخت افزاری کار نداریم و نرم افزاری می خواهیم
                    خوب یه حلقه ایجاد می کنیم و میگیم طبق یه روالی بچرخ!
                    الان نمی دونم چرا هیچی به جز delay به ذهنم نمیرسه :surprised:

                    آهان این کارو کنیم ، اول بیایم ببنیم که کدام تغییر وضعیت سری تر اتفاق می افته مثلا تو یه جایی این تغییر ها رو مرتب کنیم و دونه دونه با تاخیر لازم اجراشون کنیم
                    خوبه اینجوری برای PWM?

                    از این چیزایی که بالا گفتید میشه سرنخ بدید به جز Tite شون ؟ :mrgreen:
                    { خلاف قوانین - پاک شد }

                    دیدگاه


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

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

                      بنا براین در یک برنامه تا میشه نباید DELAY داد. اون موقع که دارین DELAY میدین میتونین بجای "وقت تلف کردن" کار دیگه ای رو انجام بدین. البته مسلما دقت زمانی کمتری برای کاری که میخواستین توش DELAY بدین بوجود میاد. یه کمی گنگ شد. بذارین اینجوری بگم. فرض کنیم شما میخوایین یک pwm با نسبت 50/50 تولید کنین اون هم با فرکانس 1 کیلو هرتز. اگر شما از یک محیط MULTI TASK با زمان سوئیچ 1 میلی ثانیه استفاده کنین ممکنه هیچ وقت نتونین این کار رو انجام بدین. چرا؟ چون در یک میلی ثانیه برنامه شما اجرا میشه و در یک زمان بعدی که میتونه تا 1 میلی ثانیه هم ادامه پیدا کنه یک کار دیگه. چون زمان بین تسک ها به اشتراک گذاشته میشه.
                      بنا براین ساخت یک PWM به فرمی که ذکر شد قطعی نخواهد بود.

                      حالا فرض کنین میخواییم همین PWM رو با فرکانس 100 هرتز تولید کنیم. احتمال انجامش بیشتر میشه.
                      این از زمانبندی ها. ولی راجع به عناوینی که قید کردم. فعلا طلبتون فردا مسافرم و دیگه باید برم لالا. انشالله اگه عمری باقی بود چهارم فروردین خدمت میرسم. اگه خواستین مطمئن باشین یادم نمیره؛ یه PM برام بدین.

                      سال نو خوش.

                      دیدگاه


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

                        ممنون
                        من منظورم ام این بود یه چارتی بنویسم که داخل اون خودش Task ها رو جابه جا کنه و اونی که زودتر موقشه رو اجرا کنه
                        یعنی فرضا 4 تا PWM درام که هم فرکانس و هم Duty Time شون قابل تغییره
                        من چند تا متغیر داشته باشم مقدار اون ها رو که تغییر دادم پالس ها هم تغییر کنه

                        مسافرت خوش بگذره، مزاحمتون میشم بعدن
                        { خلاف قوانین - پاک شد }

                        دیدگاه


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

                          برای multi task نوشتن می تونی از سیستم عامل FreeRTOS استفاده کنی. واسه winavr پورت شده و خیلی راحت کار میکنه. یه سری به سایتش بزن.
                          اگرم با مفاهیمش آشنا نشدی، تا چند روز دیگه یه تاپیک تو بخش آرم درمورد سیستم عامل باز میشه که میتونی اطلاعات خوبی بگیری....
                          https://www.linkedin.com/in/mohammadhosseini69

                          http://zakhar.blog.ir

                          دیدگاه


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

                            شرمنده میپرم وسط بحثتون :(

                            من طبق همین راهنمای شما

                            نوشته اصلی توسط محمد حسینی
                            سلام
                            به درخواست یکی از دوستان، می خوام تو این تاپیک به کتابخونه ارتباط سریال uart رو معرفی کنم. این کتابخونه جدا از کتابخونه های avrlib و چون راحتر بود دیگه بیخیال کتابخونه uart Avrlib شدم. این فایل رو می تونین از اینجا دانلود کنید : (چرا سایت امکان پلود نداره؟؟!)
                            http://beaststwo.org/avr-uart/Updated%20_UART_Library.zip
                            کار کردن باهاش خیلی ساده. (البته یه باگ داشت که در راه پیدا کردنش، دست دوتا mega16 هام از این دنیا کوتاه شد و البته یه mega16 دیگه رو هم فلج کردم!! بهرحال در راه علم ...)
                            uart.h رو باز کنید. خیلی سریع بررسی می کنیم. یه ماکرو به شکل زیر تعریف کرده :

                            #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1)

                            این ماکرو برای معرفی کردن نرخ ارتباط سریال (یا همون سرعت خودمون!!) استفاده میشه. پارامتر هاش هم که مشخص، اولی baud و دومی فرکانس کلاک. بعد از این یه ماکرو دیگه یه نام UART_BAUD_SELECT_DOUBLE_SPEED برای استفاده از سرعت دو برابر تعریف شده.
                            ادامه:

                            /** Size of the circular receive buffer, must be power of 2 */
                            #ifndef UART_RX_BUFFER_SIZE
                            #define UART_RX_BUFFER_SIZE 32
                            #endif
                            /** Size of the circular transmit buffer, must be power of 2 */
                            #ifndef UART_TX_BUFFER_SIZE
                            #define UART_TX_BUFFER_SIZE 32
                            #endif

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

                            extern void uart_init(unsigned int baudrate);

                            این تابع uart رو فعال میکنه و مقداردهی های اولیه رو انجام میده. پارامتر تابع باید با ماکرو تعیین baud باشه. مثلا این دستور برای تعیین باوود 9600 برای کلاک 1 مگاهرتز :

                            uart_init(UART_BAUD_SELECT(9600, 1000000L));

                            بقیه توابع هم مشخص دیگه! من فقط با uart_puts کار میکنم. برای ارسال رشته. بقیه توابع بکار نمیان!!!
                            uart.c رو باز کنید. اینجا دو تا متغیر مهم داریم.
                            UART_RxBuf
                            این رشته، همون بافر برای نگه داری اطلاعات دریافتیه. هر بایت اطلاعاتی که بیاد تو این متغیر ذخیره میشه.
                            UART_RxHead
                            این متغیر نشون میده چند بایت تو بافر UART_RxBuf اطلاعات دریافتی ذخیره شده.
                            وقفه دربافت رو ببینید ...

                            ISR(UART0_RECEIVE_INTERRUPT)
                            /************************************************** ***********************
                            Function: UART Receive Complete interrupt
                            Purpose: called when the UART has received a character
                            ************************************************** ************************/
                            { …

                            این خط رو آخر وقفه می بینیم :

                            UART_RxBuf[tmphead] = data;

                            بایت دریافتی رو تو بافر مینویسه. اما یه مشکل داره! اونم اینه که از اندیس شماره 1 شروع به نوشتن میکنه نه صفر!! چراش رو دیگه خودتون تو چند خط بالاتر ببینین. خوب برای رفع این مشکل اینطوری تغییرش بدین:

                            UART_RxBuf[tmphead-1] = data;

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

                            #include <avr/io.h>
                            #include <util/delay.h>
                            #include "uart.c"
                            char *str="test serial";
                            int main()
                            {
                            sei();
                            uart_init(UART_BAUD_SELECT(9600, 1000000L));
                            _delay_ms(2000);
                            uart_puts(str);
                            _delay_ms(2000);
                            uart_puts("ok"
                            return 0;
                            }

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

                            #include <avr/io.h>
                            #include <util/delay.h>
                            #include "lcd.c"
                            #include "uart.c"
                            int main()
                            {
                            sei();
                            lcdInit();
                            uart_init(UART_BAUD_SELECT(9600, 1000000L));

                            while(1)
                            {
                            lcdClear();
                            if (UART_RxHead != 0)
                            lcdPrintData(UART_RxBuf, UART_RxHead);
                            _delay_ms(20);
                            }
                            }

                            دستور sei یادتون نره! وقفه ها باید فعال بشن.
                            ضمنا فریم ارسال اطلاعات هم تو تابع uart_init تعیین شده. پیش فرض همون 8 بیت داده بدون parity و یک بیت داده. معمولا همینه دیگه. مگه اینکه یه پروژه مخوف سری داشته باشین ... !!
                            موفق باشید.
                            درست کردم
                            این هم برنامم


                            #include <avr/io.h>
                            #include <util/delay.h>
                            #include "uart.c"
                            char *str="test serial";
                            int main()
                            {
                            sei();
                            uart_init(UART_BAUD_SELECT(9600, 1105920L));
                            _delay_ms(2000);
                            uart_puts(str);
                            _delay_ms(2000);
                            uart_puts("ok"
                            return 0;
                            while(1){
                            _delay_ms(2000);
                            uart_puts(str);
                            _delay_ms(2000);
                            uart_puts("ok"

                            }
                            }


                            ولی اصلا کار نمی کنه :(
                            اصلاً هیپر ترمینال نه چیزی میاد نه چیزی میشه نوشت :-((
                            چند تا کتابخونه دیگه هم امتحان کردم ، ولی کار نیم کنند
                            از AVRSTUDIO5 استفاده می کنم

                            دیدگاه


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

                              سلام
                              دوستان من تویه یه عملیات به ظاهر ساده ولی یکم پیچ دار گیر کردم اگه میشه راهنمایی کنید
                              a=2460
                              a=*1389
                              حاصل مقدار صحیحی نیست . با انواع متغیر چک کردم و فقط زمانی که از نوع float استفاده کردم درست شد و در بقیه موارد جواب اشتباه بود .حالا من نمی خوام از float استفاده کنم باید چیکار کنم؟
                              از avrstudio هم استفاده می کنم

                              دیدگاه


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

                                مشکل حل شد :mrgreen:
                                unisgned long a;
                                sprintf(str,"%lu",a)q
                                نکته در lu بود و بی توجهی من!

                                دیدگاه

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