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 communication problem

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







SPI communication problem
PostPosted: Mon Dec 08, 2008 11:22 am     Reply with quote

I try to make my two 18F4620 communicate with each other.
One with 40MHz clock, the other with 10MHz.
Now, I make master setting with:
Code:
setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_16);
with 40Mhz clock

Slave setting:
Code:
setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16);

I try to make it work for a while.
The master can make the right signal but some how the slave just receive the correct signal.
Please help. thanks for all.
Here is my code:
Code:
#include <18F4620.H>
#device  ADC=10
#use     delay (clock= 40000000)
#use     rs232 (baud = 115200, xmit= PIN_C6, rcv= PIN_C7)
#define  ccp2_period  1000
int8 duty_set=160;
#INT_CCP2                           // Capture/Compare ISR
void system_clock_CCP2_ISR()
{
   A4 = 1;                          // get a scope to see this   

   CCP_2 += ccp2_period;
   spi_write(duty_set);
   A4 = 0;
}
void main()
{
 
 setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_2 );

   setup_ccp2 ( CCP_COMPARE_INT );  // configure CCP2 in COMPARE mode and ...
                                    // CCP2 Interrupt on compare match
   enable_interrupts ( INT_CCP2 );
   enable_interrupts ( GLOBAL   );

   set_timer1(0);CCP_2=ccp2_period; // start the CCP2_ISR at 1 msec later

   setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_16);

 while ( 1 )
   {
   }
}




and slave code
Code:

include <18F4620.H> // <18F452.H>   // device header file from CCS-C

#device  ADC=10                     // choose 10 bit AD instead of 8

#use     delay (clock= 10000000)    // 20 MHz crystal oscillator

#use     rs232 (baud = 28500, xmit= PIN_C6, rcv= PIN_C7, errors)

#define  ccp2_period  250           // CCP2_compare_match_interrupt_period

int16    time_tick  = 0;            // system clock
int16    time_sec   = 0;
//int datain=80;
//int16    ad_data;

#ifdef   __PCM__                    // PIC16Fxxx
#bit     A4       = 0x05.4          // Port_A, pin #5, for CCS-C only
#bit     TRISA4   = 0x85.4
#define  PORTD    *(int8 *)(0x08)
#define  TRISD    *(int8 *)(0x88)
#else                               // PIC18Fxxx
#bit     A4       = 0xF80.4
#bit     TRISA4   = 0xF92.4
#define  PORTD    *(int8 *)(0xF83)
#define  TRISD    *(int8 *)(0xF95)
#endif

/*
int16 interrupt_time=0, resolution=0,duty_length=0,duty_medium=0;
int16 duty_changer=0,duty_set=0,max_duty=0,min_duty,cycle=0,Duty_set_high=0;
*/
int16 interrupt_time,cycle;
int16 duty_length=0,duty_set=80,Duty_set_high=0;

#INT_CCP2                           // Capture/Compare ISR
void system_clock_CCP2_ISR()
{


   A4 = 1;                          // get a scope to see this signal

   CCP_2 += ccp2_period;            // setup critirion for next CCP2_ISR
                                    // CCP_2 is defined in 16F877.H
                                   
   if(spi_data_is_in())           
     {
       duty_set=spi_read();

       output_D(duty_set);
     }
 
    if ( cycle-- )                         
       {
          if (Duty_set_high<duty_set)
            {
              Duty_set_high++;
              output_high(pin_B4);   
              //A4 = 0;                 
            }
          else
            {
              output_low(pin_B4);
              //A4 = 0;                 

       }

     else {cycle=duty_length ; Duty_set_high=0 ;}


   A4 = 0;
}
void main()
{
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_2 );

   setup_ccp2 ( CCP_COMPARE_INT );  // configure CCP2 in COMPARE mode and ...
                                    // CCP2 Interrupt on compare match
   enable_interrupts ( INT_CCP2 );
   enable_interrupts ( GLOBAL   );

   set_timer1(0);CCP_2=ccp2_period; // start the CCP2_ISR at 1 msec later

   setup_adc_ports ( ANALOG_AN0 );  // RA0 as analog input
setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16);
set_tris_d(0);
  output_d(0x0);

interrupt_time = ccp2_period * 2 /10;
duty_length = 16000 / interrupt_time ;

while ( 1 )
   {
     printf(" \r\n duty_set=%lu ", duty_set );
     delay_ms ( 300 );
  }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Dec 08, 2008 1:10 pm     Reply with quote

Quote:
setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16);

Don't specify a clock divisor in the slave. The master supplies the clock.
On the slave, if you are not using \Slave Select, then you should add:
Code:
SPI_SS_DISABLED



