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 16f877a + 16f876a

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



Joined: 21 Apr 2014
Posts: 12
Location: Kefalonia, Greece

View user's profile Send private message

SPI 16f877a + 16f876a
PostPosted: Wed Feb 06, 2019 12:13 pm     Reply with quote

Tomorrow i want to test for the first time the communication between 16f877a and 16f876a with spi protocol. I want to be the 877a as master to check a push button and when this is happened i want to send data to 876a as slave to activate a led. I have made two codes for the mcus. I want you guys to see the codes for mistakes or any further tips. Compiler Vers. 5.008.

Spi Connection:
877a----------------876a
SCLK PIN18 ----->SCLK PIN14
SDO PIN24 ----->SDI PIN15
SDI PIN23 <-----SDO PIN16
PIN_D0 ----->SS PIN7

Code:

//Master's program
//------------------------------------------
#include <16F877A.h>
//#device ADC = 10
#fuses HS,NOWDT,NOPROTECT,NOLVP                       
#use delay(clock = 20MHz)
//-------------------------------------------

#define CS PIN_D0
#define btn1 PIN_B0

#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)

BYTE data1=0xff;

Void slave1()
   {
   output_low(CS);
   spi_write(data1);
   output_high(CS);
   }
   
Void main()
   {
   port_b_pullups(oxff);
   delay_ms(100);
   setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_16);
   //setup_spi(SPI_MASTER|SPI_H_TO_L|SPI_CLK_DIV_16);
   while(1)
      {
      if(!input(btn1))
         {
         slave1();
         }     
      delay_ms(100);
      }
   }



Code:

//Slave's program
//------------------------------------------
#include <16F876A.h>
//#device ADC = 10
#fuses HS,NOWDT,NOPROTECT,NOLVP                       
#use delay(clock = 20MHz)
//-------------------------------------------

#define test_led PIN_B0

#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)

int1 spi_flag=0;

#INT_SSP
Void spi_rev()
   {
    data1=spi_read();
      if(data1==0xff)
         {
          spi_flag=1;
         }
   }

Void Main()
   {
   BYTE data1;
   setup_spi(SPI_SLAVE | SPI_MODE_0);
   enable_interrupts(global);
   enable_interupts(int_ssp);
   //setup_spi(SPI_SLAVE|SPI_L_TO_H|SPI_CLK_DIV_16);
   while(1)
      {
    if(spi_flag==1)
       {
        spi_flag=0;
         output_high(test_led);
         delay_ms(1000);
         data1=0;
         output_low(test_led);
         }
         else
            {
            output_low(test_led);
            }
     
     }
   }


Last edited by Ventouza on Thu Feb 07, 2019 10:12 am; edited 9 times in total
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Feb 06, 2019 2:42 pm     Reply with quote

random comments...
1) put '// master program' as top line of master.c program, so you can tell it's the master....

2) SPI clock speed is not necessary in an SPI slave (clock is in the master).

3) code/compile/run a '1 HZ LED' program to verify PICs actually run !

4) V5.008 was a very early compiler and not stable.

5) for testing, simply have the master loop at a 1Hz rate.

6) be sure to debounce the switch on B0.

7) be sure gnd is connected between both PICs.

8) this.... output_lowCS); ... has a typo, won't compile

9) using 0xFF has a 'trigger' is bad..maybe the line is held high and you'll get 0xFF all the time..

10) define pin_B0 as perhps 'status LED'. easier to follow your program

11) add comments ! They cost nothing yet tell you WHY you coded a line.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

Re: SPI 16f877a + 16f876a
PostPosted: Wed Feb 06, 2019 7:51 pm     Reply with quote

Ventouza wrote:

Master's code
setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16);

Slave's code
setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_CLK_DIV_16);

You have two different SPI modes for master and slave. That's not
correct. They should be the same.

I suggest that you put this code above main():
Code:

#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)


Then in your master, use Mode 0 like this:
Code:
setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_16);


In your slave, do it like this:
Code:
setup_spi(SPI_SLAVE | SPI_MODE_0);
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Thu Feb 07, 2019 2:00 am     Reply with quote

There is an issue.

In the code, if the button is held 'down', the master will send every 100mSec.
In the slave, once one byte is received, the code goes off and does not read
the SPI port for 1000mSec. Result there will be an overrun error when the
slave gets back....
Use #INT_SSP to actually handle the SPI (this way the data will be
genuinely received). Have a flag set by this that says to light the LED.
Then your main loop and test if this is saying to light the LED, and delay,
without causing the overrun issue.
Ventouza



Joined: 21 Apr 2014
Posts: 12
Location: Kefalonia, Greece

View user's profile Send private message

PostPosted: Thu Feb 07, 2019 2:33 am     Reply with quote

Thanks for your tips, i have made all these changes that you suggest to me on the first message. A couple of questions now.
What's the difference between mode 0 and mode 1? I can't find on the manual what SPI_XMIT_L_TO_H does.
According to the manual #INT_SSP----> I2C or SPI activity. What exactly activity means? causes an interrupt when the data is received?
I could use spi_data_is_in() but an interrupt is a way better.
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Feb 07, 2019 5:58 am     Reply with quote

quick comment
You need to download your PIC's datasheet and read the section on MSSP. Yes, I know 30-40-50 pages of dull, dreary reading but once you understand it, you're a far better programmer ! It describes and shows all aspects on how the SSP peripheral can be configured for either SPI or I2C modes. As for the SPI 'modes', those deal with the way data is 'seen' based upon if the clock line is high or low. As for the INT, when the peripheral 'sees' data it can inform the PIC by means of an Interrupt 'flag'. Interrupts are far better to use than 'polling', as they are faster and allow the PIC to be doing 'something' else instead of sending the data out.
Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Thu Feb 07, 2019 6:27 am     Reply with quote

and 'mode' numbers are part of SPI, not the PIC itself:

<https://en.wikipedia.org/wiki/Serial_Peripheral_Interface>

They are just a standard 'way# of signifying the four different sampling
strategies. Key is that the mode numbers _must_ match at each end.
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