We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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. :)
I tested it with ULINK and Lauterbach. Everything works as expected.
What hardware are you using? The hardware I used was the Starter kit which uses SSC0 and P3.6 for the chip select.
-Chris
I don't have any type of hardware to test the programs :(. I can only use the ASC0 and hyperterminal to show the bytes I read/write from EEPROM and for every tests. In my project we don't have much money to buy debuggers, such as uLink jejeje.
Hello Chris, Despite I have tried so much, I am not able to read what I have written in the EEPROM. I am trying to store everything I receive from EEPROM in an array located in reception interruption. I only get as answer [00][FF]. What could it be the problem? Thank you.
John, Despite our desire to help you, we are not mind readers. Please post the core of your code - just the essentials so that it can be analyzed.
Tamir, if you want, I will send you the keil proyect to your mail right?
John, I don't have your hardware so sending me your code is not going to help a lot. Besides I am at work and I don't time too much time...Just post a couple of code snippets: your peripheral configuration, ISRs, and buffers that interact with incoming data. Are you sure your external bus interface is correctly configured? Did you try to minimize the scope of the program to the absolute minimum, so that you can rule out external interferences? That can you and us, too.
Hello John,
I don't see the same issue so something must be different in your implementation. What pins are connected from the serial EERPOM to what pins of the XC164CS. What about the WR and HOLD pins (they are tied high in my configuration)?
The read and write routines are completely interrupt driven and are the same implementation only the instruction (sent to the serial EEPROM) is changed.
You would need to isolate your problem/issue and properly communicate the defect for someone else to understand what the cause might be and provide suggestions.
If you run the code using the simulator you will see that the interrupts are more than two. You would not have the correct data but the transfers should work.
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 = mi_array[j]; if (j == 0) flag = 0; } }
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; } }
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.
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.
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.