Quote:
#INT_CCP2
void system_clock_CCP2_ISR()
{
A4 = 1;

CCP_2 += ccp2_period;

if(spi_data_is_in())
{
duty_set=spi_read();

You are checking the SPI buffer in the CCP2 interrupt. Why ?
What if two bytes of SPI data arrive before an interrupt occurs ?
Normally, the SPI read operation is done in the #int_ssp interrupt.
That's the interrupt for the SPI module.


Quote:
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_2 );

setup_ccp2 ( CCP_COMPARE_INT ); // configure CCP2 in COMPARE mode and ...
// CCP2 Interrupt on compare match
enable_interrupts ( INT_CCP2 );
enable_interrupts ( GLOBAL );

set_timer1(0);CCP_2=ccp2_period; // start the CCP2_ISR at 1 msec later

setup_adc_ports ( ANALOG_AN0 ); // RA0 as analog input
setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16);
set_tris_d(0);
output_d(0x0);

Here, you are enabling global interrupts before you have finished doing
the setup code for all the modules. You should setup everything first,
and then enable interrupts.
Monk9514524
Guest







SPI c code problem~
PostPosted: Tue Dec 09, 2008 4:06 am     Reply with quote

Thanks PCM programmer

Because I need to produce 62.5Hz is about 16ms period,
the internal PWM module with 10Mhz clock can't produce that signal to reach 16ms.
I try to make the slave producing the PWM signal with the interrupt(system_clock_CCP2_ISR() ) counting.

My original thought make the function if(spi_data_is_in()) in every interrupt to know if the signal coming or not,
if that did then change the duty that slave make.

Code:

if(spi_data_is_in())
{
duty_set=spi_read(); 
}



But somehow when I send the " duty_set = 160 " to slave, the number received with 64.

It seems there are something wrong with interrupt and spi function.
I already tried for period of time.

Master
Code:
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16);
enable_interrupts ( GLOBAL  );


Slave
Code:

setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_CLK_DIV_16);
enable_interrupts ( GLOBAL  );



And if I change the setting of slave to setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16|

SPI_SS_DISABLED);
It wouldn't receive anything even the master still produce the signal to slave.

1. I am curious about the code SPI_XMIT_L_TO_H meaning, is that necessary?

2. Because the master with 40Mhz clock and slave with 10Mhz clock, then should I make the slave setting changed from
SPI_CLK_DIV_16 to SPI_CLK_DIV_4?


BTW. I try to make two sensors receiving and calculate the math all in one interrupt, but the interrupt time became one unit of resolution of PWM signal, would decrease the PWM resolution.
Is there any way to make the PWM signal then, I don't need another PIC to produce PWM signal?

Thanks for all
Monk9514524
Ttelmah
Guest







PostPosted: Tue Dec 09, 2008 5:35 am     Reply with quote

You _must not have a clock speed selected in the slave at all_.

You need to understand the 'point' about synchronous communications. _Only_ the master device generates a clock. The slave clocks the data in, using the clock that is coming from the master. The speed of the slave processor, _does not have any effect at all_, except in that you may have to allow delays between bytes when the master sends, to allow the slave time to handle things. Selecting a 'clock' on the slave, gives you an impossible setup, that will probably stop everything working.

Best Wishes
Monk9514524
Guest







SPI c code problem~
PostPosted: Wed Dec 10, 2008 2:26 am     Reply with quote

Thanks answering~Ttelmah

Because I need the Slave PIC to generate the 62.5Hz (16Ms) signal,and the inside PWM singal can not generate that long
period PWM, so I generate that signal with interrupt. Try to make SPI communcation in the interruption.


This time I changed the data receive in "while" loop in Slave setting.

Master(with 40Mhz) SPI setting in main function
Code:

setup_spi(SPI_MASTER |SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16);
enable_interrupts ( GLOBAL   );


Slave(10MHz) SPI setting in main function
Code:

...
...
setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_CLK_DIV_16| SPI_SS_DISABLED);
enable_interrupts ( GLOBAL   );
while ( 1 )
   {
     printf(" \r\n duty_set=%lu ", duty_set );
     delay_ms ( 300 );

      if(spi_data_is_in())
       {
       duty_set=spi_read();
       //duty_set=1;
       output_D(duty_set);
       }


I made the Master transfer munber 170 to Slave, which binary code is 10101010.
then Slave received the signal, turn out to be 01010100.

It did receive the data but somehow it isn't right?
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Wed Dec 10, 2008 3:08 am     Reply with quote

NO-CLOCK-SETUP-REQUIRED-FOR-A-SLAVE has already been said twice. Don't need to argue on it.
I wonder why you apparently don't use a slave select line. It's the usual, and to my opinion, only simple and robust method, to synchronize slave receiption.
Monk9514524
Guest







SPI c code problem~
PostPosted: Wed Dec 10, 2008 5:57 am     Reply with quote

FvM

I am sorry.
I just don't know how to do you told me to do?

Would you mean take away the setting in SPI_CLK_DIV_16
and find out how to use slave line?

Is it that ?
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Wed Dec 10, 2008 6:38 am     Reply with quote

The settings SPI_SLAVE and SPI_CLK_DIV_16 are mutual exclusive in SPI hardware control register, a slave don't need and should not have a CLK_DIV_xx setting.

The other suggestion is to use a slave select as frame synchronisation signal, if possible.
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