25LC512 SPI Eeprom

General discussion on mikroBasic for dsPIC30/33 and PIC24.
Post Reply
Author
Message
jmarkwolf
Posts: 89
Joined: 01 Apr 2007 15:45
Location: Southeast Michigan
Contact:

25LC512 SPI Eeprom

#1 Post by jmarkwolf » 27 Nov 2007 03:41

I'm attempting to read/write the Microchip 25LC512 64Kbyte SPI eeprom.

The address is 16-bits, and it appears that dimensioning the EEaddr variable as a WORD is in-sufficient to clock out the correct number of address bits. in the SPI_Write command.

How does on parse the high and low bytes from a word in MeBasic?

Code below:

Code: Select all

program SPI_Eeprom_Test
'device = dsPIC30F4013
'
Symbol EEcs = portB.11
symbol PGAcs = portB.12
'
main:
dim x as byte
    EEaddr as word      '
    EEread as byte      'read data from selected address
    EEwrite as byte     'write data to selected address
    EEwren as byte      'set write enable latch (enable write ops)
    EEwrdi  as byte     'reset the write enable latch (disable write ops)
    EErst as byte       'read status register
    EEwst as byte       'write status register
    EEpe as byte        'page erase
    EEse as byte        'sector erase
    EEce as byte        'chip erase
    EErdid as byte      'release from deep power down & read ID
    EEdpd as byte       'enter deep power down mode
    databyte as byte    '
'
Spi1_init()             'init hardware SPI port
Uart1_Init(9600)        'init hardware uart
u1mode.10 = 1           'specify alternate uart pin pairs (altio bit)
'
  ADCHS  = 0xFFFF       '
'
  TRISA  = $0800        '
  TRISB  = $02c2
  TRISC  = $4010
  TRISD  = $0302
  TRISF  = $0005
'
'goto Blink_LED
'
'******************************************************************************
'
' This routine writes 10 bytes to the Mchip 25LC512 external eeprom
'
'******************************************************************************
'
EEcs = 1
Spi1Stat.15 = 1       'enable SPI ports
Spi1Con.11 = 0        'enable SDO1 pin
'
' Write to eeprom
'
loop1:
EEcs = 0
Spi1_write(EEwren)
EEcs = 1
'
      EEaddr = 0
      databyte = 100
        while EEaddr <> 10
          EEcs = 0
          Spi1_write(EEwrite)
          Spi1_write(EEaddr)
          Spi1_write(databyte)
          delay_ms(100)
          EEaddr = EEaddr + 1
          databyte = databyte - 1
'          delay_ms(100)
        wend
    EEcs = 1
EEcs = 0
  Spi1_write(EEwrdi)
EEcs = 1
'
'******************************************************************************
'
' Read 10 bytes from eeprom and write to uart
'
'******************************************************************************
'
EEaddr = 0
'
    while EEaddr <> 10
        EEcs = 0
          Spi1_write(EEread)      'write the READ command
'          Spi1_write(0x00)      'try dummy hi byte
          Spi1_write(EEaddr)      'write the 16-bit address
          databyte = Spi1_read(0)  'read the eeprom
        EEcs = 1
'
        Uart1_Write_char(databyte)    '
        EEaddr = EEaddr + 1
'        delay_ms(100)
    wend
'
goto loop1



end.
'
'******************************************************************************
'
' This routine blinks LED on same pin as Hardware SPI Dout
'
'******************************************************************************
'
Blink_lED:
'
x = 5
'
  while x <> 0

portf.3 = 1
      Delay_ms(500)

portf.3 = 0
      Delay_ms(500)
x = x - 1
  wend
end.

User avatar
zristic
mikroElektronika team
Posts: 6608
Joined: 03 Aug 2004 12:59
Contact:

Re: 25LC512 SPI Eeprom

#2 Post by zristic » 27 Nov 2007 11:39

You may try this:

Spi1_write(Lo(EEaddr))
Spi1_write(Hi(EEaddr))

Also, check if your PIC does not already have the register named "EEadr". You are maybe overlapping it...

jmarkwolf
Posts: 89
Joined: 01 Apr 2007 15:45
Location: Southeast Michigan
Contact:

#3 Post by jmarkwolf » 28 Nov 2007 13:49

I found precious little information regarding implementation of an external SPI eeprom with mE Basic for dsPIC, but with the help of ZRISTIC and others I was able to get my Microchip 25LC512 SPI eeprom routine going.

Code below. Perhaps it will help others.

In appreciation...

Code: Select all

