SPI with 8051 and 93C46

Status
Not open for further replies.

vikky

Full Member level 3
Joined
Oct 18, 2007
Messages
150
Helped
4
Reputation
8
Reaction score
3
Trophy points
1,298
Activity points
2,664
8051 eeprom 93c46

can anyone help me 2 program for interfacing 93C46 with 8051 using SPI protocol.Thank you.
 

spi 93c46

u didnt mentioned which 8051 based controller u r using
you will have to search which 8051 based controller has inbuilt SPI unit.
AVR controllers ie (ATmega16 etc...) have inbuilt SPI unit so you can interface spi eeprom as far as programm is concerned you will have to set some SPI registers to enable SPI communication

If you use 8051 that doesnt have SPI unit you will have to work extra hard.
first u will have to learn SPI protocol and its timing digrams then write a program to implement SPI protocol

So it is better to use a controller with inbuilt SPI unit
 

    vikky

    Points: 2
    Helpful Answer Positive Rating
8051 93c46

Hi,
Vikky, after reading the data sheet of 93C46, please come up with a small 8051 assembler program of your own so that others may be able to help you, just try, you can do it.

Regards,
Laktronics
 

    vikky

    Points: 2
    Helpful Answer Positive Rating
93c46 8051

thanks sjerr4u and laktronics for replying.I am using 89V51rd2 which has a SPI inbuilt in it.I want 2 do a master write and master read from EEPROM and send it 2 lcd.can u guide me 2 write a program for this.
 

configuring p89v51rd2

i tried out a code to display it on the hyperterminal.but i am getting a garbage value.i will give my routine for read and write.Please guide me how to proceed.

void WR_BYTE( char EE_address, char EE_data )
{
SS=1; // Set chip select high
SPI_TX_CHAR(0x01); // start bit is bit 1,
// Note: 01 is op-code for write, since everything is right justified
// the 1 falls into the second byte in the leftmost position(bit 7).
// The EE_address must be ORed with b'1000 0000'.
EE_address |= 0x80;
SPI_TX_CHAR( EE_address );

// Address location
SPI_TX_CHAR( EE_data );
SS=0; // Data
// Must set chip select low to start
// internal programming cycle.
}



void RD_BYTE( char EE_address )
{
SS=1; // Set chip select high
SPI_TX_CHAR(0x01);

// Start bit is bit 1
EE_address=EE_address & 0xFD; // bit 7 must be 0 - can


SPI_TX_CHAR(EE_address);
// change clock polarity to 0
// The byte
// transmitted here is a don't care.
SPCR=SPCR & 0xFB; // Bring chip select low to terminate
SS=0; // the read command
SPCR=SPCR | 0x08; // Return clock polarity to 1

}
 

8051 interface 93c46

Hi,
There is more to do than what you have done. In the first place, I do not think a standard SPI can be used for this application, since the commands to be given are not byte oriented. I think you need to do bit level SPI.

To write a byte:

1. Enable chip select
2. Issue a 10 bit Write enable command (EWEN).
3. Disable chip select, Enable it again.
4. Issue 10 bit Write command including 7 bit Address.
5. Issue 8 bit data bitwise with 8 clocks.
6. Disable chip select and Enable again.
7. Wait for write delay or check readybusy bit and wait until ready
8. Disable chip select and Enable again.
9. Issue Disable Programming command (EWDS) if no more writing reqired.
9. Disable Chipselect.

To Read a byte:

1. Enable Chip select.
2. Issue 10 bit Read instruction, including address.
3. Read 8bit data one bit at a time by clocking 8 times.
4. Disable chipselect.

Notes:
1. All commands and data bits given/read with MSB first.
2. The rising edge of the clock strobes in/out all bits.
3. The data line should be pulled high.
4. ORG pin should be grounded to make 93C46 byte oriented.

Looks tough, but it can be done.

Regards,
Laktronics
 

    vikky

    Points: 2
    Helpful Answer Positive Rating
silabs spi problem wire

since i am using 89v51rd2 which has a inbuilt SPI in it i thought i can send it in byte level.moreover there is a exclusive register SPDAT for sending data.please correct me if i am wrong.
 

93c46 interfacing with 8051

Hi,
You can definitely send byte level and only byte level I suppose? But you need to send a 10 bit command including 7 bit address, using only 10 clocks, how will you do that using a byte level hardware is my question.

Regards,
Laktronics.
 

    vikky

    Points: 2
    Helpful Answer Positive Rating
do & 93c46 & dummy bit 0

i tried now between two 89v51rd2 making one as master and other as slave.i found that data is not getting inside SPDAT.i have given the code below
this is for master
#include<p89v51rd2.h>
#include<uart.h>


