/**___________________C-IMPLEMENTATION OF 93C46 64 x16 memory interface for the 8051____________________________| Created: March 7, 2007 | Coder: Muzammal Baig | Target Chip: AT89C52 | Crystall frequency: 12MHZ. (Above that there may be need for waits) | Function Implemented: This code implements 93C46B 1K 5.0V Microwire® Serial EEPROM interface for AT89C5x µC | // | Introduction: 93C46B is a 64 word (double byte per address) 1Kb EEPROM. There is another model which | has 128 single Bytes 1Kb EEPROM, you will need to modify this code for using that model | Implementation Detail: There are only two functions for dealing with the EEPROM | 1) "void ROM (void)" : This is the only function that actually communicates with the EEPROM | 2) "void ERASE_WRITE (void)": This function is an auxiliary function which waits for the Ready status of the| EEPROM chip after executing a WRITE or ERASE to the chip. According to the datasheet, typical | WRITE / ERASE time for the 93C46B is 2ms-6ms and the chip gives a ready / busy status on its DO pin | after ERASE, ERAL, WRITE or WRITE command is executed. By using EWEN and EWDS This function | imlements the Data protection lock which is a feature of the 93c46B chip | However ERASE_WRITE() is not needed for the EPROM functionality but it should be adapted as needed | by the user | WARNING: It is the user's responsibility to give a valid ERASE / WRITE code in ROM_OPAD before | calling the ERASE_WRITE function. It uses while loop for waiting so an invalid call to it may cause the | program to Hang forever | All the data passing to and from the ROM() function is done using global variables described below | ROM_WRD: 2 Byte(int) IO Buffer for EEPROM. | you will store data in ROM_WRD before a write to EEPROM | and the EEPROM will store data in it when you perform a READ | ROM_OPAD: 1 Byte(char) ROM opcode + Address | EEPROM has a single byte opcode + address this is stored by you in this byte | before giving any command to the EEPROM. | // | Usage: 1. Put the Opcode and Address in ROM_OPAD | 2. Except for WRITE, ERASE, ERAL and WRAL commands Call ROM(). And thats all you need to do | If you gave the READ command then the Data at your given address is now in ROM_WRD | 3. For the WRITE and WRAL Commands first put the data word in ROM_WRD ( 2-bytes ). Do nothing For Erase| and ERAL command | 4. Call ERASE_WRITE(). At the address in ROM_OPAD the ERASE or WRITE of data in ROM_ERD would be done | For the ERAL and WRAL commands no address is involved and these would be completed | // | Instrction Set for 93C46B: Taken from its datasheet by Microchip® Sorted by Opcode | Note: Opcode 00 has extended meaning and uses 2 positions in MSB of address so it gives 4 menings | One of these four meanings needs 25 clocks since it is s write to all command. | ____________________________________________________________________________________________ | |Instruction |SB |OPCODE | ADDRESS | DATA IN | DATA OUT |Req Clk Cycles | | |-------------------------------------------------------------------------------------------| | | EWDS | 1 | 00 |0 0 X X X X|-----------| HIGH-Z | 9 | | |-------------------------------------------------------------------------------------------| | | WRAL | 1 | 00 |0 1 X X X X| D15-D0 |RDY/(BUSY)'| 25 | | |-------------------------------------------------------------------------------------------| | | ERAL | 1 | 00 |1 0 X X X X|-----------|RDY/(BUSY)'| 9 | | |-------------------------------------------------------------------------------------------| | | EWEN | 1 | 00 |1 1 X X X X|-----------| HIGH-Z | 9 | | |-------------------------------------------------------------------------------------------| | | WRITE | 1 | 01 |A5 A4 A3 A2 A1 A0| D15-D0 |RDY/(BUSY)'| 25 | | |-------------------------------------------------------------------------------------------| | | READ | 1 | 10 |A5 A4 A3 A2 A1 A0|-----------| D15-D0 | 25 | | |-------------------------------------------------------------------------------------------| | | ERASE | 1 | 11 |A5 A4 A3 A2 A1 A0|-----------|RDY/(BUSY)'| 9 | | |-------------------------------------------------------------------------------------------| | // | Note: 1) SB stands for Start Bit | 2) OPCODE + ADDRESS is a single byte | Command Description: | ERASE: Erase a memory location given by A5-A0 in the ROM_OPAD | ERAL : Erase All 64 memory locations at once | EWDS : Disable Erase / write | EWEN : Enable Erase / write | READ : Read a Word (2-Bytes) from the location given by A5-A0 in the ROM_OPAD | ERASE_WRITE: Write a Word (2-Bytes) to the location given by A5-A0 in the ROM_OPAD | WRAL : Write same Word (2-Bytes) to all the locations | // | Main Algorithm: Send SB first then OPCODE+ADDRESS BYTE then send 16 clocks (with data for write). | Commands except READ,ERASE_WRITE and WRAL end on the ninth clock. Other commands require 25 | clocks, 9 for OPcode+Address and 16 for Data. | SPEED: All response times for 93C46B are in nS so no delays /waits need to be implemented upto 12MHz clock | /***************************************************************************************************************/ #include //Define 8051 registers | /**-------------------------------------------FUNCTIONS PROTOTYPES--------------------------------------------**/ void Initialize(void); // Function to Initiallize Variables | void ROM(void); // Function to deal with EEPROM(93C46B) | void ERASE_WRITE (void); // Function for write cycle of 93C46B | // | /******************************-----------------GLOBAL VARIABLES---------------*********************************/ int ROM_WRD; // ROM_WRD acts as a IO buffer for the EEPROM | char ROM_OPAD; // ROM_OPAD keeps current OPCODE+ADDRESS for the EEPROM | // | /**------------------------------------Port Pins Renaming for Convinience-------------------------------------**/ sbit ROM_DO = P3^2; // P3.2 EEPROM CS pin(4) of 93C46B is connected here | sbit ROM_DI = P3^3; // p3.3 EEPROM DI pin(3) of 93C46B is connected here | sbit ROM_CK = P3^4; // P3.4 EEPROM DO pin(2) of 93C46B is connected here | sbit ROM_CS = P3^5; // P3.5 EEPROM CK pin(1) of 93C46B is connected here | // | /*****************************---------------The Main Function-----------------*********************************/ /*void main (void) // | { // | Init_ROM(); // Initialize Local Variables | while(1) // Loop Forever the following Routine | { // | // Place your calls to ERASE_WRITE() and ROM() in the main code here | } // | } // | // | /**------------------------------------------The Initialize Function------------------------------------------**/ void Init_ROM (void) // | { // | ROM_DO =1; // Get Ready to receive data on this pin | ROM_OPAD=0x080; // Make it a read command so nothing is erased | ROM(); /* Call to ROM Routine to cancel out false start bit given | because when 8051 starts all its pins are at logic 1 | but ROM_CS = ROM_DI = ROM_CK = 1 means start bit for ROM | We Shall keep ROM_CK = 0 in future and this is done at the | end of ROM() function*/ // | //----------------------Enable These Lines for Erasing the ROM Chip----------------------------- | // ROM_OPAD=0x020; // Get ERAL (ERase ALL) Command Ready | // ERASE_WRITE(); // Call to ERASE_WRITE routine for sending the selected command | //---------------------------------------------------------------------------------------------- | } // | // | /******************************--------------The 93C46 EPROM Functions------------******************************/ void ROM(void) // | { // | char i; // Variable to count in loops | unsigned char ROM_OP=ROM_OPAD; // Copy ROM OPCODE from OPCODE+ADDRESS byte | ROM_OP&=0xC0; // Decode ROM OPCODE (i.e. Remove Address) | if (!ROM_OP) // OPCODE = 00? | { // | ROM_OP=ROM_OPAD & 0x030; // Mask so only first two bits of the Address field of ROM_OPAD Remain | if (ROM_OP == 0x010) // A WRAL command? | ROM_OP=0x040; // Convert it to a write Command to send 16 bits to EEPROM after OPAD | } // | //-------------------Start Bit---------------------------// | ROM_CS=1; // Select the ROM Chip | ROM_DI=1; // Start bit ready | ROM_CK=1; // Start bit given by Positive edge of clock | // | //----------------------OPCODE+ADDRESS-------------------// | for(i=0;i<8;i++) // Give OPAD (Opcode + Address) Byte to EEPROM | { // | ROM_CK=0; // Get ROM clock ready | ROM_OPAD<<=1; // Left-shift ROM OPCODE+ADDRESS by one bit. Carry = MSB | ROM_DI=CY; // Put the carry bit onto ROM Data In | ROM_CK=1; // Give this bit to ROM by Positive edge of clock | } // | // | //------------------------Write--------------------------// | if(ROM_OP==0x040) // ROM OPCODE is for WRITE or WRAL(Write ALL) instruction? | { // | for(i=0;i<16;i++) // Give the 16 bit Data to the ROM | { // | ROM_CK = 0; // Get ROM clock ready | ROM_WRD <<= 1; // Left-shift ROM_WRD by one bit. Carry = MSB | ROM_DI = CY; // Put the carry bit into ROM Data In | ROM_CK = 1; // Give this bit to ROM by Positive edge of clock | } // | } // | //------------------------READ--------------------------// | else if(ROM_OP==0x080 ) // ROM OPCODE for Read Instruction? | { // | ROM_WRD=0; // Initiallize ROM_WRD to store read DATA | for(i=0;i<16;i++) // Read the 16 bit Data from the ROM | { // | ROM_CK = 0; // Get ROM clock ready | ROM_CK = 1; // Give Positive edge of clock for ROM to put MSB at ADDRESS on DO | ROM_WRD <<=1; // Left_shift the ROM_WRD to make room for new bit to ADD | if (ROM_DO) // A '1'? | ROM_WRD++; // Add '1'to ROM_WRD | } // | } // | ROM_CS=0; // Unselect the ROM chip | ROM_DI=0; // Reset the ROM DI | ROM_CK=0; // Get Ready for next Start Bit | } // | // | void ERASE_WRITE (void) // | { // | char TEMP; // Temporay storage of a byte | unsigned int ROM_WAIT =20000; TEMP=ROM_OPAD; // Save a copy of user's OPCODE + Address | ROM_OPAD=0x030; // EWEN COMMAND for ROM (00¦110000) | ROM(); // CALL to ROM Function to send command | ROM_OPAD=TEMP; // Restore the copy of user's OPCODE + Address | ROM(); // Call to ROM Function for writing the data to respective Location | ROM_CS=1; // Select ROM Chip to read status | while(!ROM_DO) { if (--ROM_WAIT<0)break; } // Wait for ROM chip to become ready | ROM_OPAD=0x000; // EWDS Command (00¦000000) | ROM(); // Call to ROM Function to Send command | } // | //--------------------------------------END of Program----------------------------------------------------------|