'
'******************************************************************************
'
' This program writes 10 bytes of data to a 25LC512 eeprom, using the hardware
' SPI port, then reads back the same bytes, sending them out the hardware uart
' for confirmation on the USART Terminal facility.
'
'******************************************************************************
'
program Spi_EEprom_Test
'CPU = dsPIC4013
'eeprom = 25LC512
'
Symbol EEcs = portB.11
symbol PGAcs = portB.12
'
const EEread  as byte = $03     'read data from selected address
const EEwrite as byte = $02     'write data to selected address
const EEwren  as byte = $06     'set write enable latch (enable write ops)
const EEwrdi  as byte = $04     'reset the write enable latch (disable write ops)
const EErst   as byte = $05     'read status register
const EEwst   as byte = $01     'write status register
const EEpe    as byte = $42     'page erase
const EEse    as byte = $d8     'sector erase
const EEce    as byte = $c7     'chip erase
const EErdid  as byte = $ab     'release from deep power down & read ID
const EEdpd   as byte = $b9     'enter deep power down mode
'
main:
dim x as byte
    databyte as byte            '
    EEaddr as longint           '
'
Spi1_init()                     'init hardware SPI port
Uart1_Init(9600)                'init hardware uart
u1mode.10 = 1                   'specify alternate uart pin pairs (altio bit)
'
  ADPCFG = 0xFFFF               '
'
  TRISA  = $0800                '
  TRISB  = $02c2
  TRISC  = $4010
  TRISD  = $0302
  TRISF  = $0005
'
'goto Blink_LED
'
'******************************************************************************
'
' This routine writes 10 bytes to the Mchip 25LC512 external eeprom
'
'******************************************************************************
'
EEcs = 1
Spi1Stat.15 = 1       'enable SPI ports
Spi1Con.11 = 0        'enable SDO1 pin
'
loop1:
EEcs = 0
Spi1_write(EEwren)               'enable writes
EEcs = 1
'
      EEaddr = 0
      databyte = 100
          EEcs = 0
        while EEaddr <> 10
'          EEcs = 0
          Spi1_write(EEwrite)
          Spi1_write(Hi(EEaddr))
          Spi1_write(Lo(EEaddr))
          Spi1_write(databyte)
'          EEcs = 1
          EEaddr = EEaddr + 1
          databyte = databyte - 1
        wend
          EEcs = 1
delay_ms(10) 'do not omit this delay, otherwise no worky! 5mS minimum required.
'
EEcs = 0
  Spi1_write(EEwrdi)           'disable writes to eeprom
EEcs = 1
'
'******************************************************************************
'
' Read 10 bytes from eeprom and write to uart
'
'******************************************************************************
'
EEaddr = 0
'
        EEcs = 0
    while EEaddr <> 10
'        EEcs = 0
          Spi1_write(EEread)      'issue the READ command
          Spi1_write(Hi(EEaddr))
          Spi1_write(Lo(EEaddr))
          databyte = Spi1_read(0)  'read the eeprom
'        EEcs = 1
'
        Uart1_Write_char(databyte)    '
        EEaddr = EEaddr + 1
    wend
        EEcs = 1
'
goto loop1
'
end.
'
'******************************************************************************
'
' This routine blinks LED on same pin as Hardware SPI Dout to confirm
' hardware signal path.
'
'******************************************************************************
'
Blink_lED:
'
x = 5
'
  while x <> 0

portf.3 = 1
      Delay_ms(500)

portf.3 = 0
      Delay_ms(500)
x = x - 1
  wend
end.

OT
Posts: 581
Joined: 19 May 2005 05:08
Location: Fairbanks, Alaska

#4 Post by OT » 01 Dec 2007 14:28

I had a go at this in dsPIC Mpascal with 25LC1024 which is similar except that the address is 32 bit long, with some help from your code.
In your code I notice you have the chip enable/disable inside the loops commented out and instead have it outside the loops.

If I include these inside the read loop I find that only the first character or every 4th character is read out, with garbage in between. Ouside the loop it works fine, which it really shouldn't.
Did you have similar problems?

jmarkwolf
Posts: 89
Joined: 01 Apr 2007 15:45
Location: Southeast Michigan
Contact:

#5 Post by jmarkwolf » 01 Dec 2007 23:21

No, I'm not having that problem, but haven't started using the part in earnest yet, but I did have some goofy stuff happen while getting the code up and running.

It might be a "page" thing. The 25LC512 has a 128 byte "page", to which you can write 128 bytes (and no more) quickly. After which you have to transfer the page to the array, before writing more bytes to the "page". The final chip select does this. This is the thing that takes a minimum of 5mS to complete. It is internally timed so all you have to do is wait for it to expire.

It's that final chip select that does the actual transfer. If you're wiggling your chip select after each byte written to the device, the internal eeprom page logic ignores further writes until the 5mS long transfer is complete. This is probably what's hanging you up.

