I'm trying to write to and read from an AT93C46D eeprom using an Arduino UNO but for some reason the output I'm getting is not what I expect.
The eeprom has a data structure of 128 words of 8 bits each and I'm trying to write 10000010 to each word. When reading back the data however I get 11000001. When I write 00000000 to all words I get 10000000 for all words when reading. I tested my code on 2 AT93C46D eeproms and both gave the same result.
It looks like the MSB is always 1 (when reading) for some reason.
I'm probably making a stupid mistake but I can't seem to find it, any help is greatly appreciated!
Datasheet: http://www.atmel.com/images/atmel-5193-seeprom-at93c46d-datasheet.pdf
#include<SPI.h>
#define DATAOUT 11//MOSI
#define DATAIN 12//MISO
#define SPICLOCK 13//sck
#define SS 10//ss
void setup()
{
pinMode(SS,OUTPUT);
pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK,OUTPUT);
digitalWrite(SS,LOW);
Serial.begin(9600);
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
fill();
dump();
}
void loop()
{
}
void fill()
{
Serial.println("Send EWEN opcode");
digitalWrite(SS,HIGH);
SPI.transfer(B10011); //EWEN
SPI.transfer(B0000000);
digitalWrite(SS,LOW);
delay(100);
for (int i=0; i < 128; i++) {
digitalWrite(SS,HIGH);
SPI.transfer(B101);
SPI.transfer(i);
SPI.transfer(B10000010);
delay(10);
digitalWrite(SS,LOW);
}
delay(100);
Serial.println("Send EWDS opcode");
digitalWrite(SS,HIGH);
SPI.transfer(B1000); //EWDS
SPI.transfer(B00000000);
digitalWrite(SS,LOW);
delay(10);
}
void dump(){
Serial.println("Dumping AT93C46D");
byte b;
for (int i=0; i < 128; i++) {
digitalWrite(SS,HIGH);
SPI.transfer(B110); //read opcode
SPI.transfer(i);
b = SPI.transfer(B00000000); //clock data out
digitalWrite(SS,LOW);
Serial.println(b, BIN);
}
}
1 Answer 1
After looking at the product spec again I think it might be possible to get this working. The protocol is MSB with a start bit S followed by two bit op-code, and parameters. SPI on AVR is 8-bit transfer but transfer can be byte aligned with the start bit.
READ is op-code(10) followed by 7-bit address, a dummy bit and the read value. That is in total 11+8-bits. Mapping that to 8-bit transfer would be:
spi.transfer(0b110);
spi.transfer(addr << 1);
data = spi.transfer(0);
That will give 5-bit zero, start-bit, op-code in the first transfer, and followed by 7-bit address and dummy bit (LSB) in second transfer. The third transfer is the read data.
EWEN would map to:
spi.transfer(0b1001);
spi.transfer(0b10000000);
EWEN has op-code(00), followed by 9-bits, 0b11XXXXXXX.
The WRITE operation becomes:
spi.transfer(0b10);
spi.transfer(0x80 | addr);
spi.transfer(data);
Cheers!
-
I updated my .ino file per your suggestion: gist.github.com/anonymous/5f29911c6f1c15d0660f But now I get even stranger results, by writing 0 to all bits the output is '10000000' for the first half of the words and '11111111' for the second half. What is your reasoning behind doing address & 0x7f?user3027128– user30271282016年02月25日 17:47:33 +00:00Commented Feb 25, 2016 at 17:47
-
There is much more to consider with the other commands. In any case, the READ command has to create the sequence S(1), OP(10), ADDR(7-bit). The LSB of OP is MSB of the 8-bit with address therefore addr & 0x7f (alternatively alway keep address less than 128). The was a way to explain where the LSB of OP was.Mikael Patel– Mikael Patel2016年02月25日 18:52:54 +00:00Commented Feb 25, 2016 at 18:52
-
You need to verify all other sequences and then there is a special dummy bit in READ response that needs some consideration.Mikael Patel– Mikael Patel2016年02月25日 18:53:45 +00:00Commented Feb 25, 2016 at 18:53
-
Thanks for your help! I adjusted my code one final time and added some comments: gist.github.com/anonymous/3e085bd2d639f137d1a3 It might be useful for other in the future.user3027128– user30271282016年02月26日 15:40:48 +00:00Commented Feb 26, 2016 at 15:40
-
You are welcome. I had a look. Here are some possible changes (and tests). line 88-91: Could rewrite this as "data1 = (data1 << 1) | (data2 != 0);". line 82-85: Could you test this: "SPI.transfer(0b110); SPI.transfer(address << 1); data1 = SPI.transfer(0); "Mikael Patel– Mikael Patel2016年02月26日 15:52:47 +00:00Commented Feb 26, 2016 at 15:52
B10011
? Don't you meanB10011000
?