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 PIC16F15356

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



Joined: 12 Oct 2020
Posts: 44

View user's profile Send private message

SPI PIC16F15356
PostPosted: Mon Dec 18, 2023 8:58 am     Reply with quote

Hi all, hoping someone can shed some light on an SPI comms issue I'm having between two PIC16F15356, one configured as a Master, and one as Slave. The master is configured as below;

Code:

#pin_select SCK1OUT = PIN_C3
#pin_select SDI1 = PIN_C4
#pin_select SDO1 = PIN_C5

#use spi(STREAM=SPI1, MASTER, SPI1, BAUD=100000)


And the slave configuration:

Code:

#pin_select SS1IN  = PIN_A5
#pin_select SCK1IN = PIN_C3
#pin_select SDI1   = PIN_C5
#pin_select SDO1   = PIN_C4

#use spi(STREAM=SPI, SLAVE, SPI1)


The master makes the following call (you can see I already attempt a fixed value send for debugging, instead of sending 'real' data);

Code:

//for(Index = 2 ; Index < 5 ; Index++)
    //spi_xfer(SPI1, RS485RxdFrameBuffer[Index]);
spi_xfer(SPI1, 0x10);


And my Slave ISR is being triggered on SPI data reception, however this code...:
Code:

SPIRxdFrameBuffer[Index++] = spi_xfer_in();

...does not pull the value out of the SPI buffer, and my reception array remains populated with only zero values.

I have three Slave MCUs on the SPI bus, (as yet two have no code running on them), is it a possible issue that all my devices will need their SPI pins to be configured for data to be received, or am I missing something more basic?

Any help would be greatly appreciated!
Backfire



Joined: 12 Oct 2020
Posts: 44

View user's profile Send private message

PostPosted: Mon Dec 18, 2023 9:33 am     Reply with quote

Oh, it's also worth noting that I'm handling the Chip Select lines also, so this is a more full snippet of the call;

Code:

if(target == slave1)
    output_low(slave1_cs);
if(target == slave2)
    output_low(slave2_cs);

// Call to SPI xfer

output_high(slave1_cs);
output_high(slave2_cs);
Ttelmah



Joined: 11 Mar 2010
Posts: 19231

View user's profile Send private message

PostPosted: Mon Dec 18, 2023 11:17 am     Reply with quote

First thing, both your #use statement need BITS=8. By default the SPI
is setup to do a 32bit transfer.
Then specify the stream name on you spi_xfer_in,
Then have a dummy variable, and change your write to:

dummy=spi_xfer(SPI1, 0x10);

Problem without this is the spi_xfer loads the value to send, and returns
immediately. This means your CS may go off too soon. (depends on
compiler verson....). This is a fault that exists with some versions.

One other important thing. On chips with PPS, most don't need TRIS
tp be setup, since selecting the PPS device, overrides the TRIS. Yours
is one of the ones that does. Hence you need to set this correctly for
all the pins selected. So output_float on the input pins and output_drive
on the output pins. It may be that the CLK pin is correctly being driven,
but the SDO pin is not. Worth just trying manually setting these.
This is one that is only needed on a very few chips.... Sad
Backfire



Joined: 12 Oct 2020
Posts: 44

View user's profile Send private message

PostPosted: Tue Dec 19, 2023 4:21 am     Reply with quote

Hi, and thanks for the input Ttelmah.

Seemingly the same issue is persistent though, I have added back in BITS=8, (I actually had this included in earlier code attempts, I stripped it out trying to see issues)...

I also added the dummy variable as you suggest for the write function call, and manually set;
Master: Drive - SCK1, SDO1 | Float - SDI1
Slave: Drive - SDO1 | Float - SDI1, SCK1IN, SS1IN
using the output_drive/float functions as appropriate on the pins in my device setup.

I still get the ISR triggering, but still only zero data is being read in...
Ttelmah



Joined: 11 Mar 2010
Posts: 19231

View user's profile Send private message

PostPosted: Tue Dec 19, 2023 5:05 am     Reply with quote

OK.
So do you have an oscilloscope?.
If so, look at the data line and verify it does have data on it.
If not, then write a simple program on the master that toggles the SDO
line, and verify that this is seen on the SDI pin.
Always worth checking the basic first. Very Happy
Backfire



Joined: 12 Oct 2020
Posts: 44

View user's profile Send private message

PostPosted: Tue Jan 09, 2024 8:13 am     Reply with quote