unsigned char d;

void SPI_TX_CHAR(unsigned char d)
{

d=SPDAT;
DELAY(10);

}

void SPI_INITMASTER()
{

SPCR=0x40;
}

void main()
{
SPI_INITMASTER();

UART_INIT(9600,0);

SPI_TX_CHAR('A');
while(1)
{
}

}
AND THIS IS FOR SLAVE
#include<p89v51rd2.h>

#include<uart.h>

#define MOSI P1_5
#define SS P1_4

unsigned char d;

void SPI_INIT_SLAVE()
{
SS=0;
SPCR=0x40;
}



void main()
{
SPI_INIT_SLAVE();

UART_INIT(9600,0);


if(SPSR==0x80)

{
TX_CHAR(SPDAT);
}
while(1)
{
}
}
when it is not getting inside SPDAT how can i expect it 2 reach the slave.i will also attach the datasheet of 89v51rd2 for your reference.
 

8051 interfacing with 3-wire serial 93c46 eeprom

i was able to write it to the master but i was not able to make the slave display it.any suggestions???
 

assembler para 93c46

Hi,
Interconnection of SPI Master and Slave unit is done as follows:

1. Interconnect the following signals of Master and slave

MOSI to MOSI
MISO to MISO and
SCK to SCK
Connect SS- of Master to Vdd and
SS- of Slave to Vss.

2. Load SPCR of Master with 52h (sck =fosc/64) and
SPCR of Slave to 42 ; sck should be same for both.

3. Load SPIDATA of Master with the byte to be sent, it triggers SPI transmit automatically. Wait for SPIF to be set in master to find out when data transmission is over. Clear SPIF and you can load the next byte.

4. On slave Look for SPIF to be set and then read the SPIDATA and clear the SPIF bit.

5. Your slave should be ready to receive the data before the master starts its transmission, or you will lose the byte.

6. You have reversed the data assignment in the TX routine, make SPIDATA=d to load SPI reg with data 'd'

You should be able to take care of all coding aspects and correctness of the language, I will not be able to help you in this regard.

Regards,
Laktronics

Added after 30 minutes:

Hi,
Also, in SPI, only master can transmit data , so if you want to loop back the data, the Master has to do a second dummy TX and read the received data, OR, you have to change the Master/Slave roles of the devices, but synchronisation can be a problem here. Clearing of SPIF in between is important. Afterall, SPI is nothing but a back to back connected two shift registers, shifting entirely controlled by the Master.

Regards,
Laktronics
 

    vikky

    Points: 2
    Helpful Answer Positive Rating
    V

    Points: 2
    Helpful Answer Positive Rating
spi in 8051

thanks for your reply.the value is getting inside the while loop of the slave but a undefined data is getting displayed.i am sending my updated code for your reference.
for master

#include<p89v51rd2.h>
#include<uart.h>
#define MOSI P1_5
unsigned char d;

void SPI_TX_CHAR(unsigned char d)
{

SPDAT=d;
while(!(SPSR & (1<<SPSR | 0x80)));


}

void SPI_INITMASTER();
{
SPCR=0x52;
}
void main()
{
SS=1;
UART_INIT(9600,0);
SPI_INITMASTER();


while(1)
{
if(P3_2==0)
SPI_TX_CHAR('A');
}

}

FOR SLAVE

#include<p89v51rd2.h>

#include<uart.h>
#include<lcd.h>
#include<delay.h>
#define MOSI P1_5
#define SS P1_4
#define MISO P1_6

unsigned char RXED;

void SPI_INIT_SLAVE()
{
SS=0;
SPCR=0x42;
}

unsigned char SPI_SlaveReceive(void)
{

while(!(SPSR & (1<<SPSR | 0x80)));

return SPDAT;
}
void main()
{
SS=0;
SPI_INIT_SLAVE();
MISO=0;

UART_INIT(9600,0);


while(1)

{
RXED=SPI_SlaveReceive();
TX_CHAR(RXED);
}

}
i have also given the circuit connection in the right manner.
 

p89v51rd2.h

good news atlast.was able 2 communicate between two devices.now back to EEPROM program...
[/quote] You can definitely send byte level and only byte level I suppose? But you need to send a 10 bit command including 7 bit address, using only 10 clocks, how will you do that using a byte level hardware is my question.

can u give me any solution 4 this problem?
 

93c46 application

Hi,
Good to know that you are able to communicate between two Micros. I feel for interfacing with EEPROM, it is better to use bit level SPI using port bits since it requires non-byte level SPI. May be you can pack bits from neighbouring bytes and include some dummy bits to make it byte level and use hardware SPI, but I think it will be clumsy to handle and the extra dummy bits might give some problem also,.....I do not know.

