We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
When we interface flash with 8051, we send Commands to read and write. For write operation, after sending Write Command, we send data, Should there be any change in the way the data (data byte which is to be written) is sent ? For instance, we send the 8-bit word bit by bit, clock being set to 1 & 0, manually for each bit. I believe the Commands are Read and are processed by the Logic circuitry. When data is to be written, the Write cycles may take practically more time to Write in the flash, so could somebody say what is the right way to send the data,
The code is given below: quite long, but probably going through only the necessary functions would reduce time for you,
#include<reg51.h> #include<stdio.h> sbit si = P1^1; sbit SCK = P1^3; sbit SO = P1^5; sbit ce = P1^0; unsigned char Get_Byte(); // To receive 8 bit word bit by bit void Send_Byte(unsigned char b_out); // To send 8 bit word bit by bit thru SI void E_WRSR(); // Enable & write to status reg. // unsigned char Read_Status_Register(); void WREN(); // Write Enable before Write operation void Byte_Program(); // Write single byte to location void Delay(); // To wait for completion of write operation unsigned char Read_Func(); // unsigned char Read_ID(); // void Read_Cont(unsigned long addr, unsigned long no_bytes); unsigned char i, SR_byte, r_byte; void main(void){ ce = 1; // Chip Enable SCK = 0; // Clock TMOD = 0x20; TH1 = -3; // 9600 baud SCON = 0x50; TR1 = 1; TI = 1; ce = 0; Byte_Program(); ce = 1; ce = 0; Read_Func(); ce = 1; } unsigned char Get_Byte(){ // Receive dataByte from Flash through SO bit by bit unsigned char i=0, in=0, temp=0; for(i=0;i<8;i++){ in = (in << 1); temp = SO; SCK = 1; // S clock, manually set to 1 & 0 if (temp == 1){ in = in | 0x01; } SCK = 0; } return in; } void Send_Byte(unsigned char b_out){ // To Send Data Byte to Flash, bit by bit through SI for(i=0;i<8;i++){ if((b_out & 0x80) == 0x80) si = 1; else si = 0; SCK = 1; b_out = (b_out << 1); SCK = 0; } } void E_WRSR(){ //ce = 0; Send_Byte(0x50); // enable Status Reg // ce = 1; Delay(); // ce = 0; Send_Byte(0x01); // select write to status register Send_Byte(0x00); // (BPL = 0, mode 00 (bp1 & 2), NONE) // ce = 1; } void WREN(){ // ce = 0; Send_Byte(0x06); // Sending Write Enable Command // ce = 1; } unsigned char Read_Func(){ // Read single byte from Flash // ce = 0; Send_Byte(0x03); // Sending Read CMD Send_Byte(0x00); // Sending address bytes-24 bit. (0-7) Send_Byte(0x01); // Bits (8-15) Send_Byte(0x23); // Bits (16-23) Delay(); r_byte = Get_Byte(); SBUF = r_byte; P1 = r_byte; // transmit to led port1 while(TI){ } TI = 0; // ce = 1; return r_byte; } void Byte_Program(){// Write Operation (takes longer time to complete Compared to read) ce = 0; E_WRSR(); ce = 1; ce = 0; WREN(); ce = 1; // ce = 0; Send_Byte(0x02); // Byte Program CMD Send_Byte(0x00); // sending 3 address bytes (0-7) Send_Byte(0x01); // (8-15) Send_Byte(0x23); // (16-23) Send_Byte(0x29); // send byte to be programmed (data) Delay(); // ce = 1; } void Delay(){ // 14 - 20us delay, the time it takes for Write operation unsigned int j = 77; for(i=0;i<100;i++){ j = j--; } } /*unsigned char Read_Status_Register(){ ce = 0; Send_Byte(0x05); // send RDSR command SR_byte = Get_Byte(); // receive byte Delay(); P1 = SR_byte; /* SBUF = SR_byte; while(TI){ } TI = 0; // TI = 1; ce = 1; return SR_byte; } /* unsigned char Read_ID(){ ce = 0; Rd_ID = 0x00; Send_Byte(0x90); // send read ID command (90h or ABh) Send_Byte(0x00); // sending address in 3 bytes Send_Byte(0x00); Send_Byte(0x00); // send address - either 00H or 01H Rd_ID = Get_Byte(); // receive byte // SBUF = Rd_ID; // P1 = Rd_ID; // while(TI){ // } // TI = 0; ce = 1; return Rd_ID; } */
using 8051, 8052, ie AT89C52
which do you think is an apt option, will follow your method, but just to narrow down the search..
Nothing wrong with using a SPI serial flash with an 8051. We do so in some of our products. Works fine.
The biggest problem with the SPI interface is that there has never been a formal spec defining its behavior. So, sometimes you run into quirks where different devices have different interpretations of when to sample the data line relative to the clock.
Since this is a bit-banged implementation, timing isn't going to be rock solid. One place to start is with a scope on the clock and data lines. Do you have a marked difference in timing when you shift to the data portion of your message?
Note that you do not need to (and should not) issue the WRSR command on every write. The status register in these parts is implemented with the same flash technology as the rest of the chip. When you change that write enable bit, it's the same as a flash erase and write of the status register word, and the status register has a maximum number of erase cycles just like any other word in the part. (Some parts have status registers with even shorter lifetimes than the main memory section.) You can burn out the status register with repeated WRSRs, at which point the part will fail. The WREN command is sufficient to enable writing to the part. WRSR should only be used if you really need to write-protect the part for extended periods.
Nothing wrong with using a SPI serial flash with an 8051. I wholehardedly agree
HOWEVER, the serial flash in question is BIT, not BYTE addressed and, thus, not a good choice.
Erik
Note that you do not need to (and should not) issue the WRSR command on every write.
Consult the datasheet. Some explicitily recommend that you do this. I have one here that does.
The status register in these parts is implemented with the same flash technology as the rest of the chip.
In the one I have, it must be implemented as RAM, since it is automatically set to "Write disabled" when Vcc falls below the power-on reset threshold.
A few months ago, I had an FAE from Macronix explain this particular problem to me. It's not my idea; I, too, was surprised. More recently, one OEM wanted to sub a part where the status register had only a 1000-cycle lifetime (unlike the rest of the part, which was still only 10k).
If there are parts that explicitly require a WRSR before every write, then they're in direct conflict with these parts that will fail under such conditions, and we can thank the manufacturers for making it impossible to write a generic driver that allows simple part substitution by manufacturing/purchasing after the design is done. It'll be like parallel flash, with a query for two or three ad-hoc methods and a long list of individual parts with known behavior, plus the best guess at the rest.