Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.
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
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.
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.
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
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.
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.
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.
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.
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.
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.
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
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.
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.
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.
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.
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??
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.
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.
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
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.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.