Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

sram via spi problems

Status
Not open for further replies.

dsc

Member
Hi guys,

I'm using a 64k SRAM chip (23a640) with my PIC16f877A and I can't seem to get the bugger working properly. I'm also using an external EEPROM chip and that works flawlessly, so I though that using pretty much the same code to drive the SRAM would be a good idea, but seems like there's more to it than I thought.

Below is a SAVE/LOAD code for the SRAM chip, I'm using the same thing for EEPROM, the only difference being the enable/disable write code for the EEPROM chip.

Code:
SAVE_SRAM

	
	;Send the write sequence (WRITE)
		bcf     PORTC, 6		;clear the chip select (active)
		movlw	0x02			;load WRITE sequence (0000 0010 = WRITE)
		movwf	outbyte			;store in RAM location outbyte
		call	output	 		;call the SPI output routine
		movlw	0x00			;load high address byte
		movwf	outbyte			;store in RAM location outbyte
		call	output	 		;call the SPI output routine
		movf	addr,W	 		;move the address into w
		movwf	outbyte			;store in RAM location outbyte
		call	output	 		;call the SPI output routine
		movf	debug, W		;put the save value in W
		movwf   SSPBUF			;place data in send buffer
		bsf 	STATUS,	RP0		;select bank 1 
SR_loop1 
		btfss	SSPSTAT,BF		;has data been received?
		goto	SR_loop1		;loop if not received yet

		bcf 	STATUS,	RP0		;select bank 0		
		bsf     PORTC, 6        ;set negCS to 1 which means deselecting the chip when done
	
	;Perform data polling (RDSR bit 0)

SRAM_poll
		bcf     PORTC, 6		;clear the chip select (active)
		movlw	0x05			;load RDSR sequence (0000 0101 = RDSR)
		movwf	outbyte			;store in RAM location outbyte
		call	output	 		;read the data in status reg.
		movlw	0x00			;load up zero to send
		movwf	outbyte			;store in RAM location outbyte
		call	output	 		;read the data in status reg.
		bsf     PORTC, 6        ;set negCS to 1 which means deselecting the chip when done
		btfsc	rxdata,0	 	;test the WIP bit in status reg.
		goto	SRAM_poll		;WIP set, loop until WIP clear
		bsf     PORTC, 6        ;set negCS to 1 which means deselecting the chip when done

		incf	debug, F	
		bsf		PORTA, 2		;testing


		retlw	0x00

LOAD_SRAM

		

	;Send read sequence (READ), read address 0x55
		bcf     PORTC, 6		;clear the chip select (active)
		movlw	0x03			;load READ sequence (0000 0011 = READ)
		movwf	outbyte			;store in RAM location outbyte
		call	output	 		;call the SPI output routine
		
		movlw	0x00			;load high address byte
		movwf	outbyte			;store in RAM location outbyte
		call	output	 		;call the SPI output routine
	
		movf	addr,W			;move the address into w
		movwf	outbyte			;store in RAM location outbyte
		call	output			;call the SPI output routine
		movlw	0x00			;load high address byte
		movwf	outbyte			;store in RAM location outbyte
		call	output			;call output to read 1 byte
		bsf     PORTC, 6        ;set negCS to 1 which means deselecting the chip when done
		
	
		movf	rxdata, W
		movwf	test_spi		;copy rxdata to variable
		bcf		PORTA, 2		;testing

		retlw	0x00

The OUTPUT function is a short little thing:

Code:
output 
		movf    outbyte,W		;move outbyte into w
		movwf   SSPBUF			;place data in send buffer
		bsf 	STATUS,	RP0		;select bank 1 
loop1 
		btfss	SSPSTAT,BF		;has data been received?
		goto	loop1			;loop if not received yet
		bcf 	STATUS,	RP0		;select bank 0
		movf	SSPBUF,W		;empty the receive buffer
		movwf	rxdata			;put received byte into rxdata
		retlw 	0x00			;return from subroutine

SPI set up like this:

Code:
Set_SPI

		bsf	PORTC, 7		;set negCS to 1 which means deselecting the chip
		bsf	PORTC, 6		;set negCS to 1 which means deselecting the chip
		clrf    SSPCON			;clear SSP control register
  		movlw   0x30			;0011 0000 - Fosc/4, no collison, no overflow, 
  		movwf   SSPCON    		;SSPI, idle state for clock is high level
		bsf 	STATUS,	RP0		;select bank 1     
 		clrf    SSPSTAT 		;clear SSPSTAT
  		movlw   0x80			;1000 0000 - Input data sampled at end of data output time      
  		movwf   SSPSTAT
		bcf 	STATUS,	RP0		;select bank 0
		

		bsf		PCLATH, 3
		call	SET_SRAM &0x7ff		
		bcf		PCLATH, 3		
		
 		clrf	addr  			;clear addr variable

