This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Programming to external EEPROM

Hello. I need some help.
I'm trying to write, read and erase an external EEPROM (25AA040 MICROCHIP) via SPI from XC164CS board, for example, one byte at 0x00 adress of the eeprom, but i don't know how to do it.
Into the datasheet, I can see some instructions but i don't know what to do with them:
img28.imagevenue.com/img.php
Could anyone help me?
Thank you very much. :)

Parents
  • void SSC0_viRx(void) interrupt SSC0RINT {
    
      if (eeprom.bytesRx < eeprom.rxCnt) {
              eeprom.bytesRx++;
    
              if ((eeprom.cmd == READ) && (eeprom.bytesRx >= START_RX_MSG)) {
           *eeprom.rxptr++ = (S8) (SSC0_RB);
              }
            else {
            eeprom.data = (S8) (SSC0_RB);   /* */
                    my_array[j] = SSC0_RB;
                    j++;
                    if (j == NUMBER)
                    {
                            flag = 1;
                            ASC0_TBIC_IR = 1;
                    }
    
        }
    
              if (eeprom.bytesRx >= eeprom.rxCnt) {
                eeprom.busy = false;
                            CS_EEPROM = high;
              }
      }
    }
    void ASC0_viTxBuffer(void) interrupt ASC0_TBINT using RB_LEVEL14
    {
             if ((j > 0) && (flag == 1))
             {
                            j--;
                            ASC0_TBUF = my_array[j];
                            if (j == 0) flag = 0;
             }
    }
    

Reply
  • void SSC0_viRx(void) interrupt SSC0RINT {
    
      if (eeprom.bytesRx < eeprom.rxCnt) {
              eeprom.bytesRx++;
    
              if ((eeprom.cmd == READ) && (eeprom.bytesRx >= START_RX_MSG)) {
           *eeprom.rxptr++ = (S8) (SSC0_RB);
              }
            else {
            eeprom.data = (S8) (SSC0_RB);   /* */
                    my_array[j] = SSC0_RB;
                    j++;
                    if (j == NUMBER)
                    {
                            flag = 1;
                            ASC0_TBIC_IR = 1;
                    }
    
        }
    
              if (eeprom.bytesRx >= eeprom.rxCnt) {
                eeprom.busy = false;
                            CS_EEPROM = high;
              }
      }
    }
    void ASC0_viTxBuffer(void) interrupt ASC0_TBINT using RB_LEVEL14
    {
             if ((j > 0) && (flag == 1))
             {
                            j--;
                            ASC0_TBUF = my_array[j];
                            if (j == 0) flag = 0;
             }
    }
    

