-
-
Save anonymous/3e085bd2d639f137d1a3 to your computer and use it in GitHub Desktop.
/* | |
* The AT93C46D eeprom can used by an arduino using SPI with modified settings. | |
* In this code I assume that pin 6 (ORG) is connected to GND so the 128x8 organization is selected. | |
* Slave Select needs to be pulled high when using the eeprom where in SPI you normaly pull low to select a chip. | |
* | |
* Before doing an action (reading/writing/..) you need to send a start bit (1), afterwards the opcode for | |
* the action you want to perform (2 bits) and then any other required data. This information can be found in the | |
* datasheet (http://www.atmel.com/images/atmel-5193-seeprom-at93c46d-datasheet.pdf) on page 6. | |
* | |
* As an example when reading a byte you first send a start bit (1) and the opcode (10) followed by the | |
* address (7 bits) afterwards you can retrieve the data (which is always preceded by a 0). | |
* | |
*/ | |
#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("Filling AT93C46D"); | |
Serial.println("Send EWEN opcode"); | |
digitalWrite(SS,HIGH); | |
SPI.transfer(0b1001); | |
SPI.transfer(0b10000000); | |
digitalWrite(SS,LOW); | |
delay(100); | |
for (int address = 0; address < 128; address++) { | |
digitalWrite(SS,HIGH); | |
SPI.transfer(B10); // 1 start bit, first bit of opcode | |
SPI.transfer(0b10000000 | address); // bitwise or to preced the address by 1 (second opcode bit) | |
SPI.transfer(0b10101010); // the data that is written | |
delay(10); //give the eeprom some time to complete the write request | |
digitalWrite(SS,LOW); | |
} | |
Serial.println("Done filling eeprom"); | |
delay(100); | |
Serial.println("Send EWDS opcode"); | |
digitalWrite(SS,HIGH); | |
SPI.transfer(0b1000); | |
SPI.transfer(0b00000000); | |
digitalWrite(SS,LOW); | |
delay(10); | |
} | |
void dump(){ | |
Serial.println("Dumping AT93C46D"); | |
byte data1; | |
byte data2; | |
for (int address = 0; address < 128; address++) { | |
digitalWrite(SS,HIGH); | |
SPI.transfer(0b11); // start bit and first bit of read opcode | |
SPI.transfer(address); // second bit of read opcode is 0 so the address is automatically preceded by 0 | |
data1 = SPI.transfer(0); // data1 contains a 0 and the first 7 bits at the address | |
data2 = SPI.transfer(0); // contains the 8th bit (LSB) | |
digitalWrite(SS,LOW); | |
data1 = data1 << 1; // bitwise shift to get rid of the preceding 0 | |
if (bitRead(data2, 7) == 1){ | |
bitWrite(data1, 0, 1); // change LSB if needed | |
} | |
printByte(data1); | |
} | |
} | |
void printByte(byte data){ // print with all preceding 0's | |
for (int i = 7; i >= 0 ; i--) { | |
if (bitRead(data, i) == 1) { | |
Serial.print(1); | |
} else { | |
Serial.print(0); | |
} | |
} | |
Serial.print("\n"); | |
} |
Here is my code for AT93C46D 8 bit. Just completed the testing, maybe will be useful for someone :) :
`/*****************************************************
Eeprom Settings
*****************************************************/
include "hw_config.h"
include "SPI.h"
ifndef EEPROM_AT93C46D_H
define EEPROM_AT93C46D_H
/** Example:
- @code
#include "EEPROM_AT93C46D.h"
define spi3_set_cs_1 GPIOA->BSRR = GPIO_BSRR_BS15; //set on PA15 1
define spi3_set_cs_0 GPIOA->BSRR = GPIO_BSRR_BR15; //set on PA15 0
define MISO_spi3 (GPIOB->IDR & 0x0010) //PB4(MISO)
void spi3_init_master(void)
{
//to enable SPI3 nead to disable JTAG!
//AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG;
//AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_DISABLE; //JTAG-DP Disabled and SW-DP Disabled
//QPIO Init
RCC->APB2ENR |= (RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPAEN); // GPIOA Clock ON. Alter function clock ON
RCC->APB2ENR |= (RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPBEN); // GPIOB Clock ON. Alter function clock ON
GPIOB->CRL &= ~(GPIO_CRL_CNF3 | GPIO_CRL_CNF4 | GPIO_CRL_CNF5); // Clear CNF bit 3, 4 and 5
GPIOA->CRH &= ~(GPIO_CRH_CNF15); // Clear CNF bit 15
GPIOB->CRL |= GPIO_CRL_CNF5_1 | GPIO_CRL_CNF3_1; //PB5(MOSI), PB3(SCK) - AF, Output, PP
GPIOA->CRH &= ~GPIO_CRH_CNF15; //PA15(NSS) - Output, PP
GPIOB->CRL |= GPIO_CRL_MODE5 | GPIO_CRL_MODE3; //Outputs MOSI, SCK - 50MHz
GPIOA->CRH |= GPIO_CRH_MODE15; //Outputs NSS - 50MHz
GPIOB->CRL |= GPIO_CRL_CNF4_0; //PB4(MISO) - Input floating
GPIOB->CRL &= ~GPIO_CRL_MODE4; //PB4(MISO) - Input
spi3_set_cs_0
//Init SPI3 (Master)
//8 data bits, MSB send first, spi MODE 0, program mode driwe NSS pin NSS (PA4) is alowed to use as output
RCC->APB1ENR |= RCC_APB1ENR_SPI3EN; //SPI3 Clock ON
SPI3->CR1 &= ~SPI_CR1_BR;
SPI3->CR1 |= SPI_CR1_BR_2; //Baud rate = Fpclk(36MHz)/32 (1,125MHz) from max 1.46MHz for AT93C46D and +3.3V
SPI3->CR1 &= ~SPI_CR1_CPOL; //polarity of SCK
SPI3->CR1 &= ~SPI_CR1_CPHA; //phase of SCK
SPI3->CR1 &= ~SPI_CR1_DFF; //8 data bits
SPI3->CR1 &= ~SPI_CR1_LSBFIRST; //MSB send first
SPI3->CR1 |= SPI_CR1_SSM; //program mode driwe NSS
SPI3->CR1 |= SPI_CR1_SSI; //analog as an pin NSS is high level
SPI3->CR2 |= SPI_CR2_SSOE; //pin NSS - pin driwe slave select
SPI3->CR1 |= SPI_CR1_MSTR; //is Master
SPI3->CR1 |= SPI_CR1_SPE; //enable SPI3
}
spi3_init_master();
int main()
{
while(1)
{
if(getchar_USB()== 165) //0xA5 //start of CMD
{
//AF remap and debug I/O configuration register (AFIO_MAPR)
//SWJ _CFG[2:0] = 100 -> JTAG-DP Disabled and SW-DP Disabled
//line 2604 in stm32f10x.h file
AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG;
AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_DISABLE; //JTAG-DP Disabled and SW-DP Disabled
Delay(10); //3,92s
spi3_init_master();
Delay(10); //3,92s
EWEN_instruction(); //Enable write/erase mode of eeprom
//for(i=0;i<128;i++){WRITE_eeprom(i, i);};
WRITE_eeprom(6, 9);
EWDS_instruction(); //Disable write/erase mode of eeprom
i= Read_eeprom(6);
USB_Send_Data(i);
//for(i=0;i<128;i++){USB_Send_Data(Read_eeprom(i));};
//while(1) {i= Read_eeprom(6);}; //
Delay(10); //3,92s
//AF remap and debug I/O configuration register (AFIO_MAPR)
//SWJ _CFG[2:0] = 100 -> JTAG-DP Disabled and SW-DP Disabled
//line 2604 in stm32f10x.h file
AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG;
Delay(10); //3,92s
};
}
}
- @Endcode
*/
void Delay( uint32_t Val);
void spi3_Send_to_eeprom(uint8_t send_data);
void EWEN_instruction(void);
void EWDS_instruction(void);
void WRITE_eeprom(unsigned char ADDR, unsigned char BUTE);
unsigned char Read_eeprom(unsigned char ADDR);
void Erase_eeprom(unsigned char ADDR);
void Delay( uint32_t Val) /* Time to wait in micro seconds. */ //0,098us
{
for( ; Val != 0; Val--)
{
__nop();
};
}
//Send cmd to eeprom
void spi3_Send_to_eeprom(uint8_t send_data)
{
SPI3->DR = send_data; //Pyshemo v bufer peredavacha SPI3
//while(!(SPI3->SR & SPI_SR_TXE)); //Ochikuyemo zavershennya pereda4i danykh modulem SPI3 (TXE =1 - bufer pereda4i porogniy)
while((SPI3->SR & SPI_SR_BSY)||(!(SPI3->SR & SPI_SR_TXE)));
}
//Enable write/erase mode of eeprom
void EWEN_instruction(void)
{
spi3_set_cs_1;
Delay(10); //0,00000098s //0,98uS //tcss = 250ns or more
spi3_Send_to_eeprom(0x09); //00001001
spi3_Send_to_eeprom(0x80); //1xxxxxxx
Delay(10); //0,00000098s //0,98uS //tcsh = 0 or more
spi3_set_cs_0;
Delay(10); //0,00000098s //0,98uS //tcs = 250ns...1000ns or more
}
//Disable write/erase mode of eeprom
void EWDS_instruction(void)
{
spi3_set_cs_1;
Delay(10); //0,00000098s //0,98uS //tcss = 250ns or more
spi3_Send_to_eeprom(0x08); //00001000
spi3_Send_to_eeprom(0x00); //0xxxxxxx
Delay(10); //0,00000098s //0,98uS //tcsh = 0 or more
spi3_set_cs_0;
Delay(10); //0,00000098s //0,98uS //tcs = 250ns...1000ns or more
}
//Read datas from eeprom
unsigned char Read_eeprom(unsigned char ADDR)
{
unsigned char read_eeprom;
spi3_set_cs_1;
Delay(10); //0,00000098s //0,98uS //tcss = 250ns or more
spi3_Send_to_eeprom(0x06); //00000110
spi3_Send_to_eeprom(((ADDR<<1)&(0xfe))); //ADDR + 0 (dumm bit)
read_eeprom = SPI3->DR; //nead to read dummy bute!, dont work without that!
spi3_Send_to_eeprom(0x00); //00000000 // send just clk to receive datas
//while((SPI3->SR & SPI_SR_BSY)||(!(SPI3->SR & SPI_SR_RXNE)));
read_eeprom = SPI3->DR; //read bute
Delay(10); //0,00000098s //0,98uS //tcsh = 0 or more
spi3_set_cs_0;
Delay(10); //0,00000098s //0,98uS //tcs = 250ns...1000ns or more
return read_eeprom; //read result from data register
}
//Write datas to eeprom
void WRITE_eeprom(unsigned char ADDR, unsigned char BUTE)
{
Erase_eeprom(ADDR); //Erase eeprom
spi3_set_cs_1;
Delay(10); //0,00000098s //0,98uS //tcss = 250ns or more
spi3_Send_to_eeprom(0x02); //00000010
spi3_Send_to_eeprom((ADDR|0x80)); //1 (opcode) + ADDR
spi3_Send_to_eeprom(BUTE); // send bute to eeprom
Delay(10); //0,00000098s //0,98uS //tcsh = 0 or more
spi3_set_cs_0;
/** wait busy flag clear */
Delay(10); //0,00000098s //0,98uS //250ns < tcs < 1000ns
spi3_set_cs_1;
Delay(10); //0,00000098s //0,98uS //tsv < 250ns...1000ns
while(!MISO_spi3); //wait until end of write //0.1ms < twp < 5ms
Delay(150000); //0,0098s
spi3_set_cs_0;
Delay(10); //0,00000098s //0,98uS //tcs 250ns...1000ns or more
}
//Erase eeprom
void Erase_eeprom(unsigned char ADDR)
{
spi3_set_cs_1;
Delay(10); //0,00000098s //0,98uS //tcss = 250ns or more
spi3_Send_to_eeprom(0x03); //00000011
spi3_Send_to_eeprom((ADDR|0x80)); //1 (opcode) + ADDR
Delay(10); //0,00000098s //0,98uS //tcsh = 0 or more
spi3_set_cs_0;
/** wait busy flag clear */
Delay(10); //0,00000098s //0,98uS //250ns < tcs < 1000ns
spi3_set_cs_1;
Delay(10); //0,00000098s //0,98uS //tsv < 250ns...1000ns
while(!MISO_spi3); //wait until end of write //0.1ms < twp < 5ms
Delay(150000); //0,0098s
spi3_set_cs_0;
Delay(10); //0,00000098s //0,98uS //tcs 250ns...1000ns or more
}
endif /* EEPROM_AT93C46D_H */
`
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);