Skip to content

Instantly share code, notes, and snippets.

/AT93C46D.ino Secret
Created Feb 26, 2016

Embed
What would you like to do?
/*
* 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");
}
@mikaelpatel

This comment has been minimized.

Copy link

commented Feb 26, 2016

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);

@YuriySta

This comment has been minimized.

Copy link

commented May 13, 2016

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      
  };

}
}

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 */

`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.