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

Slave SPI

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



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

Slave SPI
PostPosted: Tue Jul 27, 2021 1:00 pm     Reply with quote

PIC18F23K22
CCS 5.094
MPLAB 8.92

Connecting two PIC18F23K22 pics together via SPI1.

I get no data out of the SLAVE side. Master side is clocking, doing to slave_select correctly.

I just did the following simple loop on the Slave:

Code:
while(1) {  // endless main loop


  delay_ms(5);
  spi_write(0x25);
  output_toggle(PIN_A0);

}   // end endless loop


to force the SLAVE to just constantly send. The code hangs at the spi_write() function. I know this because PIN_A0 does not toggle. When I comment out the spi_write(), PIN_A0 toggles.

I am not using the default Slave_Select, I am using PIN_C2. It is controlled by the MASTER via output_high() and output_low()


SLAVE is set up as:
Code:
setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_SS_DISABLED | spi_clk_div_16 | spi_xmit_l_to_h);


Not sure what is going on here, I thought I could force the slave to send on the spi by continuously calling spi_write.

The SCLK is supplied by the MASTER via a spi_read(0); call, and the SCLK is present verified with the scope.

I can post more code if needed, just tried to whittle it down the a bare minimum to see why the SLAVE will not send.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Tue Jul 27, 2021 2:14 pm     Reply with quote

Expanding on this topic a bit, it seems to be a timing problem with using the manual slave select line. I can get the fixed data sent by the slave to the master, but I have to wait several ms to do so.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Tue Jul 27, 2021 2:30 pm     Reply with quote

Well a closer look shows the master is only reading back what it wrote in the following line:
Code:
depth = spi_read(0x01);


so my read back is 1 instead of what the slave should write out which is
Code:
spi_write(0x25);


The slave is not hanging on the spi_write call, but DO shows no data. I do see data on DI to the slave which is DO of the Master. SCLK is correct too.
seems like something fundamental and simple but not seeing it.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Tue Jul 27, 2021 6:25 pm     Reply with quote

Not sure what is going on or how much to try to explain.
Basically it works now between the two pics.
Except for certain conditions like
a decimal 33 sent from the slave to the master shows up as a 32
A 0X31 shows up at the Master as 48 decimal.
A 0x0FF shows up at the master as 255 decimal

Mode 0 does not work at all only reports 0.
I am running mode 1 now.

Master is set up like this:

Code:
#DEFINE SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#DEFINE SPI_MODE_1  (SPI_L_TO_H)
#DEFINE SPI_MODE_2  (SPI_H_TO_L)
#DEFINE SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

output_high(LED1_CNTRL);                                // This is the Slave Select l
setup_spi(SPI_MASTER | SPI_MODE_1 | SPI_SS_DISABLED | spi_clk_div_16);      // Use manual line instead of SS line on PIC for control



main loop is

Code:
  output_low(LED1_CNTRL);
       delay_us(100);
       
       depth = spi_read(0x00);
       delay_us(10);
       fprintf(HOST_SERIAL, "D= %u\n\r",depth);
       
       output_high(LED1_CNTRL);



SLAVE:

Code:
#DEFINE SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#DEFINE SPI_MODE_1  (SPI_L_TO_H)
#DEFINE SPI_MODE_2  (SPI_H_TO_L)
#DEFINE SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

#DEFINE SLAVE_SELECTOR   PIN_C2

setup_spi(SPI_SLAVE | SPI_MODE_1 | SPI_SS_DISABLED | spi_clk_div_16);


main loop:

Code:
while(1) {  // endless main loop

if(!input(SLAVE_SELECTOR)) {
 
  spi_write(33);
  output_toggle(PIN_A0);
}
}   // end endless loop


hopefully someone can explain this behavior. After a 14 hr day, I am done, will answer questions tomorrow.
thank you all for your advice and time in advance.
Ttelmah



Joined: 11 Mar 2010
Posts: 19498

View user's profile Send private message

PostPosted: Wed Jul 28, 2021 12:01 am     Reply with quote

