|
|
View previous topic :: View next topic |
Author |
Message |
Backfire
Joined: 12 Oct 2020 Posts: 46
|
SPI PIC16F15356 |
Posted: Mon Dec 18, 2023 8:58 am |
|
|
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: 46
|
|
Posted: Mon Dec 18, 2023 9:33 am |
|
|
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: 19538
|
|
Posted: Mon Dec 18, 2023 11:17 am |
|
|
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.... |
|
|
Backfire
Joined: 12 Oct 2020 Posts: 46
|
|
Posted: Tue Dec 19, 2023 4:21 am |
|
|
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: 19538
|
|
Posted: Tue Dec 19, 2023 5:05 am |
|
|
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. |
|
|
Backfire
Joined: 12 Oct 2020 Posts: 46
|
|
Posted: Tue Jan 09, 2024 8:13 am |
|
|
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: 9243 Location: Greensville,Ontario
|
|
Posted: Tue Jan 09, 2024 9:10 am |
|
|
wild guess as wet snow coming down....
your 'time -out' timer has timed out, resets index to zero ?? |
|
|
Backfire
Joined: 12 Oct 2020 Posts: 46
|
|
Posted: Tue Jan 09, 2024 9:35 am |
|
|
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: 9243 Location: Greensville,Ontario
|
|
Posted: Tue Jan 09, 2024 10:33 am |
|
|
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: 46
|
|
Posted: Wed Jan 10, 2024 5:24 am |
|
|
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: 9243 Location: Greensville,Ontario
|
|
Posted: Wed Jan 10, 2024 6:50 am |
|
|
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: 19538
|
|
Posted: Wed Jan 10, 2024 7:14 am |
|
|
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.... |
|
|
|
|
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
|