M2 series hardware SPI

GrahamGo

Senior Member
Here attached is a working code fragment. At the moment SPI master only.

I have a few questions.

1. The hardware SPI is as expected is very fast, however the chip select CS is relatively slow. Question is there anyway I can speed the CS (ENABLE) up? I have tried, but seem to be stuck to the speed of the interpreter. At 4m/z the /CS (ENABLE on the graph) active low time is about 1.04ms whilst the 8 bit data burst is only 120us (using the /64 clock rate). I realize adjusting the master clock from 4mh/z to 16mh/z or higher will make a big difference. But I was hoping to do better than this. Note for testing SDO is linked to SDI

Right now this hardware SPI is approx 10x quicker than the bit bang routine, but potentially could be another 10x quicker if the /CS speed can be improved.

2. Is there a way to get closer to the built in definitions. ie. like hspisetup spimode00, spimedium ; spi mode 0,0 ?
Compared to this clean code, my initialization method looks quite clunky, is there a better way?

3. Please, if there are any obvious coding improvements to be made please be critical.

4. I plan to try to modify this to work as an i2C slave - it seems doable.

Code:
; -------------------------------------------------------------------------
;|                                                                         
;|   Hardware SPI for M2 series                      Version 001  2/9/12
;|                                                                         
; -------------------------------------------------------------------------

#define test
#picaxe 14M2
#no_data ' reduce upload time
#terminal 4800

; -------------------------------------------------------------------------
;|                                                                        
;|   Project Description                                                
;|                                                                       
; -------------------------------------------------------------------------
{
; Work in progress.....Current requirement SPI driver for a graphics display
; SDI not required right now.
;
; Routines providing hardware SPI in Master mode,intended to replace the
; bit banging xxM2 routines. This method should be both quicker and more
; code efficient.
;
; Hopefully  this will work in the M2 multitasking mode and may be able
; to co-exist with I2C.
; 
; 14M2 pin connections 
; pin8 	B5	= SDO
; pin9	B4	= SDI
; pin10 B3	= SCL
; pin11 B2	= /CS
; 
; Note1 The CS select deselect is slow, the Buffer Full check does not seem
; to be required.
; 
; Notes For each byte sent @ 4mh/z the /CS active time is 1.04ms, 
; data time 120us using /64 clock rate.
; To Do:-
; Activate Alternative Pin mode.
; SPI read under interrupt
; Test alongside I2C
}

; --------------------------------------------------------------------------
;|                                                                     
;|   I/O and SPI Mode Definitions                                                   
;|                                                                    
; -------------------------------------------------------------------------
{

symbol APFCON0  = $5D
symbol APFCON1  = $5E
symbol SSP1BUF  = $91
symbol SSP1STAT = $94
symbol SSP1CON1 = $95
symbol CS      	= B.2

'Mode is a constant/variable to define the mode
symbol spimode00	= %00000000 '(mode 0,0 - TX idle-Active, input sampled middle of data time)
symbol spimode01	= %01000000 '(mode 0,1 - TX idle-Active, input sampled middle of data time
symbol spimode10	= %10000000 '(mode 1,0 - TX Active-idle, input sampled end of data time)
symbol spimode11	= %11000000 '(mode 1,1 - TX Active-idle, input sampled end of data time)

'Spispeed is a constant/variable to define the clock speed
symbol spifast		= %00100000 '(clock freq / 4 ) (= 1MHz with 4MHz resonator)
symbol spimedium 	= %00100001	'(clock freq / 16) (= 250kHz with 4MHz resonator)
symbol spislow 		= %00100010	'(clock freq / 64) (= 63 kHz with 4MHz resonator)

symbol SSP1STAT_BIT 	= bit0 ; Buffer full status bit
}
; --------------------------------------------------------------------------
;|                                                                     
;|   Variable Definitions                                                   
;|                                                                    
; -------------------------------------------------------------------------
{
Symbol V1					= b0					' scratch0
Symbol V2					= b1					' scratch1 
Symbol SpiMode 		= b2					'
Symbol SpiSpeed 	= b3					'
Symbol SPItxd 		= b4  				' Data to send to SPI bus
Symbol SPIrxd 		= b5  				' Received Data from SPI bus
}
; ---------------------------------------------------------------------------
;|     Testing section                                               
; --------------------------------------------------------------------------- 
#ifdef test 