I'm probably going to go with the Ramtron FM25256, which doesn't suffer from the page write issue, and can write at full bus speeds.

I'd be interested to hear if you have more issues.

OT
Posts: 581
Joined: 19 May 2005 05:08
Location: Fairbanks, Alaska

#6 Post by OT » 02 Dec 2007 09:23

With a standby current of 150uA and only 5V power the Ramtron FM25256 would not work for my purpose. Your thoughts about page write and delays are interesting; I was mostly concerned about making sure the SPI finished its work and not thinking about additional delays. With respect to the boundaries I want to write only one byte at a time (also because of this), and because I will only need to write a couple of bytes every now and then.

Anyway, my problem is not with the writes, it is with the reads. (I can keep the CS statements inside the loop for the writes as long a it is outside the loop for the reads). Need to check if any more delays are needed, during my testing I did try introducing delays at various places without any improvement.

OT
Posts: 581
Joined: 19 May 2005 05:08
Location: Fairbanks, Alaska

#7 Post by OT » 02 Dec 2007 13:28

I posted my problem code for the 25LC1024 in the dsPIC Pascal forum. This version include WIP polling:
http://www.mikroe.com/forum/viewtopic.php?p=63499#63499

jmarkwolf
Posts: 89
Joined: 01 Apr 2007 15:45
Location: Southeast Michigan
Contact:

#8 Post by jmarkwolf » 02 Dec 2007 14:17

OT wrote:Anyway, my problem is not with the writes, it is with the reads.
How can you be confident your writes are working if you can't read the same data back?

OT
Posts: 581
Joined: 19 May 2005 05:08
Location: Fairbanks, Alaska

#9 Post by OT » 03 Dec 2007 02:06

jmarkwolf wrote:
OT wrote:Anyway, my problem is not with the writes, it is with the reads.
How can you be confident your writes are working if you can't read the same data back?
Because between a working and not working version I only make changes to the read code and no changes to the write code.
Also, after running a version that did not read correctly, I commented out the write section, so that all the program did was to read from EEPROM what was already there. The characters were available in EEPROM with the working version of the read code, but could not be read with the version where CS is changed inside the loop.

Edit: While this proves that there is a problem with the read, it could still be a problem with write, since data are not erased before the writes are started. And when trying a new chip it showed up to be a similar problems with the write. So the EEPROM data came from when the program seemed to be working. BTW I tried testing with chiperase before writing, however I cannot get it to work.

I also tested a 25LC256 (with 16 bit address) and the same happens with this chip.

OT
Posts: 581
Joined: 19 May 2005 05:08
Location: Fairbanks, Alaska

Possibly solved

#10 Post by OT » 03 Dec 2007 13:48

I have not seen this in the documentation anywhere, however it seemed that it was necessary to have a write unprotect before every write followed by a write protect when writing was finished. This also solved the problem on the read side for unknown reason. See the pascal forum post:
http://www.mikroe.com/forum/viewtopic.php?p=63575#63575
which is the current version of the code which works both on 25LC256 and 25LC1024 by setting the proper define/undefine. There are some further write tests too.

OT
Posts: 581
Joined: 19 May 2005 05:08
Location: Fairbanks, Alaska

#11 Post by OT » 04 Dec 2007 11:41

This explains the need to set the write enable latch for each write (from the data sheet):
"A write enable instruction must be issued to set the write enable latch. After a byte write, page write or STATUS register write, the write enable latch is reset."

OT
Posts: 581
Joined: 19 May 2005 05:08
Location: Fairbanks, Alaska

#12 Post by OT » 05 Dec 2007 07:38

My pascal code for the Mircrochip SPI EEPPROMs has now been organized it into a unit + test program which can be found here:
http://www.mikroe.com/forum/viewtopic.php?t=12629

Bugz Bensce
Posts: 11
Joined: 09 Nov 2015 20:29

Re: 25LC512 SPI Eeprom

#13 Post by Bugz Bensce » 18 Nov 2015 20:38

I have Successfully implemented External EEPROM via SPI(Serial Peripheral Interface) with a PIC16F887.
If you want the Project and Simulation(Proteus) you can download it below. All libraries are user defined and code is commented to explain coding decisions/implementations.
The Micro controller writes several values to the External Memory device and reads the back by only passing the address.
The read data is output via a 7-segment Common Anode display connected to PortD of the MCU.
Attachments
EEPROM_SPI.zip
NB: The simulation takes a bit of time to run because of the initial Write process. Please be patient.
(126.57 KiB) Downloaded 238 times

Post Reply

Return to “mikroBasic for dsPIC30/33 and PIC24 General”