The behaviour you are seeing, says that you have a physical problem with
the connections. The clock is being delayed. How long are the wires?. How
fast is the /16 clock (depends on your PIC clock rate). What sort of wire
is being used?. Do you have any termination on the signals?. Wires are
'transmission lines', as such signals will 'ring' if the lines are not terminated
to match the impedance of the wire. It sounds as if the rising edge in
particular is being delayed. There are problems worst on the clock line, but
on the SDI line as well, which is why some edges are not correctly received.
How are the grounds connected between the chips?. What voltage is the
system running?.
You can reduce ringing, by just adding perhaps a 22R resistor into each
signal line at it's 'source'. This fractionally reduces the actual clock edge
speed being sent on the line, thereby massively reducing ringing. Even if
the bus is running very slowly, the edges are those produced by the PIC
gates 'flat out', so ringing will occur. It is just that at low speeds this
will generally die away before the sample point of the signal.
temtronic



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

View user's profile Send private message

PostPosted: Wed Jul 28, 2021 4:43 am     Reply with quote

The 2 examples you post, lose the last bit, 'classic' for a long serial line with RC clocks. BTDT decades ago. Could get 12-13 miles on the serial loops, never got 15 until I slowed the clock down.
As Mr. T points out there's a few 'hardware' issues that can cause the loss of data but I'll add...
PIC clock... should be real xtal/2 caps not internal RC
distance...you need GOOD copper between PICs
clock.. what speed ? there's a speed vs distance demon
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Wed Jul 28, 2021 9:45 am     Reply with quote

Thanks for the responses. It is a moving target problem, changing one thing makes it either work or not work. Changing back may or may not make it work again.
So, layout, ringing sounds on target.

Vcc is 3.3V
Grounds between pics are connected via a ground plane on the top of the PCB, these chips are surface mount.
Crystal is 16MHz clock speed is 64Mhz
no termination resistors or pull ups or pull downs.
chip distances is about 2 inches. Lines do have a couple vias on them as well and are two ounce copper and are 0.010" in width.
I will try the series resistors to settle the ringing.
Also may set the clock speed to be 16MHz to slow things down as well.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Wed Jul 28, 2021 10:21 am     Reply with quote

changed my clock statements on both pics to be crystal 16M and clock 16M instead of clock 64M
put a DIV-64 on the SPI clock on both pics.
still do not have good data, looked close with a scope and I have 250mV overshoot on the rising edges of the SCLK signal and a -250mV undershoot (below ground) on the falling edges of the SCLK signal.
I will try some series resistances next.
Hopefully a board or communication scheme is not needed.

I usually use USE SPI to do my SPI setup but in this case used SETUP_SPI because I could not get USE SPI to compile when doing MASTER and SLAVE calls.
would that be a better way so I could drop the communication speeds really low? may not be helpful as the I/O change really fast to different states.
Ttelmah



Joined: 11 Mar 2010
Posts: 19498

View user's profile Send private message

PostPosted: Wed Jul 28, 2021 10:38 am     Reply with quote

Your issue with mode 0, is in the errata. The chip has a problem as a
master when reading data back that it will assert the BF bit to say it
has data immediately, when CKE is zero.
Big caveat....

Really at your slow clock rate, it should be fine, especially with such small
lengths involved.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Wed Jul 28, 2021 11:25 am     Reply with quote

Ttelmah I agree on the data rates should work, I go about the same distance and much faster with SPI on the same board. I tried the other SPI modes and no improvement.
last effort will be series resistors.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Wed Jul 28, 2021 1:27 pm     Reply with quote

Unless someone has some insight, I am tapping out and designing this portion out. Resistors made no difference. Does not make sense, SPI running all over this board, just not this one. I hate the redesign, but I really do not want to support something that is obviously picky in this configuration for some reason.
Ttelmah



Joined: 11 Mar 2010
Posts: 19498

View user's profile Send private message

PostPosted: Thu Jul 29, 2021 1:16 am     Reply with quote

There are a number of things that might be causing your issues.
Are you setting up the slew rate control for the pins?. Must admit I'd be
surprised to see overshoot if this is enabled.
Try adding set_slow_slew_c(FALSE); and the same for all the ports you
are using. I'm assuming you are using the default port C pins for the SPI.
Given your slow clock rate, you can then try with this enabled. If the problem
disappears you know it is a transmission line problem.
Generally the newer generation chips like this that support lower voltage
operation, become increasingly sensitive to their supply. How well decoupled
are the chips?. Really good ceramic capacitors close to the supply legs on
both?. Anything else on the board that might be generating noise?.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Thu Jul 29, 2021 4:42 pm     Reply with quote

