اطلاعیه

Collapse
No announcement yet.

شیفت 16 بیت ذر کدویژن

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

    شیفت 16 بیت ذر کدویژن

    سلام

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

    من این خط رو مینویسم ولی از بیت 8 به بعد خروجی صفر میده!
    کد:
     for(i=0;i<16;i++)
     {
      PORTA.0=(0x5555&(0x0001<<i));
      delay_ms(1);
     }

    ممنون از کمکتون

    #2
    پاسخ : شیفت 16 بیت ذر کدویژن

    سلام
    پشت پرانتزها یک int بزار ببین مشکلش حل می شود.
    کد:
    PORTA.0=int(0x5555&(0x0001<<i));

    دیدگاه


      #3
      پاسخ : شیفت 16 بیت ذر کدویژن

      متاسفانه خطا داد

      دیدگاه


        #4
        پاسخ : شیفت 16 بیت ذر کدویژن


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

        ذكات علم ياد دادنه ....

        دیدگاه


          #5
          پاسخ : شیفت 16 بیت ذر کدویژن

          نوشته اصلی توسط majid.4206
          سلام
          این int که میزاریم واسه چیه بعضی جاها دیدم این کارو میکنن
          سلام
          یعنی اون عملیاتی که در جلو پرانتز هست را به صورت 16 بیتی انجام دهد و نتیجه را به صورت 16 بیتی برگرداند.

          دیدگاه


            #6
            پاسخ : شیفت 16 بیت ذر کدویژن

            این int فقط در ++C مصداق داره ودر C بایستی بصورت (int) استفاده اش کرد. و معنیش هم اینه که: از اینجا به بعد عبارت رو به عنوان یک int در نظر بگیر. مثلا اگر بخواییم مقدار اعشاری f رو در مقدار صحیح i بذاریم؛ صرف نوشتن دستور:


            i = f;


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

            باید این کد بصورت زیر نوشته بشه:

            i = (int)f;


            وگرنه کامپایلر در هر دو صورت مقدار صحیح f رو داخل i میریزه.

            متاسفانه این باگ کد ویژن هست. برای چک کردن اینکه حاصل عبارت صفر هست یا نه از تابع داخلی __BSTB1 استفاده میکنه که علی رغم صدا کردن این تابع بطور 16 بیتی؛ در تابع فقط با بایت پایینی کار میکنه. تنها صورتی که تونستم مجبورش کنم کد درست تولید کنه این بود:

            PORTA.0 = ((0x5555U & (0x0001U << i))!=0) ? 1 : 0;

            دیدگاه


              #7
              پاسخ : شیفت 16 بیت ذر کدویژن

              برنامه زیر رو من الان تست کردم درست جواب می دهد.
              شما شیفت به چپ می دادید و بعد با آن مقدار and می کردید و نتیجه را درون یک پین می ریختید آنگاه از آن 16 بیت باید بیت صفرام داخل آن پین قرار گیرد به خاطر همین آن نتیجه که نیاز دارید را ملاحظه نمی کردید. در این جا مقدار 0x5555 را یک شیفت به راست می دهیم نتیجه 16 بیتی می شود بعد با یک and می کنیم که نتیجه بشود یک بیت آنگاه آنرا در پین خروجی قرار می دهیم.
              کد:
              for(i=0;i<16;i++)
               {
                PORTA.0=(0x5555>>i)&0x1;
                delay_ms(100);
               }

              دیدگاه


                #8
                پاسخ : شیفت 16 بیت ذر کدویژن

                جناب آقا حامد گل.
                مشکل این نیست که چه کدی باید نوشته بشه که بشه ازش جواب گرفت. مسئله مهم تر اینجا این هست که چرا اون کد بالایی با این که درست هست جواب نمیده. و اون کد اولی با اینکه درسته کار نمیکنه. این مشکل کد ویژنه.

                فایل lst تولید شده از کامپایل این کد ها رو در کد ویژن یک نگاهی بکنین. خودتون براحتی متوجه میشین.

                دیدگاه


                  #9
                  پاسخ : شیفت 16 بیت ذر کدویژن

                  سلام

                  ممنون از آقا حامد و آقا رضای گل

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

                  برای مثال برنامه ی زیر رو ببینید

                  کد:
                      for(cunter1=0;cunter1<8;cunter1++)
                      {
                        temp=cunter1*8;
                        t0=(data_a[temp] & (0x01<<shiffter));
                        t1=(data_a[temp+1] & (0x01<<shiffter));
                        t2=(data_a[temp+2] & (0x01<<shiffter));
                        t3=(data_a[temp+3] & (0x01<<shiffter));
                        t4=(data_a[temp+4] & (0x01<<shiffter));
                        t5=(data_a[temp+5] & (0x01<<shiffter));
                        t6=(data_a[temp+6] & (0x01<<shiffter));
                        t7=(data_a[temp+7] & (0x01<<shiffter));
                        lach_data[cunter1]=t0 * 1 + t1 * 2 + t2 * 4 + t3 * 8 + t4 * 16 + t5 * 32 + t6 * 64 + t7 * 128;
                      }


                  این برنامه بیتی که shiffter به اون اشاره میکنه رو داخل متغیرهای t0~7 میریزه...

                  الان این که نوشتم آرایه اش 8 بیتیه...

                  ولی میخوام 16 بیتی یا حتی 32 بیتی بشه که داخل برنامه نویسی راحت تر باشم :redface:

                  کد:
                  PORTA.0 = ((0x5555U & (0x0001U << i))!=0) ? 1 : 0;

                  این کد درست کار داد :applause:

                  ولی میتونم بپرسم این قسمت چه کاری انجام میده؟
                  کد:
                  ? 1 : 0
                  ممنون از لطف شما :nerd:

                  دیدگاه


                    #10
                    پاسخ : شیفت 16 بیت ذر کدویژن

                    سلام دادا.
                    ولی میتونم بپرسم این قسمت چه کاری انجام میده؟
                    ? 1 : 0
                    با اجازه اساتید خودم آقا رضا و آقا حامد

                    برای اینکه در بیان دچار سوء تفاهم نشیم بنده عین جملات کتاب آقای جعفرنژاد رو نقل میکنم:

                    عملگر "؟" عبارتی را ارزیابی کرده، بر اساس ارزش آن عبارت (درستی یا نادرستی)، نتیجه عبارت دیگر را در متغیری قرار میدهد:
                    متغیر = <عبارت1> ؟ <عبارت2> : <عبارت3>

                    اگر <عبارت 1> داری ارزش درستی باشد، مقدار ازریابی شده <عبارت 2> در متغیر قرار میگیرد وگرنه مقدار ارزیابی شده <عبارت 3> در متغیر قرار خواهد گرفت.
                    مثال:

                    کد:
                    int x,y;
                    x=5;
                    y=x>5 ? x*2 : x*5;
                    در این دستورات داریم:
                    <عبارت 1>: x>5
                    <عبارت 2>: x*2
                    <عبارت 3>: x*5

                    <عبارت 1> دارای ارزش نادرستی است، زیرا x از 5 بزرگتر نیست. بنابراین مقدار <عبارت 3> که برابر با 25=5*5 است، در متغیر Y قرار دارد.
                    تشکر لازم نیست!

                    دیدگاه


                      #11
                      پاسخ : شیفت 16 بیت ذر کدویژن

                      عملیاتی که در پست اول تاپیک انجام شده، از اساس دارای مشکل است. به این ترتیب که رجیستر پورت به دلیل ماهیت 8 بیتی که دارد، حتی با فرض درست انجام شدن عملیات شیفت و AND هم برای مقادیر بزرگتر از 8 بیت به درستی مقدار نمی پذیرد. اما اگر بجای رجیستر پورت یک متغیر 16 بیتی را با مقدار مورد نظر مساوی قرار دهید و بوسیله U ( و یا (unsigned int) ) هم 16 بیتی بودن و بدون علامت بودن اعداد را به کامپایلر یادآور شوید، در این صورت خواهید دید که برنامه به درستی کار می کند و اشکال از مساوی قرار دادن PORTA.0 است و نه عملیات شیفت و AND انجام شده:

                      کد:
                      unsigned int x;
                      for(i=0;i<16;i++)
                      {
                       x=0x5555U&(0x0001U<<i);
                       delay_ms(1);
                      {


                      در کاربرد مورد نظر در پست اول تاپیک هم هر یک از دو روشی که جناب آقازاده یا حامد AT91 فرمودند، جوابگو است. در روش دوم که مبتنی بر شیفت به راست است، اطلاعات مفید در محدوده همان 8 بیت پائین قرار می گیرد و بنابراین برای اعمال به PORTA قابل استفاده خواهد بود.
                      اوژن: به معنای افکننده و شکست دهنده است
                      دانایی، توانایی است-Knowledge is POWER
                      برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
                      وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
                      قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
                      اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
                      ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

                      دیدگاه


                        #12
                        پاسخ : شیفت 16 بیت ذر کدویژن

                        نوشته اصلی توسط طراح
                        عملیاتی که در پست اول تاپیک انجام شده، از اساس دارای مشکل است. به این ترتیب که رجیستر پورت به دلیل ماهیت 8 بیتی که دارد، حتی با فرض درست انجام شدن عملیات شیفت و AND هم برای مقادیر بزرگتر از 8 بیت به درستی مقدار نمی پذیرد. اما اگر بجای رجیستر پورت یک متغیر 16 بیتی را با مقدار مورد نظر مساوی قرار دهید و بوسیله U ( و یا (unsigned int) ) هم 16 بیتی بودن و بدون علامت بودن اعداد را به کامپایلر یادآور شوید، در این صورت خواهید دید که برنامه به درستی کار می کند و اشکال از مساوی قرار دادن PORTA.0 است و نه عملیات شیفت و AND انجام شده:
                        سلام

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

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

                        ولی در هر صورت خروجی تابع دومی که نوشته شده ، همون متغییر data_latch هست و اون هم 8 بیتی هست و 8بیتی هم میگیره...

                        خروجی تابع اول هم بیت هست و PORTA.0 هم یک بیت هست...

                        پس فکر نکنم مشکلی داشته باشه...چون این قسمت کد چند ماهی هست که درست کار میکنه :agree:

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

                        موفق باشید

                        دیدگاه


                          #13
                          پاسخ : شیفت 16 بیت ذر کدویژن

                          در مورد برنامه تابلو روان، اگر سرعت کد برای شما مهم است می توانید بجای اینکه بعد از عملیات شیفت و AND به 8 عدد برسید که دارای مقادیر صفر یا یک هستند و مجددا آنها را بسته به مرتبه خود شیفت دهید و با هم جمع کنید، به یکباره در همان مرحله شیفت به گونه ای عمل کنید که یک شیفت متغیر انجام شود تا هر عضو آرایه به عددی منجر شود که متناظر بیت مورد نظر در نتیجه نهایی باشد. این 8 عدد به راحتی قابل OR کردن خواهند بود و در تابلو روان که در برخی موارد بحث سرعت مشکل ساز می شود، این تفاوت روش ممکن است تعیین کننده باشد. کد زیر نمونه ای از چنین عملیاتی است که شاید نیاز به اصلاحاتی داشته باشد:

                          کد:
                          for(counter1=0;counter1<8;counter1++)
                          {
                           for (i=0;i<8;i++)
                           {
                           if (shifter > i)
                            latch_data[counter1]|=((data_a[i+8*counter1] >> (shifter - i))&(0x0001U<<i));
                           else
                            latch_data[counter1]|=((data_a[i+8*counter1] << (i - shifter))&(0x0001U<<i));
                           }
                          }
                          اوژن: به معنای افکننده و شکست دهنده است
                          دانایی، توانایی است-Knowledge is POWER
                          برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
                          وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
                          قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
                          اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
                          ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

                          دیدگاه


                            #14
                            پاسخ : شیفت 16 بیت ذر کدویژن

                            با عرض تبریک سال نو خدمت سروران.
                            عملیاتی که در پست اول تاپیک انجام شده، از اساس دارای مشکل است.
                            متاسفانه این مشکل بیشتر به وجود چیزی مانند کد ویژن برمیگرده که خیلی از قواعد کاری رو برای به اصطلاح راحتی برنامه نویس بهم ریخته. اگر قراره علی آباد هم شهری باشه که تکلیف بقیه دهات و شهر ها نا معلومه. منظورم اینه که وقتی عبارتی مثل PORTA.0 در این زبان C استفاده میشه قاعدتا بایستی در نظر گرفت که سیستم مقدار عبارت قید شده رو با استفاده از یک cast ضمنی به مقدار بیتی تبدیل میکند. و قاعدتا این مقدار بیتی بایستی از صفر بودن یا نبودن مقدار محاسبه شده نهایی نشات بگیرد. انصافا بنظر میرسد که کد ویژن هم با همین دید جلو میرود ولی وقتی نتیجه محاسبه را در جفت رجیستر 31 و 30 برای تابع داخلی فوق الذکر پاس میکند میبینیم که در تابع فوق فقط مقدار r30 چک میشود. که این باگ کامپایلر است.
                            ضمنا در عبارت اول رجیستر پورت مد نظر نیست و فقط یک بیت از آن مد نظر است. بنا براین نبایستی طبق روالهای موجود حاصل سمت راست عبارت به بایت تبدیل شود. مضاف بر اینکه حاصل سمت راست عبارت دارای مقدار 16 بیتی بوده و بفرم 16 بیتی محاسبه میشود.


                            کد:
                            000082 e0a1   	LDI R26,LOW(1)		1 << i
                            000083 e0b0   	LDI R27,HIGH(1)
                            000084 940e 0091 	CALL __LSLW12
                            000086 75e5   	ANDI R30,LOW(0x5555)	& 0x5555
                            000087 75f5   	ANDI R31,HIGH(0x5555)
                            000088 940e 009a 	CALL __BSTB1		-> bit <<<P1
                            00008a b3eb   	IN  R30,0x1B
                            00008b f9e0   	BLD R30,0
                            00008c bbeb   	OUT 0x1B,R30		PORTA.0
                            
                                 __BSTB1:
                            00009a 94e8   	CLT
                            00009b 2400   	CLR R0
                            00009c 11e0   	CPSE R30,R0		<<<< P2
                            00009d 9468   	SET
                            00009e 9508   	RET
                            
                            P1:	value evaluated in R31:R30
                            P2:	Only R30 is tested.

                            دیدگاه


                              #15
                              پاسخ : شیفت 16 بیت ذر کدویژن


                              باید این کد بصورت زیر نوشته بشه:
                              i = (int)f;

                              وگرنه کامپایلر در هر دو صورت مقدار صحیح f رو داخل i میریزه.
                              اقا رضا اگه در هر دو صورت مقدار صحیح ریخته میشه تو i پس
                              چرا از این دستور استفاده میشه؟
                              i = (int)f;
                              ذكات علم ياد دادنه ....

                              دیدگاه

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