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 support@ccsinfo.com

SPI soft vs hardware usage in CCS

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



Joined: 08 Feb 2009
Posts: 4

View user's profile Send private message

SPI soft vs hardware usage in CCS
PostPosted: Mon Oct 12, 2009 12:14 am     Reply with quote

I have two processors I want to link with SPI.
16F886 as a master with hardware SPI.
12F675 as a slave with software SPI.
I haven't been really clear on the implementation with the documentation given in the CCS user guide.
I need help getting this started. Such as...
If I issue a command from the master, does the software SPI provide an interrupt with the #int_ssp?
If this does, after receiving the interrupt, can I grab the command with something like:
my_command = spi_xfer(); ?

Say I am asking for an ADC result that is going to be 16 bits. But the spi is set up as 8bit.
I get the interrupt for the command which is asking for the data.

Can I post the first byte by simply using the line:
spi_xfer(my_byte); ?

I understand that software spi is pretty slow, but how do I figure out what baud might work fine with the 12f675? I plan to use the 4Mhz internal clock.

The slave processor really doesn't have anything to do till it gets asked for ADC data. Then it will take some samples, average them and have 2 bytes to return to the master. I am trying to figure out the best method to interface this.
I am thinking like:
Issue a command to "get adc data".
The slave then starts this process.
The slave waits till another command is issued asking for a byte of the result. The slave posts it with spi_xfer and then waits. The master then asks for the second byte and we respond again with another spi_xfer.

I suppose this might be over simplified. But I haven't been able to find an example of hardware spi talking to software spi. Does anyone have this?
Thanks,
GregR
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Oct 12, 2009 11:27 am     Reply with quote

The 12F675 doesn't have an SSP module, so it can't be easily be used as
a hardware SPI slave or an i2c slave. None of the currently available
12F-series 8-pin PICs have an SSP module.

The problem is that SPI is a clocked protocol. If there is no hardware
support, then you need to do edge-detection with code. This is going
to be difficult if you want to do anything else besides just "camping on"
the SCLK pin in your slave PIC.

I think you could do it with the External interrupt pin. Connect SCLK
from the Master PIC to the INT_EXT pin in the 12F675. Assuming the
Master is using SPI Mode 0, then setup INT_EXT to interrupt on the
negative edge.

In Mode 0, data is clocked out of the Master on the negative edge.
It's sampled on the rising edge by the slave. You could emulate
this behavior by interrupting your slave on the negative edge of SCLK.
If the slave PIC is running at 4 MHz, it would take about 30 us to get
into the #int_ext routine, after the falling edge occurs. Then you could
read the SDI pin on your slave, and get the data bit. After 8 interrupts
you would have the incoming byte. Also, you could output data on
the SDO pin of the slave in the same interrupt.

Because it takes 30 us just to get into the #int_isr, and presumably
about 10 us to output data on the SDO pin, and another 10 us to input
data on SDI, and 30 us more to exit the isr, the "round trip" time is 80 us.
Realistically, the Master SCLK period should be greater than this, and
should be 100 us. So the SCLK frequency is 10 KHz.

That's too slow to be generated by the hardware SPI module in the
master PIC. Assuming a 4 MHz oscillator in the master, the largest
available divisor is 64, and this would give 62.5 KHz for SCLK.
That's too high for a software SPI slave. You could speed things up
in the slave by using #int_global. It would get rid of some of the
overhead in the CCS interrupt dispatcher. Using #int_global adds
complexity to the design but it could be done. Maybe if you used
#int_global and ran the slave PIC at 20 MHz, it give a fast enough
response time. The other option is to use software SPI in the Master.
Then you could run SCLK as slow as necessary.


I think using a software UART would be easier. Use #int_ext to
detect the start bit of an incoming byte to the 12F675. Read the bits
in the isr with getc().
groberts



Joined: 08 Feb 2009
Posts: 4

View user's profile Send private message

SPI soft vs hardware usage in CCS
PostPosted: Tue Oct 13, 2009 9:41 am     Reply with quote

Have you ever used the CCS software based SPI functions?
I understand what you are saying about trying to run totally thru programmed IO and manual monitoring. I don't want to do that if I don't have to. The CCS compiler appears to have a library function set for this but the details on how this really operates are pretty vague. I have asked the official CCS support about this. If I get a good answer, I'll post that.
GregR
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Oct 13, 2009 4:41 pm     Reply with quote

I haven't used software SPI with the #use spi() statement, so I made
a test program to see what it does. This is a software SPI slave on
pins A1, A2, A4, and A5. I compiled it with vs. 4.099.
Code:

#include<12F675.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,MCLR
#use delay(clock=4000000)

#use spi(Slave, Mode=0, DI=PIN_A1, DO=PIN_A2, CLK=PIN_A4, ENABLE=PIN_A5, BITS=8, MSB_FIRST)

//=======================
void main(void)
{
int8 data_received;

data_received = spi_xfer(0);

while(1);
}