OK, burned another day on SPI between two pics,
broke camp on using spi_read and spi_write.
did code for using SPI_XFER and #USE SPI()

what is happening now is, I get all 1s sent. My signals, i.e. clock looks great no ringing or overshooting. Still is not working though. Here is my code snippets.

MASTER:

Code:

#DEFINE CS_7766 PIN_A5

#INCLUDE <18F23K22.h>

#use SPI(master, bits=8, mode=0, clk=PIN_C3, DO=PIN_C5, DI=PIN_C4, enable=PIN_A0, sample_rise, enable_active=1, baud=100000, stream=STREAM_7766)


Code:

void main()
{
output_low(CS_7766);
delay_ms(1000);
spi_init(STREAM_7766,100000);

while (1) {

output_HIGH(CS_7766);
       
       disable_interrupts(global);
   
       
       delay_us(100);
       
       depth = spi_xfer(STREAM_7766, 0);
       output_low(CS_7766);

       enable_interrupts(global);
       
       output_low(CS_7766);
} // end while
} // end main



SLAVE:
Code:

#DEFINE SLAVE_SELECTOR   PIN_A5

#use spi(slave, bits=8, mode=0, CLK=PIN_C3, DO=PIN_C5, DI=PIN_C4, enable=PIN_A5, sample_rise, STREAM=DEPTH_1)


#INT_SSP
void ssp_isr(void) {

   spi_xfer(DEPTH_1,0x01,8);

}

spi_init(DEPTH_1,100000);

void main() {

while(1) {  // endless main loop

delay_us(1);
  }



The interrupt in the slave was a late attempt, I just get all 1,s now.
if I do force_sw in the # use spi it runs really slow and seems to only send one bit per each read by the master.
comments and ideas are welcome. Seems like it is close. But after another long day, what do I know?
Ttelmah



Joined: 11 Mar 2010
Posts: 19498

View user's profile Send private message

PostPosted: Fri Jul 30, 2021 12:50 am     Reply with quote

Suite of things:
A slave does not have a speed. Get rid of the SPI_init on the slave.
Setting this can result in invalid chip configurations.
Use the port names. Much easier. You seem to be using a high select
line. Why?. If you want to use the slave select, this has to be low for
a transfer, and should only be low for the actual transfer. This is why it is
marked /SS. Low slave select. You talks about using software SPI. You do
understand this can _only_ apply to the master?.
Setting a slow baud rate does not force software to be used, since the
compiler can set this up using timer2. Understand that on an SPI transfer,
you always receive the byte loaded 'last time' by the slave. Loading this
is what 'spi_prewrite' is for, or load it with the read on the slave:
Code:

//In the master
#use SPI(master, bits=8, mode=0, SPI1, enable=PIN_A0, enable_active=0, baud=100000, stream=STREAM_7766)
//Enable must be active low.

//Then in slave.
#use spi(slave, bits=8, mode=0, SPI1, STREAM=DEPTH_1, ENABLE=PIN_A5, ENABLE_ACTIVE=0)
//the mode already specifies the sample edge etc...
//slave select, will _only_ work in the slave if the enable is set
//to the SS pin, and ENABLE_ACTIVE is 0. It physically cannot work
//with any other configuration.

#INT_SSP
void ssp_isr(void)
{
   int8 dummy;
   dummy=spi_xfer(DEPTH_1,0x01);
   //This receives the byte transferred by the master, and loads the
   //byte to return for the next transfer. Since you are specifying
   //bits=8, a word length is not needed.
}

void main()
{
    //Er what you posted cannot work, since the interrupt is not enabled
    spi_prewrite(DEPTH_1,1); //preload the first byte
    enable_interrupts(INT_SSP);
    enable_interrupts(GLOBAL);
    while(TRUE)
       delay_us(1);
}


Understand that every transfer both sends and receives. The master sends
a dummy byte (in your case 0, and clocks a byte back. The slave receives
this byte, and loads the _next_ byte to transfer
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Aug 02, 2021 5:21 pm     Reply with quote

In addition to Ttelmah's code, this thread has sample code for an
SPI master and slave, using the older setup_spi() routines:
http://www.ccsinfo.com/forum/viewtopic.php?t=39145&start=1

This thread has an example in which the master and slave are done
inside one PIC. The master is in software but the slave is done using
the hardware SSP module:
http://www.ccsinfo.com/forum/viewtopic.php?t=26888
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