CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Defining multiple SPI streams

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
pedrohenrique



Joined: 20 Jun 2008
Posts: 4

View user's profile Send private message

Defining multiple SPI streams
PostPosted: Fri Jun 20, 2008 1:38 pm     Reply with quote

Hi

I am trying to interface several slaves through the SPI bus. Each of the slaves requires a different mode (MODE 0 with 8 bits, MODE 1 with 16 bits and MODE 3 with 16 bits).
To do so I am defining 3 streams using the use spi statement, and communication using the spi_xfer command.

I have found that only the last use spi statement applies to all the code, and I can only interface the slave which the last statement matches (the others don't like the mode). If I change the order the same applies.

I would like to know if there is any way for me to define the streams in another fashion or if I can otherwise configure the bus prior to using it (while allowing me to still control the number of data bits)

Any help is greatly appreciated

Kind regards
Pedro Inácio
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jun 20, 2008 6:43 pm     Reply with quote

I did some testing for a few minutes here with vs. 4.074, and you are
correct. #use spi() with streams is not as flexible as we would wish.
It does not re-configure the hardware module when you use a different
stream.

It would be easier to use setup_spi() with spi_write() and spi_read(), etc.
Then you can call setup_spi() when you want to change the SPI mode or
the baud rate.
pedrohenrique



Joined: 20 Jun 2008
Posts: 4

View user's profile Send private message

PostPosted: Sat Jun 21, 2008 2:38 am     Reply with quote

Dear PCM Programmer

Thank you for your input. I am glad to know that it is not an error on my part as I can try and take another approach. I will try to use those commands as you suggest and will let you know how it goes.

Kind regards
Pedro Inácio
pedrohenrique



Joined: 20 Jun 2008
Posts: 4

View user's profile Send private message

PostPosted: Sat Jun 21, 2008 7:39 am     Reply with quote

Dear PCM Programmer

I followed your advice on the commands and was able to interface all the slave peripherals regardless of the order. I removed the use spi directives altogether.

Thank you very much for your help

Kind Regards
Pedro Inácio
bboone



Joined: 04 Jun 2014
Posts: 3
Location: United States

View user's profile Send private message

PostPosted: Mon Oct 05, 2015 10:38 am     Reply with quote

is this still an issue in 5.024?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Oct 05, 2015 12:09 pm     Reply with quote

What's your PIC ? I'll check it.
bboone



Joined: 04 Jun 2014
Posts: 3
Location: United States

View user's profile Send private message

PostPosted: Mon Oct 05, 2015 12:48 pm     Reply with quote

pic18F87K90
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Mon Oct 05, 2015 12:55 pm     Reply with quote

Software SPI, will give different speeds for defined streams. Different routines used for each transfer. For hardware, the port is configured once at the start of the code. The same applies with serial.
If only one stream is 'fast', you could set this up to use hardware, and the others to use software. Then just turn the SPI peripheral on/off when you want to use the software streams.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Oct 05, 2015 12:57 pm     Reply with quote

Code:
#include <18F87K90.h>
#fuses INTRC_IO, NOWDT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)

#use spi(SPI1, baud=1000000, mode=0, bits=8,  stream=spi_stream_0)
#use spi(SPI1, baud=2000000, mode=1, bits=16, stream=spi_stream_1)
#use spi(SPI1, baud=5000000, mode=3, bits=16, stream=spi_stream_2)

//=======================================     
void main()
{
int8 result_8;
int16 result_16;

result_8 = spi_xfer(spi_stream_0, 0x55);
result_16 = spi_xfer(spi_stream_1, 0x1234);
result_16 = spi_xfer(spi_stream_2, 0x5678);

while(TRUE);
}


The .LST file below shows that the compiler is setting up the hardware
SPI module for the particular stream, each time it talks to that stream.
This is with compiler vs. 5.024.
Code:

.................... result_8 = spi_xfer(spi_stream_0, 0x55);
000A4:  BCF    SSP1CON1.SSPEN
000A6:  MOVLW  40
000A8:  MOVWF  SSP1STAT
000AA:  MOVLW  20
000AC:  MOVWF  SSP1CON1
000AE:  MOVLW  55
000B0:  MOVWF  ??65535
000B2:  MOVLB  0
000B4:  BRA    0004
000B6:  MOVF   @01,W
000B8:  MOVFF  01,result_8
.................... result_16 = spi_xfer(spi_stream_1, 0x1234);
000BC:  BCF    SSP1CON1.SSPEN
000BE:  MOVLW  00
000C0:  MOVWF  SSP1STAT
000C2:  MOVLW  20
000C4:  MOVWF  SSP1CON1
000C6:  MOVLW  12
000C8:  MOVWF  ??65535+1
000CA:  MOVLW  34
000CC:  MOVWF  ??65535
000CE:  BRA    0016
000D0:  MOVF   @01,W
000D2:  MOVFF  02,result_16+1
000D6:  MOVFF  01,result_16
.................... result_16 = spi_xfer(spi_stream_2, 0x5678);
000DA:  BCF    SSP1CON1.SSPEN
000DC:  MOVLW  00
000DE:  MOVWF  SSP1STAT
000E0:  MOVLW  30
000E2:  MOVWF  SSP1CON1
000E4:  MOVLW  56
000E6:  MOVWF  ??65535+1
000E8:  MOVLW  78
000EA:  MOVWF  ??65535
000EC:  BRA    0036
000EE:  MOVF   @01,W
000F0:  MOVFF  02,result_16+1
000F4:  MOVFF  01,result_16
.................... 
.................... while(TRUE);
000F8:  BRA    00F8
.................... } 
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Mon Oct 05, 2015 1:07 pm     Reply with quote