So, SPI comms have been established! The required fix was found in this thread; ( http://www.ccsinfo.com/forum/viewtopic.php?p=227266 ), and it was the requirement for the slave SPI #use statement to include the ENABLE=PIN_A5, despite it having being set with the #pin_select statement.

Now onto the next issue, which I have looked at from all angles, to no avail; So I am once again looking for brains to pick!

I have 3 slave devices on my SPI bus, they are all PIC16F15356's, and another of the same device acting as a master. I create 3 SPI streams in the master device with the following code;
Code:

#use spi(STREAM=DRV1, MASTER, SPI1, BITS=8, BAUD=500000, ENABLE=PIN_C0)
#use spi(STREAM=DRV2, MASTER, SPI1, BITS=8, BAUD=500000, ENABLE=PIN_C1)
#use spi(STREAM=DRV3, MASTER, SPI1, BITS=8, BAUD=500000, ENABLE=PIN_C2)


And then the required spi_xfer(...) call is made with the following logic:
Code:

// Get parameters from the data frame...
AddressedMotor = ((CommandsBuffer[CommandCountLoopCounter][1]>>4) & 0b00001111);

// Forward the other details to the relevant driver IC...
if((AddressedMotor == 1) || (AddressedMotor == 2) || (AddressedMotor == 3))
{
 for(Index = 1 ; Index < 4 ; Index++)
   SPIReturnVal = spi_xfer(DRV1, CommandsBuffer[CommandCountLoopCounter][Index], 8);
}
if((AddressedMotor == 4) || (AddressedMotor == 5) || (AddressedMotor == 6))
{
 for(Index = 1 ; Index < 4 ; Index++)
   SPIReturnVal = spi_xfer(DRV2, CommandsBuffer[CommandCountLoopCounter][Index], 8);
}
if((AddressedMotor == 7) || (AddressedMotor == 8) || (AddressedMotor == 9))
{
 for(Index = 1 ; Index < 4 ; Index++)
   SPIReturnVal = spi_xfer(DRV3, CommandsBuffer[CommandCountLoopCounter][Index], 8);
}


The slave devices are set up as such:
Code:

// The #use SPI statement requires the ENABLE (CS/SS) pin be set, in the statement
//this is not clearly shown in the compiler manual!
#use spi(STREAM=SPI, SLAVE, SPI1, BITS=8, ENABLE=PIN_A5)


And the Rx ISR;
Code:

#INT_SSP
void SPI_ISR(void)
{
   static int8 Index = 0;
   
   // Load data in from SPI peripheral...
   CommandsBuffer[CommandsToProcess][Index] = spi_xfer_in(SPI, 8);

   // Reset our time-out timer... We use this to see if we've had a break in
   //SPI data reception for a few ms, and if so, we can pause interrupts and
   //process the received commands.
   set_timer0(0);
   
   // Handle message wrapping, and increase our received commands counter...
   if(Index == 2)
   {
      Index = 0;
      CommandsToProcess++;
      return;
   }
   
   Index++;
}


These transfers are mostly made without issue to my slave devices, but I seem to have a bug somewhere, as my slave IC responsible for handling Motor #5 always seemingly receives corrupt data for this motor, the other two SPI slaves receive data correctly.

When performing a data-dump to attempt to find the issue, I have the following in the buffer;
Code:

Buf[0][0]:40
Buf[0][1]:f7
Buf[0][2]:f7

Buf[1][0]:f7
Buf[1][1]:07
Buf[1][2]:fc

Buf[2][0]:60
Buf[2][1]:f7
Buf[2][2]:f8


Where Buf[1][0], should be 0x50, as I've 100% confirmed that is the data byte being sent.

Any guidance would be greatly appreciated, as I've mentioned, the SPI slave devices handling motors 1,2,3 and 7,8,9 don't seem to have any issues, what am I missing?
temtronic



Joined: 01 Jul 2010
Posts: 9117
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Jan 09, 2024 9:10 am     Reply with quote

wild guess as wet snow coming down....
your 'time -out' timer has timed out, resets index to zero ??
Backfire



Joined: 12 Oct 2020
Posts: 44

View user's profile Send private message

PostPosted: Tue Jan 09, 2024 9:35 am     Reply with quote

Hi temtronic, though I am using a timer, I'm using it as an 'inactivity monitor', so my main routine has the below call;

Code:

// Check to see if we've got SPI messages, but not actually received anything
//for a tiny while (1ms) (Timer#0 time-out)...
if((CommandsToProcess > 0) && (get_timer0() > 64))
{
    disable_interrupts(INT_SSP);
    ParseCommands();
    enable_interrupts(INT_SSP);
}


The timer itself isn't configured to cause a time-out/interrupt, I just use it to determine if the bus has 'gone quiet' for moment.
temtronic



Joined: 01 Jul 2010
Posts: 9117
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Jan 09, 2024 10:33 am     Reply with quote

hmm, i was thinking that if the ISR did occour, 1st thing you do in the ISR is make index==0.
course I just came in from shovelling 2 " of wet,heavy snow so may not be thinking straight....
Backfire



Joined: 12 Oct 2020
Posts: 44

View user's profile Send private message

PostPosted: Wed Jan 10, 2024 5:24 am     Reply with quote

Is my issue likely to be caused by the fact I don't set a MODE value / SAMPLE_RISE/SAMPLE_FALL values? The compiler documentation has so many options for configuring the SPI peripheral, I might be missing something I need.

Though I still find it strange this issue is only on one device out of three on the bus. I've even tried a whole new board to eliminate having had a static discharge frying a memory location!
temtronic



Joined: 01 Jul 2010
Posts: 9117
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Jan 10, 2024 6:50 am     Reply with quote

maybe some quirky hardware issue ?
can you swap #2 for #1 or 3, run program and get same result or does the error follow the unit ( #2)
does it work fine with only 2 devices ?

can you comment out the 'time out timer' code just to eliminate that it is the cause ?
reduce program to JUST reading the 3 devices,to eliminate any other unforeseen 'interaction' that just magically occours.....
Ttelmah



Joined: 11 Mar 2010
Posts: 19231

View user's profile Send private message

PostPosted: Wed Jan 10, 2024 7:14 am     Reply with quote

I notice the transmission code is counting from 1. Why?. Means the array
lines all have to be one byte larger than you'd expect.
My suspicion is that in fact this is resulting in a wrap in the array handling
here. So when you talk to index==4 you are actually writing to the start of
the next line in the buffer....
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