SpiMode= SpiMode01 : SpiSpeed= SpiSlow 		' 
Gosub SPISETUP

Main:
	For V2= $85 to $127	
		SpiTxd = V2 : Gosub WriteToSPI
	 	SERTXD ("SP1Txd = ", #SpiTxd," SP1Rxd = ", #SpiRxd,CR,LF)
	 	Pause 1000
	Next V2
	Goto main
	
#endif	
; ---------------------------------------------------------------------------
;|     SPI Initialisation                                               
; --------------------------------------------------------------------------- 	
 
SpiSetup: ' b2 = spimode, b3 = spispeed

'B2 CS output, B3 SCK0 output, B4 SDI input, B5 SDO output     
							'76543210        
 let dirsB =	%11101111 	' set port pin directions
  
 		PeekSFR SSP1CON1, V1 : V1 = V1 AND %11011111
 		PokeSFR SSP1CON1, V1 	'turn off module, in case it was on
 		PeekSFR SSP1STAT, V1 : V1 = V1 AND %00111111 : V1 = V1 OR SpiMode
		PokeSFR SSP1STAT, V1 ' Set the SPImode
		PeekSFR SSP1CON1, V1 : V1 = V1 AND %11011100 : V1 = V1 OR SpiSpeed
    PokeSFR SSP1CON1, V1	'enable MSSP, idle is low,set clock rate
   
'    pokesfr APFCON1,0	'alternate pin config
 return
 
; ---------------------------------------------------------------------------
;|     SPI Transmit Routines                                                
; --------------------------------------------------------------------------- 

WriteToSPI:
	Low CS	
  pokesfr SSP1BUF,SpiTxd
'  Do while SSP1STAT_BIT=1 loop ' * see note 1
	High CS
  peeksfr SSP1BUF,SpiRxd
  return 
  
  end
M2 hardware SPI.JPG
 

srnet

Senior Member
Of this bit;

Low CS
pokesfr SSP1BUF,SpiTxd
' Do while SSP1STAT_BIT=1 loop ' * see note 1
High CS

How much time is down to the Low CS, High CS without the pokesfr ?

And even if it could be sped up a bit, will the SPI write time form a significant part of the overall program speed ?
 

GrahamGo

Senior Member
Of this bit;

Low CS
pokesfr SSP1BUF,SpiTxd
' Do while SSP1STAT_BIT=1 loop ' * see note 1
High CS

How much time is down to the Low CS, High CS without the pokesfr ?

And even if it could be sped up a bit, will the SPI write time form a significant part of the overall program speed ?
Good question, I only have had this working for an hour. Without, the pokesfr the time from Low CS to High CS is 0.42 ms, with pokesfr inserted its back to 1.047ms. The clock is (15 spaces) 8us each = 120us.

You are right in that perhaps a group of data encapsulated in one CS, might be quicker. I just wish (right now) that I could insert a little assembler code!

I am trying to drive a color graphics LCD and I simply want more speed than the bit bang way. I would also prefer to use the M2 series. From my pathetic number of posts you see the Picaxe is fairly new to me.
 

srnet

Senior Member
The colour Graphics LCD may well support burst writes.

I have used burst mode on an RF module to fill a FIFO buffer, you just leave CS low and each successive write went to the next location in the buffer. Same for a read.

However, when using the SPI interface in general, the CS low\high does not occupy a large overall part of the program. Even if you could eliminate the CS low\high delay completly you may well find that overall program speed does not improve very much at all.

Good work.
 
Top