Using PE example, got communication between FRDM board and 24LC00 but can't seem to write a read accurately.
First I do a block write then block read using typical example for I2C component.
volatile bool DataReceivedFlg = FALSE;
volatile bool DataTransmittedFlg = FALSE;
uint8_t OutData[4] = {0x00U, 0x01U, 0x02U, 0x03U}; /* Initialization of output data buffer */
uint8_t InpData[16];
LDD_TError Error;
LDD_TDeviceData *MyI2CPtr;
First picture is writing of data to device, only two values the first being address zero, second data value of 1.
Second picture is writing of control word and address zero to device in prep of reading
Third picture is the read
Solved! Go to Solution.
I think I have discovered the true problem. The 24LC00 doesn't support sequential or page write. It does support sequential read. The app note I have been studying made it seem that all24LCxx devices supported some sort of page write.
This is for the 24LC00
this is the 24LC01
This is how you must write to this device:
1. Send the device address (0xA0 on the line) byte with RD/WR = 0.
WARNING: IIRC PE left shifts the device address, so instead of 0xA0 you may need to set the address as 0x50 look at the code.
2, If nacked give up or go back to 1.
3. Send the "word" address only the lower 4 bits are used.
4. Send the data.
5. Send stop.
ACKNOWLEDGE POLLING
loop on sending 1. and getting a NACK.
Hey Jim, if you look at my attached scope shots its all there. I am getting the ACKs and I believe the s.w. creates the correct START and STOP sequences. But I am definitely missing something.
Not seeing an attachment.
Jim, you must view my original message under activity vs. inbox. Viewing it in the inbox view, you don't see any attachments. That was driving me crazy when I first started using this community.
Oh, I see - well I see you write the control byte and address but I don't see a read on the scope.
The read should send the control byte (as a read) the read a byte, so you should really see 4 bytes transferred.
The last picture should show the read.
Sent from Steve Cohen's blackberry
(818)261-1033
I did not see the third trace.
I think that on the final read, you should test for an error. You should get a NACK because the eeprom should be still writing. It looks like you get an ACK, but still you do need to test for NACK after writing and attempting to read.
Just retry the read until error comes back 0 (or get the error code when the done flag is set, not sure how PE handles this). Look on page 9 of the PDF link I posted.
According to that a write can take 4ms.
Also, make Avnet get one of these: Saleae Logic. .
The third trace was on the second page of the PPT file.
Yes, I did see it.
As I said, even if this is not your problem, the code is logically incorrect. After the write you MUST check for NACK as this is what indicates the device is still writing. You then need to resend the address write. EEPROMs are relatively slow. I have "talked" to EEPROM on I2C many times and I assure this must be done.
Please read the pdf as I suggested, if you have not done so, it will make this clear.
Why do you init the I2C again?
Here is what I see as wrong - after the second write I don't see a stop. I also do not understand why the second write is acked, it should be nacked.
From the PDF:
"Since the device will not acknowledge during a write
cycle, this can be used to determine when the cycle is
complete (this feature can be used to maximize bus
throughput). Once the Stop condition for a Write
command has been issued from the master, the device
initiates the internally timed write cycle. ACK polling
can be initiated immediately. This involves the master
sending a Start condition followed by the control byte
for a Write command (R/W = 0). If the device is still
busy with the write cycle, then no ACK will be returned.
If no ACK is returned, then the Start bit and control byte
must be re-sent. If the cycle is complete, then the
device will return the ACK and the master can then
proceed with the next Read or Write command. See
Figure 7-1 for flow diagram."
Also I recommend that you not use power point to upload as some users do not have it. If needs be, paste the images together in paint, or save as a pdf.
Thanks Jim for your help. I am just not used to Kinetis yet.
I am trying the higher level component since it breaks it down more then the LDD. And in the typical example they actually provide typical usage for an eeprom. The only problem is I didn't know where to enable Cpu_Delay100US(100); which they use in between the write and then read of the eeprom.
here is my write
TransmitComplete = 0;
err = I2C2_SelectSlave(0x50);
buffer[0] = 0; //storage address
buffer[1] = 0x10; //data
err = I2C2_SendBlock(buffer, 2, &sent); //send storage address and data to the EEPROM
while(!TransmitComplete){} //wait for communication completition, this flag set in interrupt routine
err = I2C2_SendStop(); //Send STOP condition
send command 0x50, address 0, data 0x10 then send stop. Page 7 of Microchip AN974
for read I stopped the processor then trigger scope again since I didn't feel like putzing around with s.w. delay.
buffer[0] = 0;
err = I2C2_SendBlock(buffer, 1, &sent);
while(!TransmitComplete){}
err = I2C2_RecvChar(&data);
send command with WRITE, address withWRITE, then read but that doesn't follow the data sheet!!!!!
after control byte sent with WRITE, then address with WRITE, need to generate START with control again and READ, then data is read correctly.
so I need to figure out how to do this with the component methods available.
So before crashing I tried this code instead to generate a restart during the read.
But the restart in the middle of the READ process isn't a real START. The control word with WRITE and address with WRITE goes out fine. But err = I2C2_SelectSlave(0x51); creates a mess. Its not a valid start. I saw a message saying using the freq divider for the i2c clock can cause problems during a restart. Maybe there is an errata of some sort.
Send I2C2_SelectSlave(0x51); is way wrong. If you look at the code, it shifts it left then sets the R/W bit (if it is a read).
When you set 0x50, it actually goes out as 0xA0. Not sure where the idea to left shift the set slave address comes from but PE is not the only one to do it.
Here is the article on the silicon error, don't know if it applies to your case:
KL25Z and I2C: Missing Repeated Start Condition | MCU on Eclipse
OMFG, I think the bug is exactly what I have been chasing. I had to remind my old brain about I2C which took a few days, but last night it was obvious that I am experiencing the same disease.
Laughing out loud, here is my current settings
Yeah I see now how 0x51 couldn't work. Got to find which PE command does a start condition + READ.
} | |
DeviceDataPrv->SlaveAddr = (uint8_t)((uint8_t)Addr << 0x01U); /* Set slave address */ | |
DeviceDataPrv->SerFlag &= (uint8_t)~(GENERAL_CALL | ADDR_10); /* Clear the general call flag and 10-bit address mode flag */ | |
DeviceDataPrv->SerFlag |= ADDR_7; /* Set 7-bit address mode flag */ |
You should look at the PE code, I am pretty sure all that should be done there.
Also, now that you have fixed the repeated start condition, go back to what you had.
Unless I am cheating, I think it works now. I just informed my two customers who are about to do the same thing what the work around it. Thanks Jim. Now need to see what PE provides for timer delays for Kinetis like 100usec delays.
I'd make a better test. I would write address in address (e.g.. 1=1 2=2 etc) for all 16 locations, read it back then test it.
I still think you should test for NACK instead of the delay,otherwise it may only work under some conditions.
Agreed, I will test a few bytes, then look for the NACK to make sure I am not on the hairy edge. Thanks again for the link, I was about to wonder if I would ever get i2c to work.
Jim, I am following exactly the typical example code: I archived the project and am attaching. With you pointing out the bug, I did make the suggested changes. Just for testing I put a ton of delays after writing the block before reading. Doesn't fix it. See below what I read back.
this shows the tail end of the write cycle, the STOP condition only occurs at the end
I am basically trying to read and write this data to the eeprom. the first byte of course is used for the address.
uint8_t OutData[5] = {0x00U, 0xaaU, 0x55U, 0xa5U, 0x5aU}; | /* Initialization of output data buffer */ |
I confirmed there are no stop conditions during the block write before the end.
Basically this next capture is after the control word is send with WRITE and address zero, it shows the proper START with read by following your suggestion about the clock path choice
this shows the tail end of the write block showing the data did go out correctly
And this shows the tail end of the block read. I do see two spikes but they are not within the clocks.
Some other advise - always cycle power between test runs. If you stop the debugger while you were reading data back you can leave the device is a bad state, when it is driving SDA low, and is expecting clocks from the mcu, but the mcu has been reset. The mcu sees SDA low and will just error out. This is much more likely to happen in a tight test loop as you have.
And you should be testing the return codes and have a break point in I2C2_OnError.