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

18F2620 SPI Slave Problem with SS pin

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



Joined: 15 Nov 2008
Posts: 4

View user's profile Send private message

18F2620 SPI Slave Problem with SS pin
PostPosted: Sat Nov 15, 2008 4:53 am     Reply with quote

Hi everybody,
I have a problem with the SPI communication.

18F2620 (Rev 0x6) is slave and my SPI is configured by setup_spi(SPI_SLAVE) command. I've watched the SDO,SDI,SS and SCK lines and they are correct. 18F2620 osilator is configured as 8MHz internal and clock is 32MHz with PLL.
(Fisrt SS pin from high to low. After 50 microsecond SCK gets from high to low 8 times (50microsecond each) and SCK gets high after 50 microsec SSpin gets high)
But SSP interrupt never occurs. But when i use setup_spi(SPI_SLAVE|spi_ss_disabled) , SSP interrupt occurs and i get the true data from the SPI. But for sycronizing i need to use SS pin RA5. Now i do it by software like

if (!input(PIN_A5))
{
setup_spi(spi_slave | spi_ss_disabled);
while (!input(PIN_A5)) {}
setup_spi(FALSE);
}

Is there any problem with the SlaveSelect pin or need any confugiration for the 2620. Thanks for your help.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sat Nov 15, 2008 8:03 am     Reply with quote

One problem is that you haven't configured the SPI mode in your slave.

SPI hardware works in one of four modes, depending on the combination of two parameters:
1) initial clock level.
2) Sampling data on the first or second clock edge, regardless of whether that clock edge is rising or falling.

Because CCS uses a signal naming different from what either Motorola or Microchip has defined, I always use the following 'translation' definitions.
Code:
                                                     // Clock base   Sample on
#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)   //    low       leading edge
#define SPI_MODE_1  (SPI_L_TO_H)                     //    low       trailing edge
#define SPI_MODE_2  (SPI_H_TO_L)                     //    high      leading edge
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)   //    high      trailing edge


Usage example:
  setup_spi(SPI_SLAVE | SPI_MODE_0);


You have configured:
Code:
setup_spi(SPI_SLAVE)
Checkout the header file for your processor and you will find out this equals to:
Code:
setup_spi(SPI_SLAVE | SPI_L_TO_H)
This is SPI mode 1 which expects the clock level to be low in inactive state, from your description we understand the clock level is high in inactive state and thus is a mismatch.

Find out the SPI mode of your SPI master and setup the slave to use the same mode. With the initial clock level high this will be either mode 2 or 3.

More information on SPI: http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
gnz



Joined: 15 Nov 2008
Posts: 4

View user's profile Send private message

PostPosted: Tue Nov 18, 2008 4:14 am     Reply with quote

Hi ckielstra,
I have added the setup_spi(SPI_SLAVE | SPI_MODE_1); to my code but nothing changes the problem is with the spi_ss_disabled. When i use this, it is ok i can communicate over SPI, but when i did not use it, SPI port doesnt take any clocks. Here is my code

Code:

#include "18F2620.h"
#device ICD=TRUE
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES PROTECT                  //Code protected from reads
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES NOBROWNOUT               //No brownout reset
#FUSES BORV21                   //Brownout reset at 2.1V
#FUSES PUT                      //Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES LVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES XINST                    //Extended set extension and Indexed Addressing mode enabled
#FUSES PBADEN                   //PORTB pins are configured as analog input channels on RESET
#FUSES LPT1OSC                  //Timer1 configured for low-power operation
#FUSES MCLR                   

#use delay(internal=8M, clock=32M)

#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)   //    low       leading edge
#define SPI_MODE_1  (SPI_L_TO_H)                     //    low       trailing edge
#define SPI_MODE_2  (SPI_H_TO_L)                     //    high      leading edge
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)   //    high      trailing edge


int1 ADCConverted;
int8 ADCResult;

