Log in

View Full Version : Fast External Memory



prstein
- 2nd March 2010, 13:25
I need to keep track of two large arrays (1024 elements) of LONGs in a two-channel pulse height analyzer. As each value comes in I need to increment that element by one. For example, if ADC1 returns a value of 258 I need to get the value of MyLongArray[258] and add 1 to it.

I am currently doing this by streaming the data out to a PC and letting the PC do the work of storing and updating the array. I'd like to move this into a self-contained board instead.

The largest (RAM-wise) PBP-compatible PIC can only maintain one of these arrays so I'm thinking some external RAM might do the trick. I've tried using Ramtron serial F-RAM but it just takes too long. It appears that the I2C interface is too slow with PBP.

So I'm wondering if any of you folks have any suggestions. Is there a way to use SPI or I2C with PBP that lets me get up to or above 1 MHz? Alternately, could I bit-bang parallel memory in a high-speed fashion? Or is there some other way to accomplish the same goal?

Thanks,
Paul

Dave
- 2nd March 2010, 14:23
prstein, What is the frequency you are updating this ram histogram?

Dave Purola,
N8NTA

prstein
- 2nd March 2010, 14:30
prstein, What is the frequency you are updating this ram histogram?

Dave Purola,
N8NTA

Dave,

The timing for pulses coming in is random, but it might be as high as a few thousand per second all totaled up.

Paul

Art
- 2nd March 2010, 15:13
Is it a bad idea to use two of the pics you say are capable of maintaining one of the arrays?
I would think an 8 bit parallel interface between them could be that fast.
Definitely faster than SPI or I2C could do it.

Demon
- 2nd March 2010, 16:46
I'm not familiar with the F-RAM products. I just use chips like the AT24C1024 when I need external ram.

Sorry, I can't comment on speeds and interfacing right now, I'm still too rusty (been out of the loop too long). But you might want to take a look at those, they are common and cheap.

I'm just throwing this out in case it actually is helpful to you.


Features
• Low-voltage Operation
– 2.7 (VCC = 2.7V to 5.5V)
• Internally Organized 131,072 x 8
• 2-wire Serial Interface
• Schmitt Triggers, Filtered Inputs for Noise Suppression
• Bi-directional Data Transfer Protocol
• 400 kHz (2.7V) and 1 MHz (5V) Clock Rate
• Write Protect Pin for Hardware and Software Data Protection
• 256-byte Page Write Mode (Partial Page Writes Allowed)
• Random and Sequential Read Modes
• Self-timed Write Cycle (5 ms Typical)
• High Reliability
– Endurance: 100,000 Write Cycles/Page
– Data Retention: 40 Years
• 8-lead PDIP, 8-lead EIAJ SOIC, 8-lead LAP and 8-ball dBGATM Packages
Description
The AT24C1024 provides 1,048,576 bits of serial electrically erasable and programmable
read only memory (EEPROM) organized as 131,072 words of 8 bits each. The
device’s cascadable feature allows up to 2 devices to share a common 2-wire bus.
The device is optimized for use in many industrial and commercial applications where
low-power and low-voltage operation are essential. The devices are available in
space-saving 8-lead PDIP, 8-lead EIAJ SOIC, 8-lead Leadless Array (LAP), and 8-ball
dBGA packages. In addition, the entire family is available in 2.7V (2.7V to 5.5V)
versions.

prstein
- 2nd March 2010, 17:03
Art,

Not a bad idea, but that's a lot of pins (and capability) going to waste. I went and actually tested some code and I can't *quite* fit an array of 1024 LONGs, but I can break it down and get 1024 24-bit values.

This discussion started me looking around, and I'm thinking of picking up a few of these to try: http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&name=800-1433-5-ND

Robert,

Thanks for the input, but that device looks way too slow.

Best Regards,
Paul

rmteo
- 2nd March 2010, 17:14
Which PIC are you using? To use that static RAM, you will need one with an External Memory Bus - typically an 80-pin TQFP device.

aratti
- 2nd March 2010, 17:18
I need to keep track of two large arrays (1024 elements) of LONGs in a two-channel pulse height analyzer. As each value comes in I need to increment that element by one. For example, if ADC1 returns a value of 258 I need to get the value of MyLongArray[258] and add 1 to it.

I wonder why you need a long variable for this application? Once that an array has reached a count of 255 (one byte) statistically your pattern is not going to change much till when your long will overflow.


I am currently doing this by streaming the data out to a PC and letting the PC do the work of storing and updating the array. I'd like to move this into a self-contained board instead.

Surely you are doing the transfer via serial port, I don't see why a serial eeprom shouldn't be able to cope with the PC baud rate.

Al.

prstein
- 2nd March 2010, 18:34
Which PIC are you using? To use that static RAM, you will need one with an External Memory Bus - typically an 80-pin TQFP device.

Which PIC is yet to be decided. I work a lot with the 18F452 currently. I'm not opposed to using a larger PIC, but 40 pins ought to cover everything. I didn't think I needed to use an explicit memory bus, I presumed that I could just control the the interface directly. I suppose there would be speed disadvantages, though.

Best Regards,
Paul

