M25P128Module
SwordfishUser.M25P128Module History
Hide minor edits - Show changes to output
Changed line 2 from:
to:
Deleted line 1:
Changed line 2 from:
to:
%center%http://www.ohararp.com/images/WEATHER_A.JPG"Easypic4 Dev Board"\\
Changed lines 2-3 from:
to:
Changed lines 2-4 from:
to:
%center%http://www.ohararp.com/images/WEATHER_A.JPG"Easypic4 Dev Board"\\
[[http://www.intersema.ch/index.php?option=com_rubberdoc&view=doc&id=41&format=raw | link text]]
[[http://www.intersema.ch/index.php?option=com_rubberdoc&view=doc&id=41&format=raw | link text]]
Changed lines 8-9 from:
This module was created to share with others the great datalogging potential of this little chip in conjunction with the SF compiler. This chip is accessed in a manner very similar to a Serial EEPROM. I did want to point out several distinct difference that could cause trouble for people.
to:
This module was created by Timothy Box and converted to SF by Ryan O'Hara to share with others the great datalogging potential of this little chip in conjunction with the SF compiler. This chip is accessed in a manner very similar to a Serial EEPROM. I did want to point out several distinct difference that could cause trouble for people.
Changed lines 1-4 from:
http://www.ohararp.com/images/M25P128_SCH.JPG"M25P128 Schematic"\\
to:
%center%http://www.ohararp.com/images/M25P128_SCH.JPG"M25P128 Schematic"\\
%lfloat% http://www.sfcompiler.co.uk/wiki/uploads/StevenWright/download.gif
%lfloat% http://www.sfcompiler.co.uk/wiki/uploads/StevenWright/download.gif
Added lines 7-8:
Changed line 1 from:
http://www.ohararp.com/images/M25P128_SCH.JPG"M25P128 Schematic"
to:
http://www.ohararp.com/images/M25P128_SCH.JPG"M25P128 Schematic"\\
Changed line 1 from:
http://www.ohararp.com/images/M25P128_SCH.JPG"M25P128" | '''Figure 1'''
to:
http://www.ohararp.com/images/M25P128_SCH.JPG"M25P128 Schematic"
Added line 4:
!!! Introduction
Changed lines 6-7 from:
1. Each sector of memory must have been previously erased before writing to that page. This means you cannot write to several addresss and then "backup" to rewrite to the first address. The entire sector must be erased before you can return rewrite to the first address.
to:
1. Each sector of memory must have been previously erased before writing to that page. This means you cannot write to several address and then "backup" to rewrite to the first address. The entire sector must be erased before you can return rewrite to the first address.
Changed lines 10-12 from:
3. Finally, if you are using this chip in conjunction with a usb connection, when the
to:
3. Finally, if you are using this chip in conjunction with a usb connection, when the BulkErase command is issued it can take a fair amount of time (30 seconds or so) to earse all the data memory. You must somehow poll the usb line to keep the usb connection alive when this command is used.
Changed lines 2-12 from:
to:
[[http://www.ohararp.com/files/M25P128.pdf | M25P128 Datasheet]]
This module was created to share with others the great datalogging potential of this little chip in conjunction with the SF compiler. This chip is accessed in a manner very similar to a Serial EEPROM. I did want to point out several distinct difference that could cause trouble for people.
1. Each sector of memory must have been previously erased before writing to that page. This means you cannot write to several addresss and then "backup" to rewrite to the first address. The entire sector must be erased before you can return rewrite to the first address.
2. When you use the WriteBytes command you can begin at any address within a sector/page. However, caution must be taken so that you do not write over a page boundary.
3. Finally, if you are using this chip in conjunction with a usb connection, when the
This module was created to share with others the great datalogging potential of this little chip in conjunction with the SF compiler. This chip is accessed in a manner very similar to a Serial EEPROM. I did want to point out several distinct difference that could cause trouble for people.
1. Each sector of memory must have been previously erased before writing to that page. This means you cannot write to several addresss and then "backup" to rewrite to the first address. The entire sector must be erased before you can return rewrite to the first address.
2. When you use the WriteBytes command you can begin at any address within a sector/page. However, caution must be taken so that you do not write over a page boundary.
3. Finally, if you are using this chip in conjunction with a usb connection, when the
Added lines 1-2:
http://www.ohararp.com/images/M25P128_SCH.JPG"M25P128" | '''Figure 1'''
Changed line 367 from:
Public Function ReadBytes(pM25PDataAddress As LongWord,ByRef pM25PDataIn() As Byte,pBytesToRead As LongWord) As Byte
to:
Public Sub ReadBytes(pM25PDataAddress As LongWord,ByRef pM25PDataIn() As Byte,pBytesToRead As LongWord)
Changed line 389 from:
End Function
to:
End Sub
Changed line 8 from:
OSC = HSPLL, // HS Oscillator
to:
OSC = HSPLL, // HS Oscillator
Changed line 13 from:
WDT = OFF, // Watchdog Timer Disabled
to:
WDT = OFF, // Watchdog Timer Disabled
Changed lines 15-17 from:
WDTPS = 256, // 15000 x 4mS = 60 seconds
LVP = OFF, // Low_Voltage Programming
PBADEN = OFF // PORTB Digital
LVP
to:
WDTPS = 256, // 15000 x 4mS = 60 seconds
LVP = OFF, // Low_Voltage Programming
PBADEN = OFF // PORTB Digital
LVP = OFF, // Low_Voltage Programming
PBADEN = OFF // PORTB Digital
Changed lines 2-15 from:
*****************************************************************************
* Name
*
* : All Rights Reserved
* Date : 1/16/2009
* Version : 1.0
* Notes : This code was originally developed by Tim Box and ported to SF
* : by Ryan O'Hara
* : This handy little chip provides up to 128Mb -> 16MB of Flash memory
*****************************************************************************
}
Module M25P128
to:
// DEVICE AND CLOCK
Device = 18F2620
Clock = 40
// DEVICE FUSE CONFIG
Config
OSC = HSPLL, // HS Oscillator
FCMEN = OFF, // Failsafe Clock Monitor Disabled
IESO = OFF, // Int/Ext Oscillator Switch Over Disabled
PWRT = OFF, // Power Up Timer Disabled
BOREN = OFF, // Brownout Reset Disabled
WDT = OFF, // Watchdog Timer Disabled
MCLRE = ON, // MCLR Enabled
WDTPS = 256, // 15000 x 4mS = 60 seconds
LVP = OFF, // Low_Voltage Programming
PBADEN = OFF // PORTB Digital
Device = 18F2620
Clock = 40
// DEVICE FUSE CONFIG
Config
OSC = HSPLL, // HS Oscillator
FCMEN = OFF, // Failsafe Clock Monitor Disabled
IESO = OFF, // Int/Ext Oscillator Switch Over Disabled
PWRT = OFF, // Power Up Timer Disabled
BOREN = OFF, // Brownout Reset Disabled
WDT = OFF, // Watchdog Timer Disabled
MCLRE = ON, // MCLR Enabled
WDTPS = 256, // 15000 x 4mS = 60 seconds
LVP = OFF, // Low_Voltage Programming
PBADEN = OFF // PORTB Digital
Added line 20:
#option WDT = True
Added lines 23-105:
// INCLUDES
Include "UTILS.BAS"
Include "SUART.bas"
Include "CONVERT.bas"
Include "SHIFT.bas"
Include "M25P128.BAS"
// ALIAS
Dim LED_FIX As PORTB.2
Dim LED_NOFIX As PORTB.3
Dim IDX As LongWord
Dim ID As LongWord
Dim M25PData(256) As Byte
Sub SETUP()
SetAllDigital()
M25P128.Init()
SetTX(PORTB.7)
SetRX(PORTB.6)
SetBaudrate(sbr38400)
SetMode(umTrue)
End Sub
//------------------------------------------------------------------------------
SETUP()
// Serial Startup
For IDX = 0 To 4
Toggle(LED_FIX)
Toggle(LED_NOFIX)
UART.Write("HELLO WORLD",13,10)
DelayMS(1000)
Next
// Read ID
For IDX = 0 To 4
ID = M25P128.ReadId()
UART.Write("C - ",BinToStr(ID.BYTE0,8),"|",BinToStr(ID.BYTE1,8),"|",BinToStr(ID.BYTE2,8),13,10)
Next
// Erase the First Sector
M25P128.SectorErase(0)
// Write Some Data to RAM
For IDX = 0 To 255
M25PData(IDX) = IDX
Next
// Write the Data to the M25P128
M25P128.WriteBytes(128,M25PData)
// Read 256 Bytes from Address 0
M25P128.ReadBytes(128,M25PData,256)
// Write the Data to the Serial Port
UART.Write("READ BYTE - ")
For IDX = 0 To 255
UART.Write(DecToStr(M25PData(IDX)),",")
Next
UART.Write(13,10,13,10)
End=]
=code [=
{
*****************************************************************************
* Name : M25P128.BAS
* Author : Ryan O'Hara
* Notice : Copyright (c) 2009 - OHARARP LLC
* : All Rights Reserved
* Date : 1/16/2009
* Version : 1.0
* Notes : This code was originally developed by Tim Box and ported to SF
* : by Ryan O'Hara
* : This handy little chip provides up to 128Mb -> 16MB of Flash memory
*****************************************************************************
}
Module M25P128
// OPTIONS
#option SHIFT_MAX = 8
Include "UTILS.BAS"
Include "SUART.bas"
Include "CONVERT.bas"
Include "SHIFT.bas"
Include "M25P128.BAS"
// ALIAS
Dim LED_FIX As PORTB.2
Dim LED_NOFIX As PORTB.3
Dim IDX As LongWord
Dim ID As LongWord
Dim M25PData(256) As Byte
Sub SETUP()
SetAllDigital()
M25P128.Init()
SetTX(PORTB.7)
SetRX(PORTB.6)
SetBaudrate(sbr38400)
SetMode(umTrue)
End Sub
//------------------------------------------------------------------------------
SETUP()
// Serial Startup
For IDX = 0 To 4
Toggle(LED_FIX)
Toggle(LED_NOFIX)
UART.Write("HELLO WORLD",13,10)
DelayMS(1000)
Next
// Read ID
For IDX = 0 To 4
ID = M25P128.ReadId()
UART.Write("C - ",BinToStr(ID.BYTE0,8),"|",BinToStr(ID.BYTE1,8),"|",BinToStr(ID.BYTE2,8),13,10)
Next
// Erase the First Sector
M25P128.SectorErase(0)
// Write Some Data to RAM
For IDX = 0 To 255
M25PData(IDX) = IDX
Next
// Write the Data to the M25P128
M25P128.WriteBytes(128,M25PData)
// Read 256 Bytes from Address 0
M25P128.ReadBytes(128,M25PData,256)
// Write the Data to the Serial Port
UART.Write("READ BYTE - ")
For IDX = 0 To 255
UART.Write(DecToStr(M25PData(IDX)),",")
Next
UART.Write(13,10,13,10)
End=]
=code [=
{
*****************************************************************************
* Name : M25P128.BAS
* Author : Ryan O'Hara
* Notice : Copyright (c) 2009 - OHARARP LLC
* : All Rights Reserved
* Date : 1/16/2009
* Version : 1.0
* Notes : This code was originally developed by Tim Box and ported to SF
* : by Ryan O'Hara
* : This handy little chip provides up to 128Mb -> 16MB of Flash memory
*****************************************************************************
}
Module M25P128
// OPTIONS
#option SHIFT_MAX = 8
Added lines 1-315:
=code [=
{
*****************************************************************************
* Name : M25P128.BAS
* Author : Ryan O'Hara
* Notice : Copyright (c) 2009 - OHARARP LLC
* : All Rights Reserved
* Date : 1/16/2009
* Version : 1.0
* Notes : This code was originally developed by Tim Box and ported to SF
* : by Ryan O'Hara
* : This handy little chip provides up to 128Mb -> 16MB of Flash memory
*****************************************************************************
}
Module M25P128
// OPTIONS
#option SHIFT_MAX = 8
// IMPORT MODULES
Include "SHIFT.BAS"
// DEFAULT MODULE OPTIONS - USER OPTIONS CAN OVERRIDE THESE VALUES...
#option M25P_CS = PORTC.2 // use 10k ohms pull-up resistor
#option M25P_CLK = PORTC.3 // use 10k ohms pull-down resistor
#option M25P_SDI = PORTC.4 //
#option M25P_SDO = PORTC.5 //
// Validate CS pin...
#if IsOption(M25P_CS) And Not IsValidPortPin(M25P_CS)
#error M25P_CS, "Invalid option. CS must be a valid port pin."
#endif
// Validate CLK pin...
#if IsOption(M25P_CLK) And Not IsValidPortPin(M25P_CLK)
#error M25P_CLK, "Invalid option. CLK must be a valid port pin."
#endif
// Validate SDI pin...
#if IsOption(M25P_SDI) And Not IsValidPortPin(M25P_SDI)
#error M25P_SDI, "Invalid option. DI must be a valid port pin."
#endif
// Validate SDO pin...
#if IsOption(M25P_SDO) And Not IsValidPortPin(M25P_SDO)
#error M25P_SDO, "Invalid option. DO must be a valid port pin."
#endif
// ======= M25P128 Instructions ==================================
Const
M25P_WREN = $06, ' Write M25PEnable
M25P_WRDI = $04, ' Write M25PDisable
M25P_RDID = $9F, ' Read Identification
M25P_RDSR = $05, ' Read STATUS Register
M25P_WRSR = $01, ' Write STATUS Register
M25P_Read = $03, ' Read Data Bytes
M25P_Read_Fast = $0B, ' Read Data Bytes At Higher Speed
M25P_PP = $02, ' PAGE Program
M25P_SE = $D8, ' Sector Erase
M25P_BE = $C7, ' Bulk Erase
M25P_Dummy = $FF ' Dummy Byte for Fast Read
// Variables used with commands to the M25P128
Dim M25PStatus As Byte
Dim M25PIndex As Byte ' Index Counter
Dim SRWD As M25PStatus.7 ' Status Register Write M25PDisable
Dim BP2 As M25PStatus.4 ' The Block Protect (BP2, BP1, BP0) bits
Dim BP1 As M25PStatus.3
Dim BP0 As M25PStatus.2
Dim WEL As M25PStatus.1 ' The Write M25PEnable Latch
Dim WIP As M25PStatus.0 ' The Write In Progress
// Bring port and pin options into the module...
Dim CS As M25P_CS.M25P_CS@
Dim CLK As M25P_CLK.M25P_CLK@
Dim SDI As M25P_SDI.M25P_SDI@
Dim SDO As M25P_SDO.M25P_SDO@
{
****************************************************************************
* Name : Disable(PRIVATE)
* Purpose : Disable the M25P128
****************************************************************************
}
Sub M25PDisable()
High(CS) ' M25PDisable the chip again
End Sub
{
****************************************************************************
* Name : Enable(PRIVATE)
* Purpose : Enable the M25P128
****************************************************************************
}
Sub M25PEnable()
Low(CS) ' M25PEnable the chip
End Sub
{
****************************************************************************
* Name : Write(PRIVATE)
* Purpose : Write M25PEnable the M25P128
****************************************************************************
}
Sub WriteEnable()
M25PEnable() ' M25PEnable the chip
Shift.Out(MSB_FIRST,M25P_WREN,8) ' Send the WREN command
M25PDisable() ' M25PDisable the chip again
End Sub ' All done return
{
****************************************************************************
* Name : WriteDisble(PRIVATE)
* Purpose : Write M25PDisable the M25P128
****************************************************************************
}
Sub WriteDisable()
M25PEnable() ' M25PEnable the chip
Shift.Out(MSB_FIRST,M25P_WRDI,8) ' Send the WRDI command
M25PDisable() ' M25PDisable the chip again
End Sub
{
****************************************************************************
* Name : ReadID
* Purpose : Read the 24 Bit Id of the M25P128
****************************************************************************
}
Public Function ReadId() As LongWord
M25PEnable() ' M25PEnable the chip
Shift.Out(MSB_FIRST,M25P_RDID,8) ' Send the RDID command
ReadId.BYTE0 = Shift.In(MSB_POST,8) ' readin the 24 bit ID data
ReadId.BYTE1 = Shift.In(MSB_POST,8)
ReadId.BYTE2 = Shift.In(MSB_POST,8) ' M25PDisable the chip again
M25PDisable()
End Function
{
****************************************************************************
* Name : ReadStatus(PRIVATE)
* Purpose : Read the Read Status Register of the the M25P128
****************************************************************************
}
Sub ReadStatus()
M25PEnable() ' M25PEnable the chip
Shift.Out(MSB_FIRST,M25P_RDSR,8) ' Send the RDSR command
M25PStatus = Shift.In(MSB_POST,8)
End Sub
{
****************************************************************************
* Name : ReReadStatus(PRIVATE)
* Purpose : ReRead the Read Status Register of the the M25P128
****************************************************************************
}
Sub ReReadStatus()
M25PStatus = Shift.In(MSB_POST,8)
End Sub
{
****************************************************************************
* Name : BulkErase
* Purpose : Erase the Entire M25P128 DATA - TAKES AWHILE TO OPERATE
****************************************************************************
}
Public Sub BulkErase()
ReadStatus() ' Check its Not in the middle of a current Write
While WIP = 1
ReReadStatus()
Wend
M25PDisable() ' M25PDisable To ensure the Read STATUS is stopped
DelayUS(4)
M25PEnable() ' M25PEnable the chip again
WriteEnable()
M25PEnable() ' M25PEnable the chip
Shift.Out(MSB_FIRST,M25P_BE,8) ' Sent the Bulk erase instruction
M25PDisable() ' M25PDisable the chip To start the erase
End Sub
{
****************************************************************************
* Name : SectorErase
* Purpose : Erase the One Sector of the M25P128 DATA
****************************************************************************
}
Public Sub SectorErase(pM25PDataAddress As LongWord)
ReadStatus() ' Check its not in the middle of a current write
While WIP = 1
ReReadStatus()
Wend
M25PDisable() ' M25PDisable to ensure the read status is stopped
DelayUS(4)
M25PEnable() ' M25PEnable the chip again
WriteEnable()
M25PEnable() ' M25PEnable the chip
Shift.Out(MSB_FIRST,M25P_SE,8) ' Sent the Sector erase instruction
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8) ' Send the address
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8) ' The whole sector that the address is in will be
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8) ' Erased
M25PDisable() ' M25PDisable the chip to start the erase
End Sub
{
****************************************************************************
* Name : WriteStatus
* Purpose : Make areas of the M25P128 Data read only
****************************************************************************
}
Sub WriteStatus(pM25PWriteByte As Byte)
WriteEnable()
M25PEnable() ' M25PEnable the chip
Shift.Out(MSB_FIRST,pM25PWriteByte,8)
M25PDisable() ' M25PDisable the chip again
End Sub
{
****************************************************************************
* Name : WriteByte
* Purpose : Write a single byte and the specified address
****************************************************************************
}
Public Sub WriteByte(pM25PDataAddress As LongWord,pM25PWriteByte As Byte)
ReadStatus() ' Check its not in the middle of a current write
While WIP = 1
ReReadStatus()
Wend
M25PDisable() ' M25PDisable to ensure the read status is stopped
DelayUS(4)
M25PEnable() ' M25PEnable the chip again
WriteEnable() ' Write M25PEnable the device
M25PEnable() ' M25PEnable the device
Shift.Out(MSB_FIRST,M25P_PP,8) ' Sent the Page Write instruction
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8) ' Send the address
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8)
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8)
Shift.Out(MSB_FIRST,pM25PWriteByte,8) ' Finaly the data
M25PDisable() ' Finish the write by bringing the CS line high
End Sub
{
****************************************************************************
* Name : WriteBytes
* Purpose : Write up to 255 bytes from the specified address
* CAUTION : OVERLAPPING A PAGE BOUNDARY CAN CAUSE SERIOUS ERRORS
****************************************************************************
}
Public Sub WriteBytes(pM25PDataAddress As LongWord,ByRef pM25PDataOut() As Byte)
ReadStatus() ' Check its not in the middle of a current write
While WIP = 1
ReReadStatus()
Wend
M25PDisable() ' M25PDisable to ensure the read status is stopped
DelayUS(4)
M25PEnable() ' M25PEnable the chip again
WriteEnable() ' Write M25PEnable the device
M25PEnable() ' M25PEnable the device
Shift.Out(MSB_FIRST,M25P_PP,8) ' Sent the Page Write instruction
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8) ' Send the address
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8)
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8)
For M25PIndex = 0 To Bound(pM25PDataOut) ' Via FRS0 send all the data requested
Shift.Out(MSB_FIRST,pM25PDataOut(M25PIndex),8)
Next
M25PDisable() ' Finish the write by bringing the CS line high
End Sub
{
****************************************************************************
* Name : ReadByte
* Purpose : Read a single byte at the specified address
****************************************************************************
}
Public Function ReadByte(pM25PDataAddress As LongWord) As Byte
ReadStatus() ' Check its not in the middle of a current write
While WIP = 1
ReReadStatus()
Wend
M25PDisable() ' M25PDisable to ensure the read status is stopped
DelayUS(4)
M25PEnable() ' M25PEnable the chip again
Shift.Out(MSB_FIRST,M25P_Read,8) ' Sent the data read instruction
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8) ' Send the address
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8)
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8)
ReadByte = Shift.In(MSB_POST,8) ' Read the byte in
M25PDisable()
End Function
{
****************************************************************************
* Name : ReadBytes
* Purpose : Read a multiple bytes byte at the specified address
****************************************************************************
}
Public Function ReadBytes(pM25PDataAddress As LongWord,ByRef pM25PDataIn() As Byte,pBytesToRead As LongWord) As Byte
If pBytesToRead > Bound(pM25PDataIn()) Then 'Check to make sure you do not overfill the array
pBytesToRead = Bound(pM25PDataIn())
EndIf
ReadStatus() ' Check its not in the middle of a current write
While WIP = 1
ReReadStatus()
Wend
M25PDisable() ' M25PDisable to ensure the read status is stopped
DelayUS(4)
M25PEnable() ' M25PEnable the chip again
Shift.Out(MSB_FIRST,M25P_Read_Fast,8) ' Sent the data read instruction
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8) ' Send the address
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8)
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8)
Shift.Out(MSB_FIRST,M25P_Dummy,8)
For M25PIndex = 0 To pBytesToRead - 1
pM25PDataIn(M25PIndex) = Shift.In(MSB_POST,8)
Next
M25PDisable()
End Function
{
****************************************************************************
* Name : Init
* Purpose : Setup the Port Pins
****************************************************************************
}
Public Sub Init()
Output(CS)
Shift.SetClock(CLK,TRUE) //initialise shiftOUT clock pin, IDLE HIGH
Shift.SetInput(SDI)
Shift.SetOutput(SDO) //initialise shiftOUT pin
End Sub ]
{
*****************************************************************************
* Name : M25P128.BAS
* Author : Ryan O'Hara
* Notice : Copyright (c) 2009 - OHARARP LLC
* : All Rights Reserved
* Date : 1/16/2009
* Version : 1.0
* Notes : This code was originally developed by Tim Box and ported to SF
* : by Ryan O'Hara
* : This handy little chip provides up to 128Mb -> 16MB of Flash memory
*****************************************************************************
}
Module M25P128
// OPTIONS
#option SHIFT_MAX = 8
// IMPORT MODULES
Include "SHIFT.BAS"
// DEFAULT MODULE OPTIONS - USER OPTIONS CAN OVERRIDE THESE VALUES...
#option M25P_CS = PORTC.2 // use 10k ohms pull-up resistor
#option M25P_CLK = PORTC.3 // use 10k ohms pull-down resistor
#option M25P_SDI = PORTC.4 //
#option M25P_SDO = PORTC.5 //
// Validate CS pin...
#if IsOption(M25P_CS) And Not IsValidPortPin(M25P_CS)
#error M25P_CS, "Invalid option. CS must be a valid port pin."
#endif
// Validate CLK pin...
#if IsOption(M25P_CLK) And Not IsValidPortPin(M25P_CLK)
#error M25P_CLK, "Invalid option. CLK must be a valid port pin."
#endif
// Validate SDI pin...
#if IsOption(M25P_SDI) And Not IsValidPortPin(M25P_SDI)
#error M25P_SDI, "Invalid option. DI must be a valid port pin."
#endif
// Validate SDO pin...
#if IsOption(M25P_SDO) And Not IsValidPortPin(M25P_SDO)
#error M25P_SDO, "Invalid option. DO must be a valid port pin."
#endif
// ======= M25P128 Instructions ==================================
Const
M25P_WREN = $06, ' Write M25PEnable
M25P_WRDI = $04, ' Write M25PDisable
M25P_RDID = $9F, ' Read Identification
M25P_RDSR = $05, ' Read STATUS Register
M25P_WRSR = $01, ' Write STATUS Register
M25P_Read = $03, ' Read Data Bytes
M25P_Read_Fast = $0B, ' Read Data Bytes At Higher Speed
M25P_PP = $02, ' PAGE Program
M25P_SE = $D8, ' Sector Erase
M25P_BE = $C7, ' Bulk Erase
M25P_Dummy = $FF ' Dummy Byte for Fast Read
// Variables used with commands to the M25P128
Dim M25PStatus As Byte
Dim M25PIndex As Byte ' Index Counter
Dim SRWD As M25PStatus.7 ' Status Register Write M25PDisable
Dim BP2 As M25PStatus.4 ' The Block Protect (BP2, BP1, BP0) bits
Dim BP1 As M25PStatus.3
Dim BP0 As M25PStatus.2
Dim WEL As M25PStatus.1 ' The Write M25PEnable Latch
Dim WIP As M25PStatus.0 ' The Write In Progress
// Bring port and pin options into the module...
Dim CS As M25P_CS.M25P_CS@
Dim CLK As M25P_CLK.M25P_CLK@
Dim SDI As M25P_SDI.M25P_SDI@
Dim SDO As M25P_SDO.M25P_SDO@
{
****************************************************************************
* Name : Disable(PRIVATE)
* Purpose : Disable the M25P128
****************************************************************************
}
Sub M25PDisable()
High(CS) ' M25PDisable the chip again
End Sub
{
****************************************************************************
* Name : Enable(PRIVATE)
* Purpose : Enable the M25P128
****************************************************************************
}
Sub M25PEnable()
Low(CS) ' M25PEnable the chip
End Sub
{
****************************************************************************
* Name : Write(PRIVATE)
* Purpose : Write M25PEnable the M25P128
****************************************************************************
}
Sub WriteEnable()
M25PEnable() ' M25PEnable the chip
Shift.Out(MSB_FIRST,M25P_WREN,8) ' Send the WREN command
M25PDisable() ' M25PDisable the chip again
End Sub ' All done return
{
****************************************************************************
* Name : WriteDisble(PRIVATE)
* Purpose : Write M25PDisable the M25P128
****************************************************************************
}
Sub WriteDisable()
M25PEnable() ' M25PEnable the chip
Shift.Out(MSB_FIRST,M25P_WRDI,8) ' Send the WRDI command
M25PDisable() ' M25PDisable the chip again
End Sub
{
****************************************************************************
* Name : ReadID
* Purpose : Read the 24 Bit Id of the M25P128
****************************************************************************
}
Public Function ReadId() As LongWord
M25PEnable() ' M25PEnable the chip
Shift.Out(MSB_FIRST,M25P_RDID,8) ' Send the RDID command
ReadId.BYTE0 = Shift.In(MSB_POST,8) ' readin the 24 bit ID data
ReadId.BYTE1 = Shift.In(MSB_POST,8)
ReadId.BYTE2 = Shift.In(MSB_POST,8) ' M25PDisable the chip again
M25PDisable()
End Function
{
****************************************************************************
* Name : ReadStatus(PRIVATE)
* Purpose : Read the Read Status Register of the the M25P128
****************************************************************************
}
Sub ReadStatus()
M25PEnable() ' M25PEnable the chip
Shift.Out(MSB_FIRST,M25P_RDSR,8) ' Send the RDSR command
M25PStatus = Shift.In(MSB_POST,8)
End Sub
{
****************************************************************************
* Name : ReReadStatus(PRIVATE)
* Purpose : ReRead the Read Status Register of the the M25P128
****************************************************************************
}
Sub ReReadStatus()
M25PStatus = Shift.In(MSB_POST,8)
End Sub
{
****************************************************************************
* Name : BulkErase
* Purpose : Erase the Entire M25P128 DATA - TAKES AWHILE TO OPERATE
****************************************************************************
}
Public Sub BulkErase()
ReadStatus() ' Check its Not in the middle of a current Write
While WIP = 1
ReReadStatus()
Wend
M25PDisable() ' M25PDisable To ensure the Read STATUS is stopped
DelayUS(4)
M25PEnable() ' M25PEnable the chip again
WriteEnable()
M25PEnable() ' M25PEnable the chip
Shift.Out(MSB_FIRST,M25P_BE,8) ' Sent the Bulk erase instruction
M25PDisable() ' M25PDisable the chip To start the erase
End Sub
{
****************************************************************************
* Name : SectorErase
* Purpose : Erase the One Sector of the M25P128 DATA
****************************************************************************
}
Public Sub SectorErase(pM25PDataAddress As LongWord)
ReadStatus() ' Check its not in the middle of a current write
While WIP = 1
ReReadStatus()
Wend
M25PDisable() ' M25PDisable to ensure the read status is stopped
DelayUS(4)
M25PEnable() ' M25PEnable the chip again
WriteEnable()
M25PEnable() ' M25PEnable the chip
Shift.Out(MSB_FIRST,M25P_SE,8) ' Sent the Sector erase instruction
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8) ' Send the address
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8) ' The whole sector that the address is in will be
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8) ' Erased
M25PDisable() ' M25PDisable the chip to start the erase
End Sub
{
****************************************************************************
* Name : WriteStatus
* Purpose : Make areas of the M25P128 Data read only
****************************************************************************
}
Sub WriteStatus(pM25PWriteByte As Byte)
WriteEnable()
M25PEnable() ' M25PEnable the chip
Shift.Out(MSB_FIRST,pM25PWriteByte,8)
M25PDisable() ' M25PDisable the chip again
End Sub
{
****************************************************************************
* Name : WriteByte
* Purpose : Write a single byte and the specified address
****************************************************************************
}
Public Sub WriteByte(pM25PDataAddress As LongWord,pM25PWriteByte As Byte)
ReadStatus() ' Check its not in the middle of a current write
While WIP = 1
ReReadStatus()
Wend
M25PDisable() ' M25PDisable to ensure the read status is stopped
DelayUS(4)
M25PEnable() ' M25PEnable the chip again
WriteEnable() ' Write M25PEnable the device
M25PEnable() ' M25PEnable the device
Shift.Out(MSB_FIRST,M25P_PP,8) ' Sent the Page Write instruction
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8) ' Send the address
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8)
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8)
Shift.Out(MSB_FIRST,pM25PWriteByte,8) ' Finaly the data
M25PDisable() ' Finish the write by bringing the CS line high
End Sub
{
****************************************************************************
* Name : WriteBytes
* Purpose : Write up to 255 bytes from the specified address
* CAUTION : OVERLAPPING A PAGE BOUNDARY CAN CAUSE SERIOUS ERRORS
****************************************************************************
}
Public Sub WriteBytes(pM25PDataAddress As LongWord,ByRef pM25PDataOut() As Byte)
ReadStatus() ' Check its not in the middle of a current write
While WIP = 1
ReReadStatus()
Wend
M25PDisable() ' M25PDisable to ensure the read status is stopped
DelayUS(4)
M25PEnable() ' M25PEnable the chip again
WriteEnable() ' Write M25PEnable the device
M25PEnable() ' M25PEnable the device
Shift.Out(MSB_FIRST,M25P_PP,8) ' Sent the Page Write instruction
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8) ' Send the address
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8)
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8)
For M25PIndex = 0 To Bound(pM25PDataOut) ' Via FRS0 send all the data requested
Shift.Out(MSB_FIRST,pM25PDataOut(M25PIndex),8)
Next
M25PDisable() ' Finish the write by bringing the CS line high
End Sub
{
****************************************************************************
* Name : ReadByte
* Purpose : Read a single byte at the specified address
****************************************************************************
}
Public Function ReadByte(pM25PDataAddress As LongWord) As Byte
ReadStatus() ' Check its not in the middle of a current write
While WIP = 1
ReReadStatus()
Wend
M25PDisable() ' M25PDisable to ensure the read status is stopped
DelayUS(4)
M25PEnable() ' M25PEnable the chip again
Shift.Out(MSB_FIRST,M25P_Read,8) ' Sent the data read instruction
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8) ' Send the address
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8)
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8)
ReadByte = Shift.In(MSB_POST,8) ' Read the byte in
M25PDisable()
End Function
{
****************************************************************************
* Name : ReadBytes
* Purpose : Read a multiple bytes byte at the specified address
****************************************************************************
}
Public Function ReadBytes(pM25PDataAddress As LongWord,ByRef pM25PDataIn() As Byte,pBytesToRead As LongWord) As Byte
If pBytesToRead > Bound(pM25PDataIn()) Then 'Check to make sure you do not overfill the array
pBytesToRead = Bound(pM25PDataIn())
EndIf
ReadStatus() ' Check its not in the middle of a current write
While WIP = 1
ReReadStatus()
Wend
M25PDisable() ' M25PDisable to ensure the read status is stopped
DelayUS(4)
M25PEnable() ' M25PEnable the chip again
Shift.Out(MSB_FIRST,M25P_Read_Fast,8) ' Sent the data read instruction
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8) ' Send the address
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8)
Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8)
Shift.Out(MSB_FIRST,M25P_Dummy,8)
For M25PIndex = 0 To pBytesToRead - 1
pM25PDataIn(M25PIndex) = Shift.In(MSB_POST,8)
Next
M25PDisable()
End Function
{
****************************************************************************
* Name : Init
* Purpose : Setup the Port Pins
****************************************************************************
}
Public Sub Init()
Output(CS)
Shift.SetClock(CLK,TRUE) //initialise shiftOUT clock pin, IDLE HIGH
Shift.SetInput(SDI)
Shift.SetOutput(SDO) //initialise shiftOUT pin
End Sub ]