So, I suggest you to use bit level SPI using the same SPI bits as general purpose bits.
You can refer the SPI send/receive routine under reference:
. May be you should thank Tesion and give him 7 points for his contribution to the Forum and use the routine in your application. Here you can selectively control the number of bits to be sent and easily adapt to your application.

Please note that you need not send me points for each of my reply.

Regards,
Laktronics
 

program for interfacing 93c46

when i have a SPI inbuilt in my controller and when i have register to carry my bits which takes care of clock i thought that would be easier.now the problem is i have 9 bits to carry including my opcodes and addressing.any suggestions?i have also attached the datasheet of eeprom.tension's program...i am afraid i have to see it tomorrow.
 

93c46- 8bit 16bit

Hi,
Yah, it looks weird for me too, but I do not have better suggestion at this time. Also please note that the EEPROM command needs a high start bit followed by two bit opcode and 7 bit address, which makes it a 10 bit command in total.

Regards,
Laktronics
 

is 93c46 & 93c46a are equivalent

Another good news..now i am able to write and read from the master and display it between two microcontrollres.but the EEPROM is still not working.There is a blank data displayed.This is my updated code...any suggestions??

#include<p89v51rd2.h>
#include<delay.h>
#include<SPI.h>
#include<uart.h>

#define MOSI P1_5
#define MISO P1_6
#define SCK P1_7
#define SS P1_4

unsigned char DAT,d,data1;


void SPI_MasterInit(void)
{
/* Set MOSI and SCK and SS(-) as output , all others input */
P1 = (1<<P1_7)|(1<<P1_5)|(1<<P1_4);
/* Enable SPI, Master, set clock rate fck/128 */
SPCR = 0x52;

}
unsigned char SPI_TX_CHAR(unsigned char d)
{
unsigned char data1;
SPDAT=d;
while(!(SPSR & (1<<SPSR | 0x80)));
// Return data register
data1=SPDAT;
return data1;

}

void ERASE()
{
SS=0;
SPI_TX_CHAR(0x03);
SPI_TX_CHAR(0xFF);

SS=1;
}
unsigned char SPI_SlaveReceive(void)
{
/* Wait for reception complete */
while(!(SPSR & (1<<SPSR | 0x80)));
/* Return data register */
return SPDAT;
}
void EWEN()
{

SS=1;
// Make sure CS is high
// Start bit is bit1,
data1=SPI_TX_CHAR(0x02);
// 00 is opcode for EWEN
data1=SPI_TX_CHAR(0x60); // 0110 (6) required for
// EWEN 0's are don't cares
SS=0; // for 5 lsb address bits
// Bring chip select line low to begin
// EEPROM internal write cycle
} // MUST wait 5 ms for internal cycle to complete



void WR_BYTE( char EE_address,char EE_data)
{
SS=1; // Set chip select high
data1=SPI_TX_CHAR(0x02); // start bit is bit 1,
// Note: 01 is op-code for write, since everything is right justified
// the 1 falls into the second byte in the leftmost position(bit 7).
// The EE_address must be ORed with b'1000 0000'.

data1=SPI_TX_CHAR( EE_address );

// Address location
data1=SPI_TX_CHAR(EE_data);

// Data
SS=0; // Must set chip select low to start
// internal programming cycle.
}


unsigned char RD_BYTE( char EE_address )
{

unsigned char data1;

SS=1;
P1 = (1<<P1_6); // Set chip select high
data1=SPI_TX_CHAR(0x03); // Start bit is bit 1// bit 7 must be 0 - can

data1=SPI_TX_CHAR(EE_address);
// change clock polarity to 0
data1=SPI_TX_CHAR(0x00);
if(MISO==0)
{

data1=SPI_SlaveReceive();
// The byte
} // transmitted here is a don't care.


return data1;

}

void main()
{

SS=0;
UART_INIT(9600,0);

SPI_MasterInit();
// ERASE();
EWEN();

WR_BYTE(0xAF,'A');
DELAY(20);
while(1)
{


if(MISO==1)
{

data1=RD_BYTE(0x3F);
TX_CHAR(SPDAT);
}
}

}
 

93cxx+8051+interface

Hi

Otherwise can u please recommend any other EEPROM which i can do a easy SPI interface with 89v51rd2.Thank You.
 

93c46 assembler

Hi Vikky,
I have not really understood your program, have found out any logic to apply the hardware SPI for your application, can you explain, how you are sending the ten bit command? In the thread given by me, the program given by CMOS is almost a software equivalent of the hardware SPI. You can slightly modify it by adding a loop index variable to the function so that the calling program can specify the number of bits to be shifted out. All that you have to do is to repetitively call this function with different data bytes to issue a command frame and data to the EEPROM.Also remember that the bits are to be shifted out as MSB first. I think these EEPROMS were born before the hardware SPIs were available, so they have not designed it to be byte oriented.
Nedless to say that a software SPI will tie down the processor time compared to a harware SPI. What else you want to do in your application.