Children
  • Hi John,

    You have changed the behavior of the interrupt service routines as I defined them (Which is fine but I think you missed what was going on). Concerning the receive interrupt you are unloading the data stream in the wrong place. Concerning the transmit interrupt you aren't sending any more bytes which is a problem.

    Remember you still need to transmit to read.

    Have a look again to the differences...

    void SSC0_viTx(void) interrupt SSC0TINT {
    
      if (eeprom.bytesTx < eeprom.txCnt) {
        eeprom.bytesTx++;
    
        if (TxMode == WRITE) { /* write mode */
          if ((eeprom.cmd == WRITE) && (eeprom.bytesTx == START_TX_MSG)) {
            eeprom.txptr = eeprom.baseptr; /* switch pointer to data */
          }
          SSC0_TB = *eeprom.txptr++; /* write user data */
        }
        else {  /* ok READ mode */
    
          if ((eeprom.cmd == READ) && (eeprom.bytesTx >= START_TX_MSG)) {
            SSC0_TB = 0; /* when reading data just send zeros */
          }
          else {
            SSC0_TB = *eeprom.txptr++; /* send command and address */
          }
        }
      }
    }
    
    void SSC0_viRx(void) interrupt SSC0RINT {
    
      if (eeprom.bytesRx < eeprom.rxCnt) {
        eeprom.bytesRx++;
    
        if ((eeprom.cmd == READ) && (eeprom.bytesRx >= START_RX_MSG)) {
          /* data stream read here! */
          *eeprom.rxptr++ = (S8) (SSC0_RB); /* read user data */
        }
        else {
          eeprom.data = (S8) (SSC0_RB); /* used for non-user data */
        }
    
        if (eeprom.bytesRx >= eeprom.rxCnt) {
          eeprom.busy = false; /* indicate the resource is free */
          CS_EEPROM = high; /* all data sent, release /CS */
        }
      }
    }
    
    

  • Ok after I sent the last post I realized you posting the code for the ASC0 interrupt (not the SSC ts interrupt) to send the data that was read from the serial EEPROM. So my comments to the SSC0 interrupt are still valid.

    -Chris

  • Ok, I just obey you and it is the result :)

    ...
    #define  NUMBER  48
    const S8 txBuf[] = "Welcome to XC164CS Serial EEPROM reading/writing";
    ...
    void SSC0_viRx(void) interrupt SSC0RINT
    {
      if (eeprom.bytesRx < eeprom.rxCnt)
      {
              eeprom.bytesRx++;
              if ((eeprom.cmd == READ) && (eeprom.bytesRx >= START_RX_MSG))
              {
    /////////////////////////////////////////////////
                    my_array[j] = SSC0_RB;
                    j++;
                    if (j == NUMBER)
                    {
                            flag = 1;
                            ASC0_TBIC_IR = 1;
                    }
    /////////////////////////////////////////////////
                    *eeprom.rxptr++ = (S8) (SSC0_RB);  /* read user data */
              }
              else
              {
            eeprom.data = (S8) (SSC0_RB);  /* used for non-user data */
              }
              if (eeprom.bytesRx >= eeprom.rxCnt)
              {
                eeprom.busy = false; /* indicate the resource is free */
                    CS_EEPROM = high;        /* all data sent, release /CS */
              }
      }
    }
    void ASC0_viTxBuffer(void) interrupt ASC0_TBINT using RB_LEVEL14
    {
             if ((j > 0) && (flag == 1))
             {
                            j--;
                            ASC0_TBUF = my_array[j];
                            if (j == 0) flag = 0;
             }
    }
    


    Hyperterminal:
    img171.imagevenue.com/img.php

    It's succesfull :)

    Now, I would like to read SC461CX only. What parameters do I have to introduce in the readEeprom function?

  • First you need to figure out why you are reading the bytes in the reverse order (reading right to left). You want to read from the XC164CS not SC461CX.

    Now, I would like to read SC461CX only. What parameters do I have to introduce in the readEeprom function?

    Not sure what you are asking as an example was supplied...
    address -> linear address of the serial EEPROM where you want to start reading from.
    &rxBuf[0] -> pointer to the first byte to receive the data from the serial EPEROM.
    txSize -> the amount of bytes you want to read from the serial EEPROM.

    /* read back the bytes we wrote to the EEPROM */
    EepromRead(address, &rxBuf[0], (U16) txSize);
    while(EepromBusy());
    

    Since the EepromRead routine is served with interrupts and can also be in the background. If you need the data immedatly then you need to wait for the EEPROM to be free (not busy).

  • 1-.The reverse order doesn't matter. It has easy solution. Just look at ASC0 interrupt. The last byte read from EEPROM is going to be the first one to be stored in my_array[j].

    2-.
    img206.imagevenue.com/img.php

    I tried programming whit this code but it do

      /* read back the bytes we wrote to the EEPROM */
      EepromRead(11, &rxBuf[11], (U16) 7);
      while(EepromBusy());
    


    img230.imagevenue.com/img.php

    What might be the problem?

  • Basically the enum represents 16-bits on the XC166 so need to adjust for this in the eeprom struct.

  • Then, shall I only have to adjust the EEPROM struct? I will try.
    By the way, we have already bought the Keil uLink2 JTAG Debugger for training my project and future developments :)

  • You would need to change the values in the enum EepromCommandType and also modify the start address of the variable eeprom.txptr in the function EepromStartTx.

  • 1-.
    Aren't the values of EepromCommandType enum constants?

    2-.

    ...
    eeprom.txptr   = (S8 *)(&eeprom);  /* reset pointer to first element */
    ...
    


    This type of instruction is new for me and I dont know it very well. I know that the pointer is reseted to fist element but could you explain me a bit? How to change the value of eeprom.txptr
    Thank you

  • John,
    First allow me to recommend that you refer to a C text book to extend your understanding of pointers. I don't know what kind of application your are writing, but do remember that making a mistake with pointers is likely to kill your controller, and could risk lives in the process!
    as to your question:

    eeprom.txptr   = (S8 *)(&eeprom);
    

    'eeprom' is a data structure that contains a member pointer to a 8 bit data type (that is 'txptr'. we can assume it is a unsigned char). that member is pointed to the beginning of 'eeprom'. that means that dereference of 'txptr' will be an unsigned char, or the first byte of the 'eeprom' structure, where I guess some text is stored (see the structure layout). note that incrementing the value of txptr by 1 will point it to the next unsigned char of the structure.

    &eeprom
    

    returns the address of 'eeprom', and that address is then casted to a unsigned char pointer so that the assignment will not cause the compiler to complain.

  • Ok Tamir,
    I understand your text. I have a new question.
    If I have to increase the pointer "x" times, is necessary to intriduce a new parameter in the function? For example:

    _inline void EepromStartTx(U16  MY_ADRESS) {
            CS_EEPROM      = low;
            eeprom.bytesTx = 1;                                     /* decrement the transmit count by one */
            eeprom.bytesRx = 0;
            eeprom.txptr   = (S8 *)(&eeprom);                   /* reset pointer to first element */
            eeprom.txptr   =  eeprom.txptr + MY_ADRESS;     /* put the pointer in my first element */
            SSC0_TB        = *eeprom.txptr++;                       /* write the first byte to the SSC0 tx buffer */
    }
    

  • eeprom.txptr   = (S8 *)(&eeprom);                   /* reset pointer to first element */
    eeprom.txptr   =  eeprom.txptr + MY_ADRESS;     /* put the pointer in my first element */
    

    can be compacted to

    eeprom.txptr = (S8 *)(&eeprom) + MY_ADRESS ;
    

    I would expect a function prototype like this:

    void EepromStartTx(U16  MY_ADRESS, unsigned  char *ap_buffer, unsigned int a_buffer_length)
    

    note that I removed the inline directive as it might probably be required to insert a loop into your function.

  • Its imposible. If I modify anything in EepromStartTxthe EEPROM only returns zeros. Any suggestion?? I just need to know this :(

  • how then do you expect to solve your problem is you cannot change anything? there is a logical empirical explanation as to why it does not work anymore. why don't you post a revision that does not work.

  • The code is too long to post here. Take the proyect at this adress:
    rapidshare.com/.../eeprom.rar.html