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

SPI Problems - Only reading every other byte

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







SPI Problems - Only reading every other byte
PostPosted: Fri Aug 11, 2006 9:25 am     Reply with quote

I'm having problems with SPI communication between two PIC's. I want to send data from a pic 18f4680 to a pic 16f876. I've written some test code that increments an int8 up and down between 0 and 255, sending each value over the SPI port. The result I get at the other end seems to miss every other byte so instead of '1,2,3,4,5 . . .' I get '1,3,5,7,9 . . .'

I can only get it to work if I use two write_spi(x) calls together - effectively sending each byte twice.

Can anyone explain whats going on?

Here is the transmitter code
Code:

#include "D:\PIC_C_Projects\PGS\Controller\Cont.h"
/*
//From header
#include <18F4680.h>
#device adc=10

#FUSES NOWDT                     //No Watch Dog Timer
#FUSES WDT128                    //Watch Dog Timer uses 1:128 Postscale
//#FUSES HS                        //High speed Osc (> 4mhz)
#FUSES H4                        //High speed osc with HW enabled 4X PLL
#FUSES NOPROTECT                 //Code not protected from reading
#FUSES BROWNOUT                  //Reset when brownout detected
#FUSES BORV43                    //Brownout reset at 4.3V
#FUSES NOPUT                     //No Power Up Timer
#FUSES NOCPD                     //No EE protection
#FUSES STVREN                    //Stack full/underflow will cause reset
#FUSES NODEBUG                   //No Debug mode for ICD
#FUSES NOLVP                     //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                     //Program memory not write protected
#FUSES NOWRTD                    //Data EEPROM not write protected
#FUSES NOWRTB                    //Boot block not write protected
#FUSES NOCPB                     //No Boot Block code protection
#FUSES NOWRTC                    //configuration not registers write protected
#FUSES NOEBTR                    //Memory not protected from table reads
#FUSES NOEBTRB                   //Boot block not protected from table reads
#FUSES MCLR                      //Master Clear pin enabled
#FUSES XINST                   //Extended set extension and Indexed Addressing mode
#FUSES LPT1OSC               //Low Power Timer OSC1
//#FUSES NOXINST                   //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#use delay(clock=32000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
*/

void SPISendByte(int8 Value)
{
   //This Works
   spi_write(Value);
   delay_us(10);
   spi_write(Value);


   //But not this
   /*
   spi_write(Value);
   */

}
int8 InByte1;

#zero_ram
void main()
{


   int8 OutByte;
   signed int16 Dir;
   setup_adc_ports(AN0_TO_AN6|VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_0);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_16);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_DIV_1|RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED|T2_DIV_BY_1,255,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_oscillator(False);

   OutByte = 0;
   Dir = 1;
   while(1)
   {
      //just to test count up and down then transmit over SPI
      OutByte += Dir;
      if(OutByte > 254) Dir = -1;
      if(OutByte < 1) Dir = 1;

      //send the byte
      SPISendByte(OutByte);

      delay_ms(50);
      putc(OutByte);

   }

}


And the reciever code
Code:



#include "D:\PIC_C_Projects\PGS\SEA_Pic16f876\SEA_Controller.h"
/*
//From Header
#include <16F876.h>

#device adc=10
//#include "Fixed.h"
#FUSES NOWDT
#FUSES HS
#FUSES PUT
#FUSES NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
*/

int8 SPIData;
int1 NewData;
int8 SPIBuff[64];
int8 index;

#INT_SSP
SSP_isr()
{
   //collect incoming SPI data into a buffer
   SPIBuff[index] = spi_read(0);
   index++;
   if(index > 63)
   {
      index = 0;
      NewData = 1;
   }
}


VOID main()
{
   int8 Out = 0;
      setup_adc_ports(ALL_ANALOG);
      setup_adc(ADC_CLOCK_INTERNAL);
      setup_spi(SPI_SLAVE|SPI_L_TO_H|SPI_CLK_DIV_4|SPI_SS_DISABLED);
      setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);
      setup_timer_1(T1_DISABLED);
      //setup_timer_2(T2_DIV_BY_16);
      enable_interrupts (INT_SSP);
      enable_interrupts (GLOBAL);
      NewData = 0;
   index = 0;

   WHILE (1)
   {
      if(NewData == 1)
      {
         //if the buffer is full empty it over the USART

         for(Out = 0; Out < 64; Out++)
         {
            putc( SPIBuff[Out] );
         }
         NewData = 0;
      }
   }
}
Ttelmah
Guest







PostPosted: Fri Aug 11, 2006 10:11 am     Reply with quote

You are creating the 'heart' problem, for yourself, by having the '0' in the SPI_READ command.
At heart, the CCS spi functions, are not well written for interrupt use. In the interrupt, if you do want to send data back, on the slave device, all that is needed is to read the register contents, then write the new byte back, and exit the interrupt. However the CCS function, if asked to write a byte back, will _wait_ for it to transfer. So by having the '0' here, you are forcing two transfers to have to occur, for each loop of the interrupt handler (one to send the byte and force the interrupt, and a second to clock back the reply)...
If you don't want to transfer data back, then get rid of the zero. You will also need to have the 10uSec delay after any transfer, since it takes about 6uSec after the byte completes for the 'slave' device to actually get into the interrupt handler. Your second transfer is working without the delay, because the slave is sitting 'waiting' in the handler.
If you do want to do transfers both ways, I have an alternative set of SPI functions, optimised for use with interrupts, which I have posted in the past, and if you want bi-directional useage, I have a newer version that I can post.

Best Wishes
WTB
Guest







PostPosted: Fri Aug 11, 2006 10:19 am     Reply with quote

Thanks for that, it now works. An example of how to return data would be appreciated as well though.

What I am trying to do eventually is to send a signed int16 over the SPI and get a signed int16 back.
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