reads, writes, and erases a 256-byte serial EEPROM.
One of the best features of the BASIC Stamp hardware is the 93LC56 serial EEPROM. The Stamp uses this device for program space, lookup tables, and nonvolatile data storage.
The program listing presents a series of subroutines that read, write, erase, write-protect, and write-enable the 93LC56. These routines are not port- and pin-independent. The program is based on the circuit shown in the illustration. If you need to change this circuit, make sure to change both the equates for D, CLK and CS, and the data-direction settings for the EEPROM port (mov !ra,x). These are at the start of the program, and in the subroutines EEread and Busy.
The program, which originally appeared in Parallax PIC Application Note #11, writes a rotating bit pattern to the EEPROM, then plays it back on a bank of eight LEDs connected to port RB. Not very exciting, but it verifies every storage cell of the EEPROM with a minimum of programming. Not all programs require the entire set of subroutines. Some are included just for the sake of demonstrating all the EEPROM's capabilities. For example, most programs can do without the routine that erases individual bytes, since a write accomplishes the same thing. And very few programs need to completely erase the EEPROM, or write a single value to all cells. So you should be able to remove EErase, EEwipe, and EEwrall to conserve program-memory space.
For more information on the EEPROM's characteristics and capabilities, please see the current edition of the Microchip Embedded Control Handbook.
To see EEPROM in operation, connect the circuit below to an erasable PIC or PIC emulator, such as the Parallax downloader. Assemble and run EEPROM.SRC. When you apply power to the PIC, it will write a scanning pattern to the bits of the EEPROM, then read this pattern back onto the LEDs.
; EEPROM (related subroutines) ; This is a collection of subroutines for reading, writing, and ; erasing the 93LC56 (or 'C56) serial EEPROM. As a demonstration, it ; writes a scanning pattern to the 256 bytes of the EEPROM, and then ; reads it back to eight LEDs connected to port rb. D = ra.0 ; Pins DI and DO of the EEPROM CLK = ra.1 ; Clock pin--data valid on rising edge CS = ra.2 ; Chip select--high = active ROP = 192 ; Opcode for read WROP = 160 ; Opcode for write EWEN = 152 ; Opcode to enable erase and write EWDS = 128 ; Opcode to disable erase and write ERAS = 224 ; Opcode to erase a byte ERAL = 144 ; Opcode to erase all bytes WRAL = 136 ; Opcode to write all bytes org 8 temp ds 1 ; Temporary variable for EE routines EEdata ds 1 ; Data to EEwrite/wrall, from EEread EEaddr ds 1 ; Address to EErase, EEwrite, EEread clocks ds 1 ; Number of clock cycles for SHiftOUT tick1 ds 1 ; Timer for demo. tick2 ds 1 ; Timer for demo. device pic16c54,xt_osc,wdt_off,protect_off reset start org 0 start mov ra,#0 ; Clear ports mov rb,#0 mov !ra,#0 ; Make all ra pins outputs initially. mov !rb,#0 ; Output for LEDs. call EEnable ; Turn off write/erase protection. mov EEdata,#1 ; EEdata = 1. mov EEaddr,#0 ; Start at address 0. :loop call EEwrite ; Write pattern to EEPROM call Busy ; Wait until done writing. rr EEdata ; Rotate the pattern right. ijnz EEaddr,:loop ; FOR EEaddr = 0 to 255... call EEdisbl ; Turn write/erase protection back on. :loop2 call EEread ; Now read back contents of EEPROM. mov rb,EEdata ; Display the EEPROM data on LEDs. inc EEaddr ; Set up for next address. call delay ; Delay to slow down the scanning. goto :loop2 ; Do forever. ; Shout shifts out the bits of the variable temp to the EEPROM data line. ; All of the other EEPROM routines call Shout. Shout rl temp ; Rotate bit7 of temp into carry movb D,c ; Move carry bit to input of EEPROM setb CLK ; Clock the bit into EEPROM nop ; Clock must be high > 500 ns clrb CLK djnz clocks,Shout ; FOR I = 1 TO clocks... ret ; Read the byte in EEaddr into EEdata. EEread mov temp,#ROP ; Move the read opcode into temp mov clocks,#4 ; Number of bits to shift out (op+1) setb CS ; Select the EEPROM. call Shout ; Shift the read opcode out. mov clocks,#8 ; Number of bits to output (8 addr bits). mov temp,EEaddr ; Set up to send the address. call Shout ; Shift out the address. mov !ra,#1 ; Now, change D to input. mov clocks,#8 ; Number of bits to input (8 data bits). :read setb CLK ; Data valid on rising edge of clock. movb c,D ; Data bit into carry. rl temp ; Rotate carry into temp. clrb CLK ; Falling edge of clock. djnz clocks,:read ; FOR I = 1 TO 8... mov EEdata,temp ; Move temp into EEdata mov !ra,#0 ; Restore D to output. clrb CS ; Deselect the EEPROM. ret ; Call to unprotect after EEdisbl or power up or any time EEPROM ; has been write protected. EEnable setb CS ; Select the EEPROM. mov clocks,#12 ; Set up to shift out opcode. mov temp,#EWEN ; temp = erase/write-enable op code. call Shout ; Shift temp out to the EEPROM. clrb CS ; Done. Deselect EEPROM. ret ; Call to protect against accidental write/erasure. Manufacturer advises ; leaving EEPROM in write-protected state most of the time to prevent accidental ; alteration by a runaway program. EEdisbl setb CS ; Select the EEPROM. mov clocks,#12 ; Set up to shift out opcode. mov temp,#EWDS ; temp = erase/write-disable op code. call Shout ; Shift temp out to the EEPROM. clrb CS ; Done. Deselect EEPROM. ret ; Write the byte in EEdata to EEaddr. EEwrite mov temp,#WROP ; Get the write op code. mov clocks,#4 ; Prepare to shift out 4 msbs. setb CS ; Select the EEPROM. call Shout ; Shift temp out to the EEPROM. mov clocks,#8 ; Now prepare for 8 addr bits. mov temp,EEaddr ; Move address into temp. call Shout ; Shift temp out to the EEPROM. mov clocks,#8 ; Prepare for 8 data bits. mov temp,EEdata ; Move data into temp. call Shout ; Shift temp out to the EEPROM. clrb CS ; Done. Deselect EEPROM. ret ; Erase the byte in EEaddr. Erasure leaves 0FFh (all 1s) in the byte. EErase mov temp,#ERAS ; Get the erase op code. mov clocks,#4 ; Prepare to shift out 4 msbs. setb CS ; Select the EEPROM. call Shout ; Shift temp out to the EEPROM. mov clocks,#8 ; Prepare for 8 addr bits. mov temp,EEaddr ; Move address into temp. call Shout ; Shift address out to the EEPROM. clrb CS ; Done. Deselect EEPROM. ret ; Erase the entire EEPROM--all 256 bytes. Call before using EEwrall below. EEwipe setb CS ; Select the EEPROM. mov temp,#ERAL ; Get the erase-all opcode. mov clocks,#12 ; Prepare to shift out 12 bits. call Shout ; Send op code + don't-care bits. clrb CS ; Done. Deselect EEPROM. ret ; Write the byte in EEdata to every address. Call EEwipe first. EEwrall setb CS ; Select the EEPROM. mov temp,#WRAL ; Get the write-all opcode. mov clocks,#12 ; Prepare to shift out 12 bits. call Shout ; Send op code + don't-care bits. mov clocks,#8 ; Prepare to shift out 8 data bits. mov temp,EEdata ; Move data into temp. call Shout ; Shift temp out to EEPROM. clrb CS ; Done. Deselect EEPROM. ret ; Check flag to determine whether the EEPROM has finished its self-timed ; erase/write. Caution: This will lock up your program until D goes high. Busy mov !ra,#1 ; Set D to input. setb CS ; Select the EEPROM. :wait jnb D,:wait ; Wait until D goes high (end of write). clrb CS ; Done. Deselect EEPROM. mov !ra,#0 ; Restore D to output. ret ; Delay routine for demo. Delay djnz tick1,Delay djnz tick2,Delay ret