View previous topic :: View next topic |
Author |
Message |
Ventouza
Joined: 21 Apr 2014 Posts: 12 Location: Kefalonia, Greece
|
SPI 16f877a + 16f876a |
Posted: Wed Feb 06, 2019 12:13 pm |
|
|
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: 9241 Location: Greensville,Ontario
|
|
Posted: Wed Feb 06, 2019 2:42 pm |
|
|
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
|
Re: SPI 16f877a + 16f876a |
Posted: Wed Feb 06, 2019 7:51 pm |
|
|
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: 19535
|
|
Posted: Thu Feb 07, 2019 2:00 am |
|
|
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
|
|
Posted: Thu Feb 07, 2019 2:33 am |
|
|
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: 9241 Location: Greensville,Ontario
|
|
Posted: Thu Feb 07, 2019 5:58 am |
|
|
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: 19535
|
|
Posted: Thu Feb 07, 2019 6:27 am |
|
|
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. |
|
|
|