اطلاعیه

Collapse
No announcement yet.

twi + write

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

    twi + write

    سلام به همگی، یال نو همه مبارک و برای همه در سال 1390 سالی پربار و علمی آرزو میکنم.

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


    #define SL_ADDR 0xA0



    void TWI_MasterInit(uint8_t baudRateRegisterSetting)
    {

    TWIC_MASTER_CTRLA = TWI_MASTER_RIEN_bm |
    TWI_MASTER_WIEN_bm |
    TWI_MASTER_ENABLE_bm;
    TWIC_MASTER_BAUD = baudRateRegisterSetting;
    TWIC_MASTER_STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;
    }


    TWIC.MASTER.ADDR = SL_ADDR & ~0x01;
    while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm) || (TWIC.MASTER.STATUS & TWI_SLAVE_RXACK_bm));
    TWIC.MASTER.DATA = 0x00;
    while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm) || (TWIC.MASTER.STATUS & TWI_SLAVE_RXACK_bm));
    TWIC_MASTER_CTRLC = TWI_MASTER_CMD_RECVTRANS_gc;
    TWIC.MASTER.DATA = 0x46;
    while ((TWIC.MASTER.STATUS & TWI_SLAVE_RXACK_bm));
    TWIC.MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;

    با تشکر
    بهادر
    {امضاء خلاف قوانین}

    #2
    پاسخ : twi + write

    سلام.با نقل قول از طرف استاد کی نژاد:
    EEPROM

    EEPROM در XMEGA در دو وضعیت I/O mapped و Memory mapped عمل می کند. در روش اول این فضا برای خود دارای آدرس مستقلی است و خواندن و نوشتن آن تنها از طریق NVM Controller میسر است. در روش دوم این نوع حافظه از آدرس 0x1000 تعریف می شود و برای خواندن آن مانند سایر نقاط SRAM عمل می شود، اما نوشتن به آن همچنان مستلزم کار با NVM Controller و البته به شیوه ای غیر از وضعیت اول است. کار با EEPROM مستلزم رعایت نکات زیادی است و از این نظر از AVR های معمولی پیچیده تر است. نوشتن به EEPROM اصولا از طریق یک بافر انجام می شود و ابتدا باید نقاط مورد نظر در این بافر پر شود و بعد یک page بصورت همزمان نوشته شود. نکته مهم این است که نقاطی از page مذکور می توانند نوشته یا پاک شوند که یکبار در بافر مذکور تغییر کرده باشند و سایر نقاط در همان page بدون تغییر باقی می مانند. طول page برای شماره های مختلف می تواند متفاوت باشد.
    عملیات پاک کردن هر نقطه منجر به پر شدن 0xff در آن می شود و با نوشتن می توان تنها یک ها را به صفر تبدیل کرد و صفر را نمی توان با نوشتن به یک تبدیل کرد. دو نوع نوشتن در این خانواده پیش بینی شده که در نوع اول نقاط حافظه همزمان پاک و مجددا نوشته می شود و در نوع دوم با فرض اینکه حافظه قبلا پاک شده، فقط عملیات نوشتن انجام می شود.از آنجایی که روش دوم به اندازه نصف روش اول زمان می برد، یک مزیت آن صرفه جویی در زمان لازم برای نوشتن است. به این ترتیب که یکبار عملیات پاک کردن صفحه بصورت همزمان انجام می شود و در حین اجرای برنامه، در هر لحظه که لازم باشد فقط عملیات نوشتن انجام می شود.در مورد نوشتن مکرر در یک آدرس از بافر، دو مطلب متناقض در متون Atmel آورده شده است. در یکجا ذکر شده که این عمل منجر به از بین رفتن اطلاعات صفحه می شود و در متن دیگری ذکر شده که بین مقدار فعلی و مقدار قبلی یک عملیات And انجام می شود. همین مطلب در سایت AVRFreaks مطرح شد و کسی اطلاعاتی در مورد آن نداشت. البته در عمل نباید چنین کاری انجام شود اما اگر لازم باشد با انجام آزمایشی می توان به صحت هریک از دو وجه مطرح شده، پی برد.
    از جمله موارد مهم درباره EEPROM این است که در برخی شماره های XMEGA، نوشتن در آن منجر به مختل شدن روند برنامه می شود. شرکت Atmel برای حل این مشکل پیشنهادی را ارائه کرده به این ترتیب که بعد از نوشتن اطلاعات و در کمتر از 2.5 میکروثانیه، میکروکنترلر در وضعیت Idle قرار بگیرد و برنامه به گونه ای نوشته شود که با فعال شدن وقفه EEPROM Ready، میکروکنترلر از این وضعیت خارج شود. برای اجرای این مسئله یک Application note و کد نمونه آن در سال 2010 منتشر شده که در سایت Atmel موجود است. قبل از آن هم نمونه کدهای کاملتری برای خواندن و نوشتن در دسترس بود که برای این شماره های به خصوص قابل استفاده نیست. کاری که بصورت عملی انجام شد، این بود که کدهای کاملتر قبلی با راه کارهای ارائه شده توسط Atmel تغییر داده شد و مشاهده شد که مشکل مذکور برطرف گردیده است. در نرم افزار IAR هم می توان با تعریف متغیر بصورت eeprom__ به محتویات این ناحیه دسترسی پیدا کرد و فقط باید بررسی شود که در آخرین نسخه این نرم افزار آیا اشکال ذکر شده لحاظ شده است یا خیر. تا نسخه 5.20 که این اشکال وجود دارد و نمی توان از نوع eeprom__ برای تمام شماره های XMEGA استفاده کرد.
    همیشه در حال یادگیری.سعی می کنم موانع سر راهم را بردارم.

    دیدگاه


      #3
      پاسخ : twi + write

      به نظر می رسد انواع سریال EEPROM با شماره های 24Cxx مورد نظر شماست. آیا پایه WP در این شماره ها را به درستی وصل کرده اید؟ همچنین اگر از کتابخانه های Atmel برای کار با این سری استفاده می کنید، بجای 0XA0 باید 0X50 را به عنوان آدرس آن ذکر کنید تا پاسخ دهد. ضمنا کدی که قرار داده اید بسیار ناقص است و باید توضیح بیشتری را در مورد کد خود قرار دهید تا امکان پاسخ دادن به مشکل شما به شکل مناسبتری فراهم شود.
      اوژن: به معنای افکننده و شکست دهنده است
      دانایی، توانایی است-Knowledge is POWER
      برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
      وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
      قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
      اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
      ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

      دیدگاه


        #4
        پاسخ : twi + write

        با تشکر از پاسخ گویی شما،

        من اصلا پایه WP را به جایی وصل نکردم،

        AT24C02

        این کد توسط WINAVR کامپیل می شود:



        #include <avr/io.h>
        #include <avr/interrupt.h>
        #include <util/delay.h>
        #include <stdio.h>
        #include "printf.h"



        /*! Baud register setting calculation. Formula described in datasheet. */
        #define TWI_BAUD(F_SYS, F_TWI) ((F_SYS / (2 * F_TWI)) - 5)

        /*! CPU speed 2MHz, BAUDRATE 100kHz and Baudrate Register Settings */
        #define CPU_SPEED 2000000
        #define BAUDRATE 100000
        #define TWI_BAUDSETTING TWI_BAUD(CPU_SPEED, BAUDRATE)


        /*! Buffer size defines */
        #define TWIM_WRITE_BUFFER_SIZE 8
        #define TWIM_READ_BUFFER_SIZE 8

        /*! Transaction status defines. */
        #define TWIM_STATUS_READY 0
        #define TWIM_STATUS_BUSY 1

        #define SL_ADDR 0xA0



        void TWI_MasterInit(uint8_t baudRateRegisterSetting)
        {

        TWIC_MASTER_CTRLA = TWI_MASTER_RIEN_bm |
        TWI_MASTER_WIEN_bm |
        TWI_MASTER_ENABLE_bm;
        TWIC_MASTER_BAUD = baudRateRegisterSetting;
        TWIC_MASTER_STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;
        }

        short TWI_GetData(unsigned char twi_data) {
        short data=0;

        TWIC.MASTER.ADDR = SL_ADDR & ~0x01;
        while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm) || (TWIC.MASTER.STATUS & TWI_SLAVE_RXACK_bm));
        TWIC.MASTER.DATA = twi_data;
        while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm) || (TWIC.MASTER.STATUS & TWI_SLAVE_RXACK_bm));

        TWIC.MASTER.ADDR = SL_ADDR | 0x01;
        while (!(TWIC.MASTER.STATUS & TWI_MASTER_RIF_bm));
        TWIC.MASTER.STATUS |= TWI_MASTER_RIF_bm;
        TWIC.MASTER.CTRLC = TWI_MASTER_CMD_RECVTRANS_gc;
        while (!(TWIC.MASTER.STATUS & TWI_MASTER_RIF_bm));
        data = TWIC.MASTER.DATA;
        TWIC.MASTER.CTRLC = TWI_MASTER_ACKACT_bm | TWI_MASTER_CMD_STOP_gc;

        return data;
        }



        int main()
        {
        uint8_t i;

        stdout = &mystdout;
        PORTK_DIR = 0xff;
        //PORTC_DIRSET = PIN0_bm; // Set SDA pin as output
        //PORTC_DIRSET = PIN1_bm; // Set SCL pin as output
        //PORTC_OUT = 0xff;
        UARTD1_init();
        TWI_MasterInit(TWI_BAUDSETTING);


        while(1){
        TWIC.MASTER.ADDR = SL_ADDR & ~0x01;
        while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm) || (TWIC.MASTER.STATUS & TWI_SLAVE_RXACK_bm));
        TWIC.MASTER.DATA = 0x00;
        while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm) || (TWIC.MASTER.STATUS & TWI_SLAVE_RXACK_bm));
        TWIC_MASTER_CTRLC = TWI_MASTER_CMD_RECVTRANS_gc;
        TWIC.MASTER.DATA = 0x46;
        while ((TWIC.MASTER.STATUS & TWI_SLAVE_RXACK_bm));
        TWIC.MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;




        for(i=0;i<=6;i++)
        {
        printf("%c", TWI_GetData(i));
        }
        printf(" "
        _delay_ms(50);
        }

        }


        {امضاء خلاف قوانین}

        دیدگاه


          #5
          پاسخ : twi + write

          آنگونه که از کد شما مشخص است، بعد از Initializeکردن TWI ابتدا در آدرس 0X00 از eeprom عدد 0X46 را نوشته اید و سپس 6 آدرس اول را خوانده و روی پورت سریال ارسال کرده اید.جدا از نوع شرط هایی که در بخش دریافت قرار داده اید و جای بحث و تغییر دارد، عمده ترین موردی که برای عدم موفقیت در نوشتن به نظر می رسد، این بخش است:

          کد:
          TWIC.MASTER.DATA = 0x46;
          while ((TWIC.MASTER.STATUS & TWI_SLAVE_RXACK_bm));
          TWIC.MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;


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

          دیدگاه


            #6
            پاسخ : twi + write

            سلام، اقا واقعا متشکر، کارم راه افتاد. کدش مثل زیر میشه:

            کد:
             TWIC.MASTER.ADDR = SL_ADDR;
               while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm) || (TWIC.MASTER.STATUS & TWI_SLAVE_RXACK_bm));
               TWIC.MASTER.DATA = twi_addr;
               while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm) || (TWIC.MASTER.STATUS & TWI_SLAVE_RXACK_bm));
               TWIC.MASTER.DATA = twi_data;
               while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm) || (TWIC.MASTER.STATUS & TWI_SLAVE_RXACK_bm));
               TWIC.MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;
            {امضاء خلاف قوانین}

            دیدگاه

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