The PIC is hooked up to an LCD and I've used it to debug the code a bit, trying to write to a single address within the SRAM and read the value from it to display it on the screen. Seems like it's the SAVE function that fails, as occasionally I get something showing on the screen, which means I have to be putting something there in the first place. Any ideas what might be wrong? The chip is wired like in this tech note:

https://www.electro-tech-online.com/custompdfs/2010/02/01000a.pdf

the |CS pin is pulled up to 5V using a 10k. Again the same hook up is used on the EEPROM chip.

Any ideas would be welcome.

Regards,
dsc.
 
I'm not a PIC person, but the reference to the 5V pull up raises alarm bells that you are powering this chip with 5V. The 23a640 is a 3.3V chips with a max supply of 3.6V.

EDIT: Correction, that's the 23K640, the 23A640 is even lower max 1.95V.

Max input voltage is VCC +0.3V, so that would definitely be over spec on the CS line.
 
Last edited:
Hi Mark,

low voltage... well that really speaks for it self doesn't it? huge thanks for poiting that out, I think I might have fried two chips by driving them/powering them with 5V.

Am I correct to think that using a simple 10k/5.7k (4.7k + 1k) voltage divider will work well enough to get around 1.7V to the chip? I'm not sure how to calculate the load resistance of the SRAM chip, so I'm guessing with the resistance values a bit.

Regards,
dsc.
 
Hi again,

I've used 20k/10k voltage divs on all signals going to the SRAM chip and still nothing (also using a new SRAM chip, as the old one is probably fried). I've also simplified the code and removed the polling section which is not needed for SRAM writes (only in EEPROM).

Anyone thinks it might have something to do with the actual SPI setup that somehow works with the EEPROM, but doesn't work with SRAM?

Regards,
dsc.
 
...and you're powering it with 1.97V?

Yes, SPI is not a hard spec and there are variations. Clock and phase can be different for different slaves. It's possible it's not talking correctly to the SRAM. I hate to say it, but getting even a Logic Analyzer was a great move for me, since I don't need to guess at this stuff I can see exactly what is happening and usually pretty quickly figure out what's going wrong. I tend to deal with a lot of these interfaces, though.
 
Hi Mark,

well it's powered from a 5V supply through a 20k/10k devider, so it's 1.66V on the Vcc pin.

I will try changing the resistor values to something smaller to see if it makes a difference. I will also try to borrow an oscilloscope from work tomorrow to see what's going on.

Regards,
Tom
 
Well, I just took a look at the datasheet. What are you doing with the Hold pin? Other than that, this just needs hands on work and I'm too lazy to decypher the assembly code to try to match it to protocol the SRAM expects and see what you are doing.

And my analog electronics skills suck really bad, but I don't know if you can supply enough current through that resistor divider for the chip to actually function. Though it doesn't take much.
 
Hi Mark,

/HOLD pin is tied to 1.9V (using 10k), the whole chip is powered with 1.9V using voltage dividers based on 360Ω/220Ω resistors (5V coming from 7805 unit). I'm not too worried about current as SRAMs generally take very little current.

**broken link removed**

**broken link removed**

Above are two scopes showing READ and WRITE operations, they are correct and I'm still getting nothing on the serial data output pin on the SRAM (reading nothing). I have no idea why to be honest.

Regards,
dsc.
 
I'm having a hard time following what is what in those image, but SO is Slave Out and should be the data you are getting back. You don't write to SO, you write to SI.
I guess those are multiple bytes. It's impossible to see the clock and the data at that resolution. Data is clocked in on the rising edge of SCK. Zoom in and make sure your SI is not transitioning on the rising edge of SCK and the data is valid at that edge.
 
Sorry should've made it clearer, it's SDO not SO, it's the data going out from the PIC chip.

I agree resolution is a bit **** on these pics, but I've zoomed in and it all looks similar to the scopes in this note:

https://www.electro-tech-online.com/custompdfs/2010/02/01000a-1.pdf

Besides the same set of instructions (well with addition of Write enable/disable) works on the EEPROM, so I'm guessing the problem is on the hardware side ie. voltage on the SRAM chip or something similar.

Data is clocked in on the rising edge of SCK. Zoom in and make sure your SI is not transitioning on the rising edge of SCK and the data is valid at that edge.

Not really sure what part of the scope you are talking here.

Regards,
dsc.
 
MicroChip really decided to be confusingly different naming there I/O. For SPI, SO is supposed to be Slave Out and means the line where the slave outputs it's data. It's called the same on both the slave and the master. The full name is MISO (Master In/Slave Out). It makes it simpler since you just connect MOSI to MOSI and MISO to MISO, there's none of this swapping RX/TX like with a UART. I guess the just decided to toss that simplicity out the window.
 
Status
Not open for further replies.

Latest threads

Back
Top