prstein
- 2nd March 2010, 18:53
I wonder why you need a long variable for this application? Once that an array has reached a count of 255 (one byte) statistically your pattern is not going to change much till when your long will overflow.

I wish! On the front end is a radiation detector. Features within the array (or spectrum, if you will) become better defined with larger accumulations, and the statistics of the measurement do improve. Your right that a long variable is probably overkill, but a word variable is certainly too small. I've been working with 512-element arrays of 24-bit values (a word and a byte) and that is probably enough, but more is better right?


Surely you are doing the transfer via serial port, I don't see why a serial eeprom shouldn't be able to cope with the PC baud rate.
Al.

If it were just sending the data one way, as it does to the PC, you'd be correct. With serial memory the value at the location must be read, incremented, then re-written. I timed it out a couple of weeks ago and it was horrendously slow (relatively speaking) using I2CREAD and I2CWRITE.

Best Regards,
Paul

P.S. I manged not to say "don't call me Shirley." 8^)

languer
- 2nd March 2010, 19:38
The 18F452 should have plenty of memory; and all the banks can be accessed linearly.

For 1024 x 32-bit (long) words; a 32K serial EEPROM (e.g. 25AA320) would do. They can be clocked up to 10MHz (all in the HW SPI) which should be more than needed.

If you strictly need RAM (not long-term storage) then a serial RAM (e.g. 23A640) should do. Again SPI interface at speeds up to 20MHz.

I still think you should have more than enough storage on an 18F452.

mark_s
- 2nd March 2010, 20:53
Paul,

Have a look at this digital o-scope project. He uses a 16Kx9 fifo, maybe
something you can adapt to your application?

http://stephan.walter.name/files/publications/walter-dso-project.pdf

Regards

Demon
- 2nd March 2010, 23:27
...

Robert,

Thanks for the input, but that device looks way too slow.

Best Regards,
Paul


You can use page writes with the AT24C1024, could that help?

Features
• ...
• 256-byte Page Write Mode (Partial Page Writes Allowed)
• ...

Art
- 2nd March 2010, 23:47
If eight pins is too much you could use a 4 bit interface.
Still much faster than any I2C or serial EEPROM, particularly when you
have to wait 10ms after a write cycle.

If you read a value and then update that value, you are supposed to wait 10ms right there.

No reason why the pic acting as a RAM chip couldn't perform other tasks until
it is interrupted,
as long as there's enough RAM left in both chips to run the program as well.