Here's the .LST file with comments added. After looking at this code,
I think it would do what you need. Because there are bugs in the
TRIS in the startup code, you should manually set the correct TRIS
for the slave at the start of main(). That way, there won't be bus
contention between the master and slave PICs for very long. (just a
few microseconds). You can do this with a set_tris_a() statement.
Code:

... #use spi(Slave, Mode=0, DI=PIN_A1, DO=PIN_A2, CLK=PIN_A4, ENABLE=PIN_A5, BITS=8, MSB_FIRST)

// Check if we have 8 bits to send, or maybe less than 8.
000A:  MOVF   28,W  // #bits (number of bits to send)
000B:  SUBLW  08    // W = 8 - #bits
000C:  BTFSC  03.2 
000D:  GOTO   012   // Jump if #bits = 8

// If #bits is < 8, then left-justify the "byte to send" bits.
000E:  MOVWF  29
000F:  RLF    27,F
0010:  DECFSZ 29,F
0011:  GOTO   00F

// Setup correct TRIS for software SPI pins.
0012:  BSF    03.5
0013:  BSF    05.1  // TRISA.1 (SDI) = input
0014:  BCF    05.2  // TRISA.2 (SDO) = output
0015:  BSF    05.4  // TRISA.4 (SCLK)= input
0016:  BSF    05.5  // TRISA.5 (\SS) = input

// Load a bit counter variable with number of bits to send.
0017:  BCF    03.5
0018:  MOVF   28,W  // Get #bits
0019:  MOVWF  29    // Load #bits into bit counter

// This is the start of the bit sending loop.
// Set SDO based on msb of "byte to send".
001A:  BTFSS  27.7  // Test msb
001B:  BCF    05.2  // SDO = 0
001C:  BTFSC  27.7
001D:  BSF    05.2  // SDO = 1
001E:  RLF    27,F  // Rotate "byte to send" left by 1

// Wait in a loop until \SS = 0.  \SS is controlled by the Master PIC,
// so the slave (this PIC) is waiting for the Master to assert \SS.
001F:  BTFSC  05.5
0020:  GOTO   01F

// Wait in loop until SCLK = 1.  Again, the Master controls this.
0021:  BTFSS  05.4
0022:  GOTO   021

// Set lsb of received byte based on value of SDI pin.
// The slave (this PIC) tests the data bit which is coming
// from the Master.
0023:  RLF    21,F  // Rotate received byte left by 1
0024:  BTFSS  05.1  // Test SDI
0025:  BCF    21.0  // set lsb = 0
0026:  BTFSC  05.1  // Test SDI
0027:  BSF    21.0  // set lsb = 1

// Wait in loop until \SS = 0
0028:  BTFSC  05.5
0029:  GOTO   028

// Wait in loop until SCLK = 0
002A:  BTFSC  05.4
002B:  GOTO   02A

// Continue until all bits in SPI transfer are done
002C:  DECFSZ 29,F  // Decrement bit counter
002D:  GOTO   01A   // Jump to top of loop if not done yet

002E:  BCF    05.5  // Set \SS = 0  (Why ?  Probably a bug)
002F:  GOTO   04A (RETURN)
.................... 
.................... //=======================
.................... void main(void)
.................... { 
0030:  CLRF   04
0031:  MOVLW  1F
0032:  ANDWF  03,F

// Here's the start-up code for the software SPI pins.
// Note that the TRIS is mistakenly setup as if this PIC
// is an SPI master.  The compiler isn't looking at the
// Master/Slave parameter in the #use spi() statement.

0033:  BSF    03.5  // Bank 1
0034:  BSF    05.1  // TRISA.1 (SDI) = input
0035:  BCF    05.2  // TRISA.2 (SDO) = output

0036:  BCF    05.4  // TRISA.4 (SCLK) = output (*** Bug)
0037:  BCF    03.5  // Bank 0
0038:  BCF    05.4  // PORTA.4 (SCLK) = 0  (*** Bug)

0039:  BSF    03.5  // Bank 1
003A:  BCF    05.5  // TRISA.5 (\SS) = output (*** Bug)
003B:  BCF    03.5  // Bank 0
003C:  BSF    05.5  // PORTA.5 (\SS) = 1  (*** Bug)

// Disable Vref for the ADC.
003D:  BCF    1F.6
003E:  BSF    03.5

// Set Analog pins to all digital i/o.
003F:  BCF    1F.0
0040:  BCF    1F.1
0041:  BCF    1F.2
0042:  BCF    1F.3

// Disable the comparator.
0043:  MOVLW  07
0044:  BCF    03.5
0045:  MOVWF  19
.................... int8 data_received;
.................... 
.................... data_received = spi_xfer(0);
0046:  CLRF   27   // Byte to send = 0
0047:  MOVLW  08   
0048:  MOVWF  28   // Number of bits = 8
0049:  GOTO   00A
004A:  MOVF   21,W  // Get received byte
004B:  MOVWF  26    // Put it in 'data_received' variable
.................... 
.................... 
.................... while(1);
004C:  GOTO   04C
.................... }

These bugs have been reported to CCS support. Hopefully they will
be fixed when vs. 4.100 is released.
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