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 Master/Slave Problems

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



Joined: 28 May 2006
Posts: 56

View user's profile Send private message

SPI Master/Slave Problems
PostPosted: Tue Apr 03, 2007 4:23 pm     Reply with quote

Hello,
In an attempt to learn SPI and free up some I/Os on my current project I'm trying to build an SPI matrix keypad encoder. I want to be able to perform an SPI read operation from the master and have the keypad encoder send the last key pressed. I understand that the slave must have the data 'ready to go' when the read request is sent. I'm using a 16F88 (using the internal clock @ 8mhz) as the encoder, and a 16F877 (@20mhz) as the master.

F877 -- F88
--------------
SDI to SDO
SDO to SDI
SCK to SCK
D1 to SS

First I press a key on the keypad to put the slave in 'spi_read()', then a read operation is started when I ground D1 on the master. I see the slave display "Reading/Writing SPI...", and after awhile it returns with an invalid result. (usually -1 or 0, not the 65 I expect.). The master returns the same. Thoughts?


SPI Master:
Code:

#include <16F877a.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=20000000)             //clock speed
#use rs232(baud=2400,xmit=PIN_C6,rcv=PIN_C7,ERRORS)
//#include <flex_lcd420.c>

//******************************
// Functions
//******************************
void Startup();
void SecondPassed();

//******************************
// Global Defs
//******************************
int BlinkState,SecondCount;

//******************************
// Code
//******************************

void Main(){
   int i;
   int KeyCode;
   int MenuIndex = 1;
   char Key;
   Startup();

   while(TRUE){
      printf("\n\rWaiting on SPI start button...\n\r");
      while(input(PIN_D0));
     
      printf("Reading SPI...\n\r");

      output_high(PIN_D1);
      Key = spi_read(65);
      output_low(pin_D1);
   
      printf("SPI Returned %i\n\r",Key);
     
      delay_ms(1000);
   }

}
void SecondPassed(){

   switch (BlinkState){
      case 0:
         BlinkState = 1;
         output_low(PIN_B5);
         break;
      default:
         BlinkState = 0;
         output_high(PIN_B5);
         break;
   }
}

#INT_TIMER2
   void Timer2Int(){
      SecondCount++; //counts ints for seconds

      if (SecondCount == 250) { //1sec passed
         SecondCount = 0;
         SecondPassed();
      }
   }


void Startup(){
   enable_interrupts(INT_TIMER2); //used to drive LED display
//   setup_timer_2(T2_DIV_BY_4,0,5);
   setup_timer_2(T2_DIV_BY_4,253,5); // one int per 4ms

   //enable_interrupts(INT_EXT);  //INT for B0 (IR or Keypad)
   enable_interrupts(GLOBAL);   //Actually enable them

   setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_64);

   printf("Keypad and LCD Test\n\r");

}



Slave Code:
Code:

#include <16F88.H>
#fuses INTRC_IO
#fuses NOWDT, BROWNOUT, NOLVP
#use delay(clock=4000000)

#use rs232(baud=2400,xmit=PIN_B3,rcv=PIN_B3,ERRORS)

#include <flex_keypad_4x4.c>
//******************************
// Functions
//******************************
//******************************
// Global Defs
//******************************
//******************************
// Code
//******************************



void main(){
   char k,spiinput;
   setup_spi(SPI_SLAVE | SPI_H_TO_L);

   kbd_init();
   delay_ms(5);
   printf("\f\rF88 Keypad to SPI encoder\n\r");

   while(TRUE){

      k=kbd_getc();
      if(k!=0){
         printf("Key: %c. Reading/Writing SPI...\n\r", k);
         spiinput = spi_read(k);
         printf("SPI Transaction complete. SPI read returned: %c.\n\r",spiinput);
        }
     }
}
Ttelmah
Guest







PostPosted: Wed Apr 04, 2007 3:55 am     Reply with quote

The internal SPI commands, are a little 'too smart' for their own good. With the read, and write, supposedly 'switching modes' according to whether this is a master of slave device. It makes getting the SPI to work harder than it should be. It also means you can't take advantage of the internal hardware buffering quite as easily as should be possible...
I have always used my own code for this reason, and in the slave in particular, it makes things much easier to understand. So:
Code:

#ifdef __PCH__
#byte   SSPBUF = 0xFC9
#byte   SSPCON = 0xFC6
#byte   SSPSTAT = 0xFC7
#else
#byte   SSPBUF = 0x13
#byte   SSPCON = 0x14
#byte   SSPSTAT = 0x94
#endif
#bit          SSPBF = SSTSTAT.0

#DEFINE  READ_SSP()   (SSPBUF)
#DEFINE  SSP_HAS_DATA() (SSPBF)
#DEFINE   WAIT_FOR_SSP()   while(!SSP_HAS_DATA())
#DEFINE   WRITE_SSP(chr)   SSPBUF=(chr)

Now the 'key' difference, is that these 'split up' the parts involved in the operations, allowing you to load the buffer, and then go and do other things if you want.
For your slave, the code would become:
Code:

void main(){
   char k,spiinput;
   setup_spi(SPI_SLAVE | SPI_H_TO_L);

   kbd_init();
   delay_ms(5);
   printf("\f\rF88 Keypad to SPI encoder\n\r");

   while(TRUE){

      k=kbd_getc();
      if(k!=0){
         printf("Key: %c. Reading/Writing SPI...\n\r", k);
         WRITE_SSP(k); //load the output buffer
         while (!SSP_HAS_DATA()) {
             //Here you can do anything you want while waiting
         }
         spiinput = READ_SSP();
         printf("SPI Transaction complete. SPI read returned: %c.\n\r",spiinput);
        }
     }
}

Provided your 'trigger'line is working as expected, your source should work.
Obviously remember that the 'SCK' line needs to directly connect between the devices, while SDO, and SDI, need to 'swap over' between the chips. Also, with the 'split' code as I show, you could 'poll' the device every 1/10th second for example, and have it just return '0', unless a key is present, removing the need for the extra wire.

Best Wishes
kd5uzz



Joined: 28 May 2006
Posts: 56

View user's profile Send private message

Undefined Identifier ?
PostPosted: Wed Apr 04, 2007 9:50 am     Reply with quote

After pasting your defines and main() code I get the above error. It seems to be the compiler doesn't like #bit SSPBF = SSTSTAT.0. I'm using compiler 3.222.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Apr 21, 2007 11:54 pm     Reply with quote

Quote:
It seems to be the compiler doesn't like #bit SSPBF = SSTSTAT.0.

If you're still interested in trying his code, that was just a typo.
Fix it by changing "SST" to "SSP", as shown below:
Code:
#bit SSPBF = SSPSTAT.0
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