I'm sure I've asked about external RAM on this board before (or on the old picbasic list).
It would be nice to have a fast pic compatible RAM chip, as well as an FPU
(another thing I've asked about).
I'm sad that the pic32 chips don't even have an FPU (something I expected).

languer
- 3rd March 2010, 00:21
Not to keep beating the same drum ...

I suggest you look at something like the 23A640. You can do sequential reads and sequential writes. And all this over SPI. At 10MHz (and four lines - max), a 32-bit transfer is 3.2uS (that should be pretty fast).

From datasheet:

If operating in Sequential mode, the data stored in the memory at the next address can be read sequentially by continuing to provide clock pulses. The internal Address Pointer is automatically incremented to the next higher address after each byte of data is shifted out. When the highest address is reached (1FFFh), the address counter rolls over to address 0000h, allowing the read cycle to be continued indefinitely.


If operating in Sequential mode, after the initial data byte is shifted in, additional bytes can be clocked into the device. The internal Address Pointer is automatically incremented. When the Address Pointer reaches the highest address (1FFFh), the address counter rolls over to (0000h). This allows the operation to continue indefinitely, however, previous data will be overwritten.

This, or something similar, should fit your needs.

prstein
- 3rd March 2010, 01:49
The 18F452 should have plenty of memory; and all the banks can be accessed linearly.

For 1024 x 32-bit (long) words; a 32K serial EEPROM (e.g. 25AA320) would do. They can be clocked up to 10MHz (all in the HW SPI) which should be more than needed.

If you strictly need RAM (not long-term storage) then a serial RAM (e.g. 23A640) should do. Again SPI interface at speeds up to 20MHz.

Doh! I didn't read enough of the manual! I somehow thought the hardware SPI and the USART shared the same pins and I didn't want to give up the USART. Now I see that it's different pins for that. I think you've pointed me to the solution. Thanks! And I apologize for not RTFMing thoroughly enough...


I still think you should have more than enough storage on an 18F452.

Sadly, no. Try compiling just this line for an 18F452:


MyArray var WORD[1024]

You get the message "ERROR: Unable to fit variable MyArray". It'd be awesome if you could show me I'm wrong here as well.

Best,
Paul

prstein
- 3rd March 2010, 01:53
Paul,

Have a look at this digital o-scope project. He uses a 16Kx9 fifo, maybe
something you can adapt to your application?

http://stephan.walter.name/files/publications/walter-dso-project.pdf

Regards

Sweet! Now I have some reading material for the evening. Even if it's not applicable to this project it looks very interesting.

Best,
Paul

prstein
- 3rd March 2010, 02:07
If eight pins is too much you could use a 4 bit interface.
Still much faster than any I2C or serial EEPROM, particularly when you
have to wait 10ms after a write cycle.

If you read a value and then update that value, you are supposed to wait 10ms right there.

No reason why the pic acting as a RAM chip couldn't perform other tasks until
it is interrupted,
as long as there's enough RAM left in both chips to run the program as well.

I'm sure I've asked about external RAM on this board before (or on the old picbasic list).
It would be nice to have a fast pic compatible RAM chip, as well as an FPU
(another thing I've asked about).
I'm sad that the pic32 chips don't even have an FPU (something I expected).

Hi Art,

I think the hardware SPI port might do it. I'm going to try these: http://www.mouser.com/ProductDetail/Ramtron/FM25C160-G/?qs=sGAEpiMZZMutXGli8Ay4kKy4ZTKwHbKi1pcR43MBP1g%3d . I don't care so much that they're non-volatile but they are much faster at writing than standard EEPROM.

Best,
Paul

languer
- 3rd March 2010, 17:07
I still think you should have more than enough storage on an 18F452.
Yeap, I must have been smoking something. No way to fit it in.

The part you highlighted is very cool (fast as SRAM, but non-volatile like SEEPROM). The 16k part will be great for 1024 WORDS, but will only fit half of the 1204 LONGS.

prstein
- 11th March 2010, 19:47
Just wanted to followup with news of success. After a comedy of wiring errors I finally got an F-RAM going using shiftin and shiftout. Once I confirmed that as working I changed the code to use the hardware SPI port. It is blazingly fast. I'm using running the 18F452 at 20MHz so I can "only" run with a 5MHz clock. Haven't actually timed it (yet) but I think it'll all work out just fine.

If there's any interest I'll post the code in the Code Examples section.

Thanks again, everyone, for all the suggestions.

Best Regards,
Paul

tenaja
- 12th March 2010, 01:52
I have used the i2c version of the FRAM and liked it. I had to switch when I needed more memory, though... it can cost over 10x the price of an atmel eeprom.

hankshone
- 17th March 2010, 15:01
Just wanted to followup with news of success. After a comedy of wiring errors I finally got an F-RAM going using shiftin and shiftout. Once I confirmed that as working I changed the code to use the hardware SPI port. It is blazingly fast. I'm using running the 18F452 at 20MHz so I can "only" run with a 5MHz clock. Haven't actually timed it (yet) but I think it'll all work out just fine.

If there's any interest I'll post the code in the Code Examples section.

Thanks again, everyone, for all the suggestions.

Best Regards,
Paul

Hi Paul: I am actually trying to figure out the hardware SPI module for F-RAM. So can you share your codes for that part? I appreciate it very much!!!

Vinson

prstein
- 17th March 2010, 16:38
Hi Paul: I am actually trying to figure out the hardware SPI module for F-RAM. So can you share your codes for that part? I appreciate it very much!!!

Vinson

Hello Vinson,

Here it is, warts and all...



'************************************************* ***************
'* Name : HW_FRAM_SPI_Test.pbp *
'* Notes : Demo of using hardware SPI port to read and write *
'* : a Ramtron FM25C106-G 16K 5V F-RAM chip. *
'* : *
'* : Assembled on an Olimex DEV-00021 40-pin *
'* : board from Sparkfun. *
'* : *
'* : Much information on working with the hardware *
'* : SPI was gleaned from Jeremy Grotte's *
'* : sdfshc32d.pbp file. *
'* : *
'* : Compiled using PBP v2.60L *
'* : *
'************************************************* ***************

' PIC18F452 DIP Package
' Pin Assignments
' Pin # Use Hookup
' 1 MCLR/VPP To Vdd through 4.7k resistor
' 2 RA0/AN0 n/c, reserved for analog input
' 3 RA1/AN1 n/c
' 4 RA2/AN2/VREF- n/c
' 5 RA3/AN3/VREF+ n/c
' 6 RA4/T0CKI n/c
' 7 RA5/AN4/SS n/c
' 8 RE0/RD/AN5 n/c
' 9 RE1/WR/AN6 n/c
' 10 RE2/CS/AN7 n/c
' 11 Vdd Power, +5V
' 12 Vss Ground
' 13 OSC1/CLKIN To 20MHz crystal
' 14 OSC2/CLKOUT To 20MHz crystal
' 15 RC0/T1OSO/T1CKI n/c
' 16 RC1/T1OSI/CCP2 n/c
' 17 RC2/CCP1 n/c
' 18 RC3/SCK/SCL to F-RAM SCK (pin 6)
' 19 RD0/PSP0 n/c
' 20 RD1/PSP1 n/c

' 21 RD2/PSP2 n/c
' 22 RD3/PSP3 FRAM_CS, to F-RAM CS (pin 1)
' 23 RC4/SDI/SDA SDI, to F-RAM SO (pin 2)
' 24 RC5/SDO SDO, to F-RAM SI (pin 5)
' 25 RC6/TX/CK TX; to MAX232A Pin 11 (goes out from pin 14 to DB9F pin 2)
' 26 RC7/RX/DT RX; to MAX232A Pin 12 (goes out from pin 13 to DB9F pin 3)
' 27 RD4/PSP4 n/c
' 28 RD5/PSP5 n/c
' 29 RD6/PSP6 n/c
' 30 RD7/PSP7 n/c
' 31 Vss Ground
' 32 Vdd Power, +5V
' 33 RB0/INT n/c
' 34 RB1 n/c
' 35 RB2 n/c
' 36 RB3/PGM n/c
' 37 RB4 n/c
' 38 RB5 n/c
' 39 RB6/PGC n/c
' 40 RB7/PGD n/c

'Notes
'-----
'SETUP RS232:
'Target device uses 115200 baud, 8 bits, 1 stop bit, flow control = none


'--------------------------------------------------------------------------------
'### Includes
'--------------------------------------------------------------------------------
'none


'--------------------------------------------------------------------------------
'### Defines
'--------------------------------------------------------------------------------
DEFINE LOADER_USED 1
DEFINE OSC 20
'Set receive register to receiver enabled
DEFINE HSER_RCSTA 90h
'Set transmit register to transmitter enabled, high speed BRGH
DEFINE HSER_TXSTA 24h
'Set baud rate
DEFINE HSER_BAUD 115200
'automatically clear any USART overflows
DEFINE HSER_CLROERR 1


'--------------------------------------------------------------------------------
'### Constants
'--------------------------------------------------------------------------------
TRUE CON 1
FALSE CON 0

OCWREN con %00000110 'F-RAM Write Enable Op-Code
OCRDSR con %00000101 'F-RAM Read Status Register Op-Code
OCWRSR con %00000001 'F-RAM Write Status Register Op-Code
OCREAD con %00000011 'F-RAM Read Memory Op-Code
OCWRITE con %00000010 'F-RAM Write Memory Op-Code


'--------------------------------------------------------------------------------
'### Aliases
'--------------------------------------------------------------------------------
SCK Var PORTC.3 ' SPI clock
SCK_TRIS Var TRISC.3 ' SPI clock direction

SDI Var PORTC.4 ' SPI data in
SDI_TRIS Var TRISC.4 ' SPI data in direction
SDO Var PORTC.5 ' SPI data out
SDO_TRIS Var TRISC.5 ' SPI data out direction

FRAM_CS Var PORTD.3 ' F-RAM chip select
FRAM_CS_TRIS Var TRISD.3 ' F-RAM chip select direction

WCOL Var SSPCON1.7 ' SSP write collision
SSPEN Var SSPCON1.5 ' SSP enable
SSPIF Var PIR1.3 ' SSP interrupt flag


'--------------------------------------------------------------------------------
'### Set Up Registers
'--------------------------------------------------------------------------------
ADCON1 = %10001110 'left justified, RA0/AN0 is analog input

'Set up SPI port
SSPSTAT = %01000000 ' Sample at middle of data output time, Transmit on idle rising edge of SCK
'SSPCON1 = %00000010 ' SPI master mode, clock = Fosc/64, Clock idle LOW.
'SSPCON1 = %00000001 ' SPI master mode, clock = Fosc/16, Clock idle LOW.
SSPCON1 = %00000000 ' SPI master mode, clock = Fosc/4, Clock idle LOW.
SSPEN = 1 ' Enable hardware SPI port.


'--------------------------------------------------------------------------------
'### Variables
'--------------------------------------------------------------------------------
nSPI_Data_In var byte
nSPI_Data_Out var byte
lVal var long
wFRAM_Addr var word


'--------------------------------------------------------------------------------
'### Initialization
'--------------------------------------------------------------------------------
FRAM_CS = 1 ' F-RAM chip not selected.
FRAM_CS_TRIS = 0' F-RAM chip select as output
SDO = 1 ' Start SPI data out high
SDO_TRIS = 0 ' SPI data out as Output
SDI_TRIS = 1 ' SPI data in as Input
SCK = 0 ' SPI clock idles low
SCK_TRIS = 0 ' SPI clock as Output

wFRAM_Addr = $000F ' Set an arbitray memory location
lVal = -5000 ' Set lVal to some starting point

pause 500

hserout["lVal initalized to ", dec lVal,13,10]

'Jump to Main program
goto main


'--------------------------------------------------------------------------------
'### Helper Functions
'--------------------------------------------------------------------------------
WriteSPI:
WCOL = 0
nSPI_Data_In = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = nSPI_Data_Out ' Send the byte.
If (WCOL) Then Return ' Check for write collision.
While (!SSPIF) ' Wait for send to complete.
Wend
Return

ReadSPI:
nSPI_Data_In = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While (!SSPIF) ' Wait for receive byte.
Wend
nSPI_Data_In = SSPBUF ' Get the byte.
return


'--------------------------------------------------------------------------------
'### MAIN PROGRAM
'--------------------------------------------------------------------------------
Main:
' Do a write
' Select the F-RAM
FRAM_CS = 0
' Begin with WREN
nSPI_Data_Out = OCWREN
gosub WriteSPI
' un-select the F-RAM
FRAM_CS = 1 ' only one Op-code per chip select!!!

' Select the F-RAM
FRAM_cs = 0
' Next send WRITE OpCode
nSPI_Data_Out = OCWrite
gosub WriteSPI

' Send two bytes of address (upper 5 bits are "don't care")
nSPI_Data_Out = wFRAM_Addr.HighByte '$00
gosub WriteSPI
nSPI_Data_Out = wFRAM_Addr.LowByte '$0f
gosub WriteSPI

' next byte(s) are data, address will increment with each write
nSPI_Data_Out = lVal.Byte0
gosub WriteSPI
nSPI_Data_Out = lVal.Byte1
gosub WriteSPI
nSPI_Data_Out = lVal.Byte2
gosub WriteSPI
nSPI_Data_Out = lVal.Byte3
gosub WriteSPI
' un-select the F-RAM
FRAM_CS = 1

' do a read
FRAM_CS = 0
' Begin by sending the read OpCode
nSPI_Data_Out = OCREAD '=READ command
gosub WriteSPI

' Send two bytes of address (upper 5 bits are "don't care")
nSPI_Data_Out = wFRAM_Addr.HighByte
gosub WriteSPI
nSPI_Data_Out = wFRAM_Addr.LowByte
gosub WriteSPI

' Now read in the value one byte at a time
gosub ReadSPI 'one byte into nSPI_Data_In
lVal.Byte0 = nSPI_Data_In
gosub ReadSPI 'one byte into nSPI_Data_In
lVal.Byte1 = nSPI_Data_In
gosub ReadSPI 'one byte into nSPI_Data_In
lVal.Byte2 = nSPI_Data_In
gosub ReadSPI 'one byte into nSPI_Data_In
lVal.Byte3 = nSPI_Data_In
FRAM_CS = 1

hserout["lVal=",dec lVal,13,10];

' Add one and write it back to the same location
lVal = lVal + 1
goto Main


Let us know if there are questions or difficulties.

Best Regards,
Paul

hankshone
- 18th March 2010, 20:09
Thanks Paul for your shared codes!!! It is great.
I did the same test, but used PIC16LF877(3.0V) and FM25V10(3.0V,1Mbit). I think the communication is the same, only with some minor modifications. I spent almost one day on it,still get no result yet.... Can you help me to check if there is anything wrong with it?
Thanks!


'************************************************* ***************
'* Name : HARDWARE_SPI_FRAM TEST.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2010 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 3/17/2010 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************
'************************************************* ***************


Define OSC 10
'INCLUDE "modedefs.bas"
DEFINE LOADER_USED 1
Define LCD_DREG PORTD
Define LCD_DBIT 4
Define LCD_RSREG PORTE
Define LCD_RSBIT 0
Define LCD_EREG PORTE
Define LCD_EBIT 1


Low PORTE.2 ' LCD R/W line low (W)
ADCON1 = %10000010 ' Set PORTA analog and right justify result
Pause 500 ' Wait .5 second

Low PORTE.2 ' LCD R/W line low (W)
ADCON1 = %10000010 ' Set PORTA analog and right justify result
Pause 500 ' Wait .5 second

Ticks VAR word ' Tick count (61 ticks = 1 sec)
Hour VAR byte ' Hour variable
Minute VAR byte ' Minute variable
Second VAR byte ' Second variable
Disp VAR byte ' Disp = 1 to update display

' Interrup handling bits
GIE var INTCON.7
PEIE var INTCON.6
TMR2IE VAR PIE1.1
TMR2ON VAR T2CON.2
TMR2IF VAR PIR1.1


' Definations for the SPI communication protocal
'------------------------------------------------------------------
'TRISB.5=0 ' This is for the CS PIN
FM_CS VAR PORTA.5 ' SPI FRAM CHIP CS PIN
FM_CS_TRIS VAR TRISA.5 ' SPI FRAM CHIP CS PIN DIRECTION

SCK VAR PORTC.3 ' SPI CLOCK
SCK_TRIS VAR TRISC.3 ' SPI CLOCK PIN DIRECTION CONTROL
SDI VAR PORTC.4 ' SPI DATA IN
SDI_TRIS VAR TRISC.4 ' SPI DATA IN PIN DIRECTION
SDO VAR PORTC.5 ' SPI DATA OUT PIN
SDO_TRIS VAR TRISC.5 ' SPI DATA OUT PIN

WCOL VAR SSPCON.7 'SSP WRITE COLLISION
SSPEN VAR SSPCON.5 'SSP ENABLE
SSPIF VAR PIR1.3 'SSP INTERRUPT FLAG
'---------------------------------------------------------------------

'-----------------------A/D setups --------------------------------------------
'Define ADC_BITS 10 ' Set number of bits in result
'Define ADC_CLOCK 2 ' Set clock source (3=rc)
'Define ADC_SAMPLEUS 20 ' Set sampling time in uS
'TRISA = %11111111 ' Set PORTA to all input
'ADCON1 = %10000010 ' Set PORTA analog and right justify result
'-------------------------------------------------------------------------------

'-------------SPI PORT REGISTERS SETUP----------------------------------------
SSPSTAT=%01000000 ' SAMPLE AT THE MIDDLE OF DATA OUTPUT TIME, TRANSMIT ON IDLE RISING EDGE OF SCK
SSPCON=%00100000 ' SPI MASTER MODE, CLOCK=Fosc/4 ENABLE HARDWARE SPI PORT
SSPEN=1 ' ENABLE HARDWARE SPI PORT
'-------------------------------------------------------------------------------

'---VARIABLES FOR THE ADDRESS AND DATA MANAGEMENT-------------------------------
'TX_LEN CON 1 'SENDING DATA LENGTH
TX_BUFF var byte'[TX_LEN] 'SENDING DATA ARRAY
'RX_LEN CON 1 'RECEIVING DATA LENGTH
RX_BUFF var byte'[RX_LEN] 'RECEIVING DATA ARRAY

ADD VAR WORD 'ADDRESS FOR THE MOMEORY(LOW 16BITS)
BLOCK0 VAR BYTE 'HIGH EIGHT BITS OF MEMORY ADDRESS
BLOCK1 VAR BYTE 'HIGH EIGHT BITS OF MEMORY ADDRESS
'-------------------------------------------------------------------------------

'-------------INITIALIZATION--------------------------------------------------
FM_CS=1 'FRAM CHIP DISABLED
FM_CS_TRIS=0 'OUTPUT
SDO=1 'START SPI PIN WITH HIGH
SDO_TRIS=0 'OUTPUT
SDI_TRIS=1 'INPUT


BLOCK0=%00000000;
BLOCK1=%00000001;

add=0;
B0 Var byte
b0=100;
X1 VAR BYTE
X2 VAR BYTE
X3 var BYTE
X4 var BYTE

'Delay VAR byte ‘ Used to Debounce button
'TRISA = 0 ‘ PORTA is output
'TRISB = 3 ‘ RB0,RB1 are inputs
'CMCON = 7 ‘ PORTA digital I/O
'PAUSE 500 ‘ Wait 0.5sec for LCD to initialize
'
' Clear Hour, Minute, Second and Ticks to zero
'
Hour = 0
Minute = 0
Second = 0
Ticks = 0
'

T2CON=%01001100 ' Set the prescaler to 1, and postscale to 10

ON INTERRUPT GOTO ISR ' ISR routine
'PR2=156 ' Set PR2 Register 10ms for timer2
'PR2=249 ' Set PRS2 Register
PR2=224' Set PR2 Resiger for 1ms timer2
GIE=1
PEIE=1
TMR2IE=1'Enable the Timer2 interrupt.
TMR2ON=1'


' Defines for the SPI-Control Registers
'-------------------------------------------------------------------------------------
TRUE con 1;
FALSE CON 0;

CONT_WREN CON %00000110 'F-RAM WRITE ENBALE OP-CODE
CONT_RDSR CON %00000101 'F-RAM READ STATUS REIGSTER OP-CODE
CONT_WRSR CON %00000001 'F-RAM WRITE STATUS REGISTER OP-CODE
CONT_READ CON %00000011 'F-RAM READ MOMEORY OP-CODE
CONT_WRITE CON %00000010 'F-RAM WRITE MEMORY OP-CODE
'-------------------------------------------------------------------------------------

LOOP:


'-------Write the OP-CODE and the three Bytes of address-----
FM_CS=0
TX_BUff=cont_WREN
gosub writespi
fm_cs=1

fm_cs=0
tx_buff=cont_write
gosub writespi
'-----send three bytes of address-------------
tx_buff=block0;
gosub writespi
tx_buff=add.byte1
gosub writespi
tx_buff=add.byte0
gosub writespi

'----------------------Write the first four bytes the desired data--------------

tx_buff=$02
gosub writespi
tx_buff=$03
gosub writespi
tx_buff=$04
gosub writespi
tx_buff=$05
gosub writespi
FM_CS=1


ADD=0

'----------------------Read the four bytes------------------------------------
fm_cs=0;
tx_buff=cont_read
gosub writespi
'------------------Sending three byts of address---------------------------
tx_buff=block0;
gosub writespi
tx_buff=add.byte1
gosub writespi
tx_buff=add.byte0
gosub writespi
'-----------------Read data into the variables-------------------------------
gosub readspi
x1=rx_buff
gosub readspi
x2=rx_buff
gosub readspi
x3=rx_buff
gosub readspi
x4=rx_buff


'hserout [dec4 hour];
'hserout [dec4 Minute];
'hserout [dec4 Ticks];
'hserout [hex ];
'hserout [dec4 ];
'hserout [dec4 ];
'hserout [dec4 ];




IF Disp = 1 THEN
LCDOUT $FE, 2
LCDOUT hex X1, ":",hex X2, ":",hex x3,":",dec4 Ticks
PAUSE 20
ENDIF
Disp = 0
'PAUSE 1000
GOTO LOOP


'-----------------Sub routines for the SPI write and read-----------------------
WriteSPI:
WCOL=0
Rx_buff=SSPBUF ' CLEAR THE BUFFER
SSPIF=0 ' CLEAR THE INTERRUP FLAG
SSPBUF=tx_buff ' SEND THE BYTE
IF(wcol) THEN RETURN
WHILE(!SSPIF)
WEND
SSPIF=0;
RETURN

ReadSPI:
rx_buff=SSPBUF ' Clear the buffer
SSPIF=0 ' Clear the interrup flag
SSPBUF=0 ' Shift out a dummy byte What is this?
while(!sspif) ' wait for receive byte
wend
rx_buff=SSPBUF ' Get the byte
return







DISABLE
ISR:
'pause 3
'pauseus 400
'TMR2ON=0' TURN OFF TMR2
Ticks = Ticks + 1
'IF Ticks < 4 THEN NoUpdate

'
' 1 second has elapsed, now update seconds and if necessary minutes and hours.

'
if Ticks=1000 then
ticks=0

Second = Second + 1 ' Update second
IF Second = 60 THEN
Second = 0
Minute = Minute + 1 ' Update Minute
IF Minute = 60 THEN
Minute = 0
Hour = Hour + 1 ' Update Hour
IF Hour = 24 THEN
Hour = 0
ENDIF
ENDIF
ENDIF
endif
Disp = 1 ' Set to update display
'
' End of time update
'
NoUpdate:
TMR2IF=0 ' Re-enable TMR2 interrupts
Resume
ENABLE ' Re-enable interrupts
END
END ' End of program

hankshone
- 18th March 2010, 20:59
Just wanted to followup with news of success. After a comedy of wiring errors I finally got an F-RAM going using shiftin and shiftout. Once I confirmed that as working I changed the code to use the hardware SPI port. It is blazingly fast. I'm using running the 18F452 at 20MHz so I can "only" run with a 5MHz clock. Haven't actually timed it (yet) but I think it'll all work out just fine.

If there's any interest I'll post the code in the Code Examples section.

Thanks again, everyone, for all the suggestions.

Best Regards,
Paul

Actually I could use SHIFTIN and SHIFTOUT for accessing the F-RAM memory, as you told, it is a "comedy" wiring error, it seems like totally reversed. But for hardware SPI, I think the MISO,MOSI connection should be followed, right? In your code, it is connected like this.

Vinson

prstein
- 18th March 2010, 21:04
Thanks Paul for your shared codes!!! It is great.
I did the same test, but used PIC16LF877(3.0V) and FM25V10(3.0V,1Mbit). I think the communication is the same, only with some minor modifications. I spent almost one day on it,still get no result yet.... Can you help me to check if there is anything wrong with it?
Thanks!

One Mbit? Now I have chip envy.

It looks like you need to add "FM_CS=1" right before the line "IF Disp = 1 THEN". The F-RAM never gets un-selected after the read.

It couldn't be that simple, could it? If that's not it please provide detail about what it is and is not doing correctly. If all else fails make sure it works using SHIFTIN and SHIFTOUT. If that fails as well use an o-scope to confirm ALL of the pins on the F-RAM are in their proper states.

Best Regards,
Paul

hankshone
- 18th March 2010, 21:13
One Mbit? Now I have chip envy.

It looks like you need to add "FM_CS=1" right before the line "IF Disp = 1 THEN". The F-RAM never gets un-selected after the read.

It couldn't be that simple, could it? If that's not it please provide detail about what it is and is not doing correctly. If all else fails make sure it works using SHIFTIN and SHIFTOUT. If that fails as well use an o-scope to confirm ALL of the pins on the F-RAM are in their proper states.

Best Regards,
Paul

Thanks Paul:-)
Really it is not quite easy. Last time it took me several days to find out the problem with SHIFTIN SHIFTOUT. I am sure the chip is working with those commands. But you know it is too slow... That's why I am switching to use the the hardware SPI to make it faster...
I will test it see what I can get..

prstein
- 18th March 2010, 21:14
Actually I could use SHIFTIN and SHIFTOUT for accessing the F-RAM memory, as you told, it is a "comedy" wiring error, it seems like totally reversed. But for hardware SPI, I think the MISO,MOSI connection should be followed, right? In your code, it is connected like this.

The only thing I don't like about SHIFTIN/SHIFTOUT is that they are so slow. But following advice from another thread (several threads actually) about SPI I used them to make sure everything was working in some fashion before I stepped up to the hardware SPI. Reversing the MISO/MOSI connections was just one of the many errors I started with. (I also spent an hour trying to figure out why I couldn't get *any* response from the F-RAM; turns out I hadn't actually installed the chip yet!)

Best Regards,
Paul

Normnet
- 18th March 2010, 22:06
The fastest memory I know of would be SRAM parallel.
Just inc the PIC port in parallel with the SRAM to inc the memory address.
Fastest PIC interface is setting a port, faster than SPI etc.

Just search Digikey for SRAM then Parallel for ns transfer time memory.

Norm

hankshone
- 18th March 2010, 22:12
One Mbit? Now I have chip envy.

It looks like you need to add "FM_CS=1" right before the line "IF Disp = 1 THEN". The F-RAM never gets un-selected after the read.

It couldn't be that simple, could it? If that's not it please provide detail about what it is and is not doing correctly. If all else fails make sure it works using SHIFTIN and SHIFTOUT. If that fails as well use an o-scope to confirm ALL of the pins on the F-RAM are in their proper states.

Best Regards,
Paul

Still with no results... The reads I get for the four variables are all zeros. I mean X1 to X4.It seems like there are response from SDO. But never get anything in SDI from the os-scope. It is weird...

languer
- 18th March 2010, 22:21
This may help for HW SPI (From 877A datasheet):
"Any write to the SSPBUF register during transmission/reception of data will be ignored and the write collision detect bit, WCOL (SSPCON<7>), will be set. User software must clear the WCOL bit so that it can be determined if the following write(s) to the SSPBUF register completed successfully."

The following:

WriteSPI (read-modify-write):
WCOL=0
Rx_buff=SSPBUF ' CLEAR THE BUFFER
SSPIF=0 ' CLEAR THE INTERRUP FLAG
SSPBUF=tx_buff ' SEND THE BYTE
IF(wcol) THEN RETURN
WHILE(!SSPIF)
WEND
SSPIF=0;
RETURN

ReadSPI:
rx_buff=SSPBUF ' Clear the buffer
SSPIF=0 ' Clear the interrup flag
SSPBUF=0 ' Shift out a dummy byte What is this?
while(!sspif) ' wait for receive byte
wend
rx_buff=SSPBUF ' Get the byte
return

Can be changed to this:

WriteSPI (write-receive-read):
SSPIF=0 ' CLEAR THE INTERRUP FLAG
WCOL=0 ' CLEAR COLLISION BIT BEFORE WRITING TO SPI
SSPBUF=tx_buff ' SEND THE BYTE
WHILE(!SSPIF) ' WAIT FOR 8-BITS TO BE CLOCKED-OUT/CLOCKED-IN - THIS HAPPENS SIMULTANEOUSLY
WEND
Rx_buff=SSPBUF ' STORE RECEIVED DATA
SSPIF=0 ' CLEAR THE INTERRUP FLAG
RETURN

ReadSPI:
SSPIF=0 ' CLEAR THE INTERRUP FLAG
WCOL=0 ' CLEAR COLLISION BIT BEFORE WRITING TO SPI
SSPBUF=0 ' SEND/CLOCK-OUT DUMMY BYTE TO CLOCK-IN RECEIVED BYTE
WHILE(!SSPIF) ' WAIT FOR 8-BITS TO BE CLOCKED-OUT/CLOCKED-IN - THIS HAPPENS SIMULTANEOUSLY
WEND
Rx_buff=SSPBUF ' STORE RECEIVED DATA
SSPIF=0 ' CLEAR THE INTERRUP FLAG
return

hankshone
- 19th March 2010, 00:42
The only thing I don't like about SHIFTIN/SHIFTOUT is that they are so slow. But following advice from another thread (several threads actually) about SPI I used them to make sure everything was working in some fashion before I stepped up to the hardware SPI. Reversing the MISO/MOSI connections was just one of the many errors I started with. (I also spent an hour trying to figure out why I couldn't get *any* response from the F-RAM; turns out I hadn't actually installed the chip yet!)

Best Regards,
Paul

As I found out the reads are all zeros, I use os-scope to track the signals and found out that there is totally no signals out in SCK, therefore no SDI because the master is not generating clocks. the SDO has some data out which I could not understand...So I am think if the MCU hardware got any problem.. or the MSSP module was not running?...it is really a torture...
.....
Vinson

hankshone
- 19th March 2010, 01:10
The only thing I don't like about SHIFTIN/SHIFTOUT is that they are so slow. But following advice from another thread (several threads actually) about SPI I used them to make sure everything was working in some fashion before I stepped up to the hardware SPI. Reversing the MISO/MOSI connections was just one of the many errors I started with. (I also spent an hour trying to figure out why I couldn't get *any* response from the F-RAM; turns out I hadn't actually installed the chip yet!)

Best Regards,
Paul

Just follow up with the my test. It is interesting that because I didn't specify the SCK's direction which killed the engine for SPI. Right now it is working. A little tricky problem, and anyway I appreciate your help very much!!!

prstein
- 19th March 2010, 01:22
As I found out the reads are all zeros, I use os-scope to track the signals and found out that there is totally no signals out in SCK, therefore no SDI because the master is not generating clocks. the SDO has some data out which I could not understand...So I am think if the MCU hardware got any problem.. or the MSSP module was not running?...it is really a torture...
.....
Vinson

Torture? If it were easy it wouldn't be nearly as much fun...

So no clock signals. SCK is on PORTC.3, which the datasheet says defaults to an input. You'll need to add "SCK_TRIS=0".

One other thing that jumped out at me is that the 16LF877 is only rated for 4MHz and you are using 10MHz according to your defines. Could that also be a source of trouble?

I hope you also took languer's suggestions. I'm pretty sure he's sharper than me...

Best Regards,
Paul

prstein
- 19th March 2010, 01:33
Whoops, looks like you got it first! The rated speed (4MHz) might still be an issue...

hankshone
- 19th March 2010, 01:58
Whoops, looks like you got it first! The rated speed (4MHz) might still be an issue...

It works fine at 10MHz. So I don't think that will introduce problem. the memory writing speed goes up a lot! I will try his codes tomorrow..also looks interesting. anyway thanks for u guys' help!