pic16f877a spi master slave help needed

Discussion in 'Embedded Systems and Microcontrollers' started by n_1_needs_help, Jul 2, 2014.

  1. n_1_needs_help

    Thread Starter New Member

    Jun 8, 2014
    5
    0
    Hi,
    I am trying to get some communication going using SPI between two PIC16f877a's and am failing miserably. Any alternative code to solve this problem using 877a or suggestions would be greatly appreciated. The basic problem is the slave is just not receiving anything from the master!

    Code ( (Unknown Language)):
    1.  
    2. //master code
    3.  #include <htc.h>
    4.  #include <stdio.h>
    5. #include "usart.h"
    6. __CONFIG(0x3f3A);
    7. //Defintions.h
    8. #define SS RA5
    9. #define SCK RC3
    10. #define SDI RC4
    11. #define SDO RC5
    12. #define FALSE 0
    13. #define TRUE 1
    14. #define RTS RA0
    15. #define CTS RA1
    16.  
    17. int i,j;
    18. void main (void)
    19. {
    20. //initialisations and declaration of variables
    21. unsigned char testCounter = 0, dummy;
    22.     INTCON=0;   // purpose of disabling the interrupts.
    23.  
    24.     init_comms();
    25. printf("\r this is a test");
    26. //initialisations of port pins
    27. for (i=1;i<250;i++);//1ms delay
    28.  
    29. PCFG3 = 0; // Configure PORTA digital I/O
    30. PCFG2 = 1;
    31. PCFG1 = 1;
    32. TRISC3 = 0; // SCK=RC3 is the serial clock
    33. TRISC4 = 1; // SDI=RC4 is serial data input
    34. TRISC5 = 0; // SDO=RC5 is serial data output
    35. TRISA0 = 0; // RA0 = RTS, an output
    36. TRISA1 = 1; // RA1 = CTS, an input
    37. TRISA5 = 0; // SS=RA5 is slave select output
    38. INTCON = 0; // Disable
    39.  
    40. //initialisation of timer SPI
    41.  
    42. SMP = 0; // Input data sampled at middle data output time
    43. CKE = 0; // Transmit occurs on idle to active clock state
    44. CKP = 1; // Idle state for clock is a high level
    45. SSPM3 = 0; //
    46. SSPM2 = 0; //
    47. SSPM1 = 0; //
    48. SSPM0 = 0; // SPI Master mode, clock = FOSC/4
    49. SSPEN = 1; // Enables serial port
    50. SS = 1; // De-select Slave (pin 7)
    51. SSPIF = 0;
    52.  
    53. //superloop program
    54. RTS = 1; //Master signals "I'm
    55. //ready!"
    56. while(CTS == 0){} //Wait for Slave
    57. //ready
    58. while(1){
    59. SS = 0; // Select Slave (Active low)
    60. // Transmit data:
    61. SSPBUF = testCounter;
    62. //Wait for transmission complete:
    63. while(BF==FALSE) {}
    64. dummy = SSPBUF; // Makes BF=FALSE
    65.  
    66. printf("\r p2 ");
    67. SS = 1; // De-select Slave
    68. testCounter++;
    69. for (j=1;j<2000;j++){
    70.  
    71. for (i=1;i<250;i++);//1ms delay
    72. }
    73. }
    74. }
    75. ---------------------------------------------
    76.  
    77.  
    78. //slave code
    79.  #include <htc.h>
    80.  #include <stdio.h>
    81. #include "usart.h"
    82. __CONFIG(0x3f3A);
    83.  
    84. #define SS RA5
    85. #define SCK RC3
    86. #define SDI RC4
    87. #define SDO RC5
    88. #define FALSE 0
    89. #define TRUE 1
    90. #define RTS RA0
    91. #define CTS RA1
    92. int i,expectedValue;
    93. void main (void)
    94. {
    95.     INTCON=0;   // purpose of disabling the interrupts.
    96.  
    97.     init_comms();
    98. //initialisations and declarations of variables
    99. unsigned char testCounter = 0, data;
    100. unsigned char errorCount = 0;
    101.  
    102. //initialisations of port pins
    103. printf("\r this is a test");
    104. for (i=1;i<250;i++);
    105.  
    106. PCFG3 = 0; // Configure PORTA digital I/O
    107. PCFG2 = 1;
    108. PCFG1 = 1;
    109. TRISC3 = 1; // SCK = RC3 clock (inputforslave)
    110. TRISC4 = 1; // SDI = RC4 serial data input
    111. TRISC5 = 0; // SDO = RC5 serial data output
    112. TRISA0 = 0; // RA0 = RTS, an output
    113. TRISA1 = 1; // RA1 = CTS, an input
    114. TRISA5 = 1; // SS = RA5 slave select input
    115. // Extra for displaying a LED
    116. TRISA2=0;
    117. TRISA3=0;
    118. INTCON = 0; // Disable all interrupts
    119. SSPIF = 0;
    120.  
    121. //initialisation of timer SPI
    122. SMP = 0; // Input data sampled at middle data output time
    123. CKE = 0; // Transmit occurs on idle to active clock state
    124. CKP = 1; // Idle state for clock is a high level
    125. SSPM3 = 0; //
    126. SSPM2 = 1; //
    127. SSPM1 = 0; //
    128. SSPM0 = 0; // SPI Slave mode, SS pin control enabled
    129. SSPEN = 1; // Enables serial port
    130. SSPIF = 0;
    131. expectedValue = errorCount = 0; // For testing and debugging
    132. RA2=0;RA3=0;
    133. //superloop program
    134. RTS = 1; //Slave signals "I'm
    135. //ready!"
    136. while(CTS == 0){} //Wait for Master ready
    137.  
    138. while(1){
    139. // Wait for Master to select Slave:
    140. while(SS == 1){}
    141. // Wait for SSPBUF to be full
    142. //printf("\r p2 ");
    143. //(Signifies reception complete):
    144. while(BF==FALSE){}
    145. data = SSPBUF; // Get data byte
    146. //printf("\r p3 ");
    147. printf("\r d [%c] ",data);
    148. RA2=1;
    149. // Wait for Master to de-select Slave while(SS == 0){}
    150. if(data != expectedValue)
    151. {
    152. errorCount++;
    153. }
    154.  
    155. printf("\r d [%c] ",data);
    156. expectedValue++;
    157.  
    158. }
    159.  
    160. }//end of main
    161.  
     
    Last edited by a moderator: Jul 2, 2014
  2. JohnInTX

    Moderator

    Jun 26, 2012
    2,341
    1,024
    Hard to tell but a few things here:
    You don't need/want this in the slave. SS/ is controlled by the SPI transmitter and sensed automatically by the SPI slave. Its possible that reading this returns a 0 which would sail right through your other code.

    You should not use r-m-w on any of the TRIS registers, especially any that are shared with peripherals i.e.
    Code ( (Unknown Language)):
    1. TRISC3 = 0; // SCK=RC3 is the serial clock
    2. TRISC4 = 1; // SDI=RC4 is serial data input
    3. TRISC5 = 0; // SDO=RC5 is serial data output
    should be done as TRISC = the equivalent byte for ALL bits at once. Since this processor does not have LATx like the 18F, I would strongly recommend that you do that with all IO i.e. maintain a byte image of the port output desired, flip bits on that then assign the whole byte to the PORT. You would not believe the problems that can arise from r-m-w shared with a peripheral - until they bite you that is. Then you'd believe. I believe.

    You should check WCOL and SSPOV and clear them as necessary - if you have a read overflow, it will hang the SSP until cleared.

    The setups look OK per se. What does the terminal say about where you are?
     
  3. shteii01

    AAC Fanatic!

    Feb 19, 2010
    3,386
    496
    Why int i,j; outside main()?
     
  4. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    If I take that literally you are saying the master is not transmitting. Fine. You need rock solid master before you try the slave end anyway.

    Get an EEPROM or such and make some master code to control it. Once that is in the bag you'll have a bit more experience to go at the slave end.

    The slave side is the truly hard one.
     
  5. JohnInTX

    Moderator

    Jun 26, 2012
    2,341
    1,024
    Don't forget to ensure that SDO on the master connects to SDI on the slave and vice versa. Same for RTS connecting to CTS, master to slave and vice versa.

    Good luck!
     
  6. n_1_needs_help

    Thread Starter New Member

    Jun 8, 2014
    5
    0
    It was working, I soldered extra pins to the board and missed a solder bridge on 1 of the extra 80 pins I soldered, and that one pin was pin 18 on the pic16f877a (SPI clock), I wonder what the odds on that are?
    Thanks for all your help!
     
Loading...