That is good, and new then. I looked at this a few versions ago, and it only initialised once.

So implies that it should work for the original poster, if he switches to a newer compiler. Smile
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Tue Oct 06, 2015 7:37 am     Reply with quote

There is a piece here that might well cause problems....

Some of the different modes, will have the idle level on the lines change.
Now the code to setup the SPI, won't get called until you actually send a byte. Problem is that therefore, if your sequence is:

Deselect all chips
Select the one chip you want.
Output to the required port.

Since the chip is selected _before_ the byte is sent to the port, it'll see the wrong idle level at the start of the transaction. Problem.

If the idle levels do change, the only way to make it work would either be to program the peripheral yourself, or to use a 'dummy' byte. So:

Deselect all chips.
Send a dummy byte to the stream you are going to use. This then reprograms the peripheral and sets the correct idle levels.
Wait for this to send.
Now select the chip you want, and talk to this.

This way the chip is only selected after the lines have been taken over and set to the right levels.

This is only necessary if you are changing mode.
Cenatronics



Joined: 27 Nov 2006
Posts: 13

View user's profile Send private message

PostPosted: Thu Jun 04, 2020 9:56 am     Reply with quote

Ttelmah wrote:
There is a piece here that might well cause problems....

Some of the different modes, will have the idle level on the lines change.
Now the code to setup the SPI, won't get called until you actually send a byte. Problem is that therefore, if your sequence is:

Deselect all chips
Select the one chip you want.
Output to the required port.

Since the chip is selected _before_ the byte is sent to the port, it'll see the wrong idle level at the start of the transaction. Problem.

If the idle levels do change, the only way to make it work would either be to program the peripheral yourself, or to use a 'dummy' byte. So:

Deselect all chips.
Send a dummy byte to the stream you are going to use. This then reprograms the peripheral and sets the correct idle levels.
Wait for this to send.
Now select the chip you want, and talk to this.

This way the chip is only selected after the lines have been taken over and set to the right levels.

This is only necessary if you are changing mode.


Is this method also valid for the latest version (5.093)?

SNO
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Fri Jun 05, 2020 12:48 am     Reply with quote

There is an undocumented 'other way'. On I2C, there is a command
i2c_init for exactly this. So you can setup the two streams, using
'NOINIT', and then simply 'INIT' the one you actually want to use.
I thought it worth just testing to see if SPI might do the same.

It works:
Code:

#use spi(SPI1, mode=0, baud=100000, NOINIT, stream=SPI_MODE0)
#use spi(SPI1, mode=2, baud=100000, NOINIT,  stream=SPI_MODE2)
//setup two spi streams without init.

   spi_init(SPI_MODE0);
   //Now select mode 0
   output_low(CS1);
   spi_xfer(address);
   val=spi_xfer(0);
   output_high(CS1);
   //and talk to first chip 
   
   spi_init(SPI_MODE2);
   //Now the mode 2 chip
   output_low(CS2);
   spi_xfer(secondaddress);
   secondval=spi_xfer(0);
   output_high(CS2); 
   //and talk to this

It is correctly setting the chip to the two different modes and using
these.
Cenatronics



Joined: 27 Nov 2006
Posts: 13

View user's profile Send private message

PostPosted: Fri Jun 05, 2020 6:44 am     Reply with quote

Thanks for your comments.

SNO
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group