//================================================
//   TIMER0 INTERRUPT //
//================================================
#int_TIMER0
void  TIMER0_isr(void)
{
   static int8 DigitCounter = 0;
   DigitCounter++;
}
//================================================
//   TIMER1 INTERRUPT // adc'i çalıştırır.
//================================================
#int_Timer1
void   TIMER1_isr(void)
{
   if (ADCConverted)
   {
      read_adc(ADC_START_ONLY);
      ADCConverted = FALSE;
   }
}
//================================================
//   ADC INTERRUPT ROUTINE   // adc nin sonucunu alır.
//================================================
#int_AD
void  AD_isr(void)
{
   ADCResult = read_adc(ADC_READ_ONLY);
   ADCConverted = TRUE;
}
//================================================
//
//================================================
void main()
{
   int16 DataIn;
   setup_oscillator(OSC_32MHZ);      // sets up the osilator to work in PLL mode 8Mhz * 4 = 32 MHz

   setup_adc_ports(AN0|VREF_VREF);
   setup_adc(ADC_CLOCK_DIV_64|ADC_TAD_MUL_20);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32|RTCC_8_bit);      // Timer0 interrupt period = 1.0msec
    setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);                  //   Timer1 interrupt period = 65.5 msec



  setup_spi(SPI_SLAVE | SPI_MODE_1);
   set_adc_channel(0);
   delay_us(10);
   

   enable_interrupts(INT_AD);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(INT_TIMER1);
   disable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);

   

   while(TRUE)
   {
      if (spi_data_is_in())
      {
         DataIn = spi_read();
      }
   }

}







This code never breaks at the line DataIn = spi_read();
But when i use setup_spi(SPI_SLAVE|SPI_MODE_1|SPI_SS_DISABLED); it works. When slave select mode, if SS pin gets into low, the SDO gets from low to high automatically and it gets to low slowly when the SS pin gets into high.

C1 = Chip Select (pin7 (RA5) of 2620) C2 = SCK (pin14 (RC3) of 2620)

PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Nov 18, 2008 1:27 pm     Reply with quote

Quote:
#FUSES LVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES XINST //Extended set extension and Indexed Addressing mode enabled
#FUSES PBADEN //PORTB pins are configured as analog input channels on RESET
#FUSES LPT1OSC

I didn't even look at the rest of your code. These two fuses are a major
problem. With LVP set, if pin B5 goes high, the PIC will go into low
voltage programming mode. It will appear to mysteriously "lock up".
Change that fuse to NOLVP.

With the XINST fuse, the PIC expects to get machine code that works
with the "extended instruction set". But the CCS compiler doesn't
support that. With XINST, your program will act in an erratic manner.
It will appear to be extremely buggy. Change it to NOXINST.

Do these two things in all future programs.
gnz



Joined: 15 Nov 2008
Posts: 4

View user's profile Send private message

PostPosted: Wed Nov 19, 2008 2:12 am     Reply with quote

Thanks for your warn, PCMprogrammer. I've changed these two configuration, and I still have problem with the SS.
gnz



Joined: 15 Nov 2008
Posts: 4

View user's profile Send private message

PostPosted: Wed Nov 19, 2008 2:36 am     Reply with quote

Problem is solved. Thanks for everybody for the replies.

The problem is solved by adding a 100ohm resistor between the 18f2620 SSpin and the chip select output of the master microcontroller.
I've found the solution from this post; http://www.ccsinfo.com/forum/viewtopic.php?t=21650&start=8

Quote:


Okay, we figured out the problem. It turns out the solution was buried in the Errata document of the 18f252:

Quote:
10. Module: MSSP (SPI, Slave Mode)
In its current implementation, the SS (Slave
Select) control signal, generated by an external
master processor, may not be successfully recognized
by the PIC� microcontroller operating in
Slave Select mode (SSPM3:SSPM0 = 0100). In
particular, it has been observed that faster
transitions (those with shorter fall times) are more
likely to be missed than than slower transitions.
Work around
Insert a series resistor between the source of the
SS signal and the corresponding SS input line of
the microcontroller. The value of the resistor is
dependent on both the application system�s
characteristics and process variations between
microcontrollers. Experimentation and thorough
testing is encouraged.
This is a recommended solution. Others may exist.


We used a 100 ohm resistor in series with the SCK line. It worked right off the bat...



18F252 errata helps but i couldn't find a solution like this at the errata of 18F2620. I think i could not read carefully.
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