Regards,
Laktronics
 

8051 93c46

I am sending 10 bit instruction through SPDAT by 2 times.it happens like this

SPDAT=0 0 0 0 0 0 START BIT OPCODE1
SPDAT=OPCODE2 A6 A5 A4 A3 A2 A1 A0

i am able to write the data but i am not able to read it from the D0 pin.i will give my code much clearer for you to understand.

#include<p89v51rd2.h>
#include<delay.h>
#include<SPI.h>
#include<uart.h>

#define MOSI P1_5
#define MISO P1_6
#define SCK P1_7
#define SS P1_4

unsigned char DAT,d,data1;


void SPI_MasterInit(void)
{
/* Set MOSI and SCK and SS(-) as output , all others input */
P1 = (1<<P1_7)|(1<<P1_5)|(1<<P1_4);
/* Enable SPI, Master, set clock rate fck/128 */
SPCR = 0x53;

}
unsigned char SPI_TX_CHAR(unsigned char d)
{

SPDAT=d;

while(!(SPSR & (1<<SPSR | 0x80)));//wait for transfer to complete


return SPDAT;

}

void ERASE()
{
SS=0;
SS=1;
SPI_TX_CHAR(0x03);//sending startbit and first opcode
SPI_TX_CHAR(0xFF);//the second opcode and address
SS=0;
//Pulled low between Last DI bit and ack to arrive from D0 pin
SS=1;
while(!(1<<MISO));//checking for busy flag
SS=0;
}
void EWDS()
{
SS=0;
SS=1;
SPI_TX_CHAR(0x02);//sending startbit and first opcode
SPI_TX_CHAR(0x00);//the second opcode and address
SS=0;

}
unsigned char SPI_SlaveReceive(void)
{
SPI_TX_CHAR(0x00);
/* Wait for reception complete */
while(!(SPSR & (1<<SPSR | 0x80)));
/* Return data register */
return SPDAT;
}
void EWEN()
{
SS=0;
SS=1;
// Make sure CS is high
// Start bit is bit1,
SPI_TX_CHAR(0x02);//sending startbit and first opcode
// 00 is opcode for EWEN
SPI_TX_CHAR(0x60); //the second opcode and address // 0110 (6) required for
// EWEN 0's are don't cares
SS=0; // for 5 lsb address bits
DELAY(20); // Bring chip select line low to begin
// EEPROM internal write cycle
} // MUST wait 5 ms for internal cycle to complete



void WR_BYTE( char EE_address,char EE_data)
{
SS=0;
SS=1;
EWEN();
SS=0;
SS=1;
// Set chip sele//ct high
SPI_TX_CHAR(0x02); // start bit is bit 1,
// Note: 01 is op-code



SPI_TX_CHAR( EE_address );

// Address location
SPI_TX_CHAR(EE_data);

SS=0;
SS=1;
while(!(1<<MISO));polling for busy flag

while(!(SPSR & (1<<SPSR | 0x80)));waiting for transmission to complete
// Data
//SS=0;
//SS=1;
//EWDS();
SS=0;
// Must set chip select low to start
DELAY(20); // internal programming cycle.
}


unsigned char RD_BYTE( char EE_address )
{

unsigned char data1;

SS=0;
SS=1;

P1 = (1<<P1_6);setting MISO as input
// Set chip select high
SPI_TX_CHAR(0x03); startbit and opcode // Start bit is bit 1

SPI_TX_CHAR(EE_address);

// change clock polarity to 0


while(MISO!=0);//waiting for low at D0
SPCR = SPCR & 0x7F;//changing clock polarity to 0
data1=SPI_TX_CHAR(0x00);//sending dummy Tx and reading at data1
SPCR = SPCR | 0x80;//changing clock polarity to 1



SS=0;

DELAY(20);
return data1;
}

void main()
{
unsigned char data2;
SS=0;
UART_INIT(9600,0);//intialising UART

SPI_MasterInit();//Intialising master
ERASE();




while(1)
{

WR_BYTE(0x8F,'D');writing


data2=RD_BYTE(0x0F);

TX_CHAR(data2);displaying the value read in hyperterminal

}

}
my final objective is to read a data from a memory device and display it on hyperterminal.I have done this successfully between two 89v51rd2 now i want to do a interface with a memory device.IS my choice of EEPROM ok?(93C46).Thanks for helping me all along.
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…