View previous topic :: View next topic |
Author |
Message |
mlkushan
Joined: 16 Nov 2008 Posts: 22 Location: Sri Lanka
|
SPI Communication problem (Between 16F877A and 16F873A) |
Posted: Sun Dec 21, 2008 10:42 am |
|
|
Hi all,
Currently I'm developing a code for an wireless sensor network application. Here I need to interconnect 16F877A and 16F873A. As the initial step I have written a sample code to simulate SPI communication in between these two micro controllers. Here 16F877A is the master and 16F873A is the slave.
I have correctly interconnected pins of two micro controllers;
SDO to SDI of the other
and SCK of master to the SCK of slave.
Both micro controllers are powered by same power supply.
My compiler version is the CCS PCM C Compiler, Version 4.057, 36748
As the first step I need to light up LED for 5 sec at the slave end. Here I send a byte to the slave after each 10sec. If the slave receives that byte it should light up the LED for 5 sec.
But once this is implemented it doesn't give any feedback. I couldn't figure out the errors in my code. I have posted the code bellow.
Please anyone be kind enough to correct me and show me the right path. Any help regarding my matters are highly appreciated.
Thanks you all in advance.
Kushan
Master code
Code: |
#include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES WRT_50% //Lower half of Program Memory is Write Protected
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#include <stdio.h>
#include <stdlibm.h>
#include <string.h>
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H) // low leading edge
#define SPI_MODE_1 (SPI_L_TO_H) // low trailing edge
#define SPI_MODE_2 (SPI_H_TO_L) // high leading edge
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H) // high trailing edge
void main()
{
long pwmDuty = 50;
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(SPI_MASTER|SPI_MODE_0|SPI_CLK_DIV_4);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_1,24,1);
setup_ccp1(CCP_PWM);
set_pwm1_duty(pwmDuty);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
// TODO: USER CODE!!
while(true){
delay_ms(10000); //wait 10 sec before transmit data to the slave
spi_write(0xAA);
delay_us(100);
}
}
|
Slave code
Code: |
#include <16F873A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES WRT_50% //Lower half of Program Memory is Write Protected
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#include <stdio.h>
#include <stdlibm.h>
#include <string.h>
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H) // low leading edge
#define SPI_MODE_1 (SPI_L_TO_H) // low trailing edge
#define SPI_MODE_2 (SPI_H_TO_L) // high leading edge
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H) // high trailing edge
int1 spiDataAvail = false;
long rcv_data;
#int_SSP //SPI activity interrupt
void SSP_isr(void){
rcv_data = spi_read();
spiDataAvail = true;
}
void main()
{
long pwmDuty = 50;
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(SPI_SLAVE|SPI_MODE_0|SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_1,24,1);
setup_ccp1(CCP_PWM);
set_pwm1_duty(pwmDuty);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
// TODO: USER CODE!!
while(true){
if(spiDataAvail){
spiDataAvail = false;
if(rcv_data==0xAA){
output_high(PIN_B2);
delay_ms(5000); //LED is on for 5 sec then off until data comes again
output_low(PIN_B2);
rcv_data = 0x00; //set to some diiferrent value
}
}
}
}
|
_________________ Kushan Sharma
mlkushan@gmail.com |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
Re: SPI Communication problem (Between 16F877A and 16F873A) |
Posted: Sun Dec 21, 2008 2:06 pm |
|
|
mlkushan wrote: | ...But once this is implemented it doesn't give any feedback.... |
What sort of feedback are you expecting? _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
mlkushan
Joined: 16 Nov 2008 Posts: 22 Location: Sri Lanka
|
|
Posted: Sun Dec 21, 2008 9:44 pm |
|
|
First thank you for your help,
Feedback in the sense, once a slave micro controller receives a byte from master through the SPI bus, a LED should light up for five sec. This LED is light up by the bellow code segment;
Code: |
..................
..................
output_high(PIN_B2);
delay_ms(5000); //LED is on for 5 sec then off until data comes again
output_low(PIN_B2);
..................
..................
|
But unfortunately it doesn't light up. So I can't figure out the exact reason for this.
So any help regarding my matters is highly appreciated...!
Thanks in advance
kushan _________________ Kushan Sharma
mlkushan@gmail.com |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 22, 2008 12:06 am |
|
|
Post a list of the connections between the two PICs, and post the pin
numbers. Look at the actual wires (or tracks) on the board and count
down the pin numbers on the I.C. In other words, I want to absolutely
verify that the physical connections are correct.
Also post if the PICs are on different boards, or the same board.
Is there a ground connection between the two boards (or PICs) ? |
|
|
mlkushan
Joined: 16 Nov 2008 Posts: 22 Location: Sri Lanka
|
|
Posted: Mon Dec 22, 2008 12:39 am |
|
|
Thank you for your help,
16F873A
PIN_C4 – (pin 15) SDI data input
PIN_C5 – (pin 16) SDO data output
PIN_C3 – (pin 14) SCK Clock
16F877A
PIN_C4 – (pin 23) SDI data input
PIN_C5 – (pin 24) SDO data output
PIN_C3 – (pin 18) SCK Clock
PIN_C3 of 16F877A is connected to PIN_C3 of 16F873A
PIN_C4 of 16F877A is connected to PIN_C5 of 16F873A
PIN_C5 of 16F877A is connected to PIN_C4 of 16F873A
Both PICs are mounted on the same board.
Both of them are powered by the same power supply.
PIN_B2 of the slave micro controller is connected to the LED.
Actually all the physical connections are correct according to the data sheet of the micro controllers.
Once again thanks for your help.
Kushan _________________ Kushan Sharma
mlkushan@gmail.com |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 22, 2008 1:07 am |
|
|
I would add the Slave Select signal.
1. Choose a general purpose i/o pin on the master PIC to use for it.
Connect that pin to the \SS pin on the slave PIC.
2. Add lines of code to the master PIC, to surround the spi_write() line
with statements that set \SS low, and then high again when the operation
is done.
3. Add a line of code in the Master PIC to initialize the Slave Select pin
to a high level at the start of main().
4. Edit the setup_spi() statement in the slave to delete the parameter
that disables Slave Select.
5. Re-compile the code for both master and slave, and re-program
both PICS with the revised code. |
|
|
Ttelmah Guest
|
|
Posted: Mon Dec 22, 2008 3:47 am |
|
|
There is a general problem, when using SPI, with initial synchronisation.
In your case, if one chip 'wakes' fractionally before the other, or there is noise on the SCK line as the chips wake up, the two chips will never get synchronised, so the second will never see '0xAA'
Now, two solutions exist for this:
1) Use the SS line. This is what it is for.
2) Have a 'sync' strategy.
Now, in your case, the 'idle' level of the clock line, will be low. So, a 'workable' strategy would be:
Add a pull-up resistor to the SCK line - perhaps 100KR. Just enough to ensure that the line will float _high_ if not driven.
Have the master, pause for a moment, then setup the SPI, then pause again. So, something like:
Code: |
delay_us(100); //This ensures the slave has time to wake before master
setup_spi(SPI_MASTER|SPI_MODE_0|SPI_CLK_DIV_4);
delay_us(100);
|
Then have the slave, wait for the line to go _low_ before setting up it's SPI.
Code: |
while (input(PIN_C3)) ; //This will wait for the line to be driven
setup_spi(SPI_SLAVE|SPI_MODE_0|SPI_SS_DISABLED);
|
Ideally, there are even more complex strategies to ensure that sync is reacquired if lost, but this should get it going, if you don't want to use another pin.
Best Wishes |
|
|
mlkushan
Joined: 16 Nov 2008 Posts: 22 Location: Sri Lanka
|
|
Posted: Mon Dec 22, 2008 3:53 am |
|
|
Thanks for your help,
I made required changes as bellow.
But unfortunately once it is implemented, the master pic get drastically overheated.
At the Master
Code: |
.............
output_high(PIN_A5); //slave select pin is high at the start.
while(true){
delay_ms(10000); //wait 10 sec before transmit data to the slave
output_low(PIN_A5); //set \SS low, and then high again when the operation is done.
spi_write(0xAA);
delay_us(100);
output_high(PIN_A5);
}
........
|
At the slave
Code: |
.........
setup_spi(SPI_SLAVE|SPI_MODE_0);
.........
|
Once again thanks a lot.
Kushan _________________ Kushan Sharma
mlkushan@gmail.com |
|
|
Ttelmah Guest
|
|
Posted: Mon Dec 22, 2008 6:31 am |
|
|
What is A5 connected to?.
If the chip is getting hot, it is almost certainly tied high or low, and when you drive it, the chip is driving into a short circuit....
Check your wiring.
Best Wishes |
|
|
mlkushan
Joined: 16 Nov 2008 Posts: 22 Location: Sri Lanka
|
|
Posted: Mon Dec 22, 2008 7:16 am |
|
|
Thanks for helping me,
PIN_A5 of 16F877A is connected to the PIN_A5 of 16F873A as the slave selection pin. At the initial stage i did testings by disabling the slave selection. Since it didn't work. I moved on to the second method with the slave selection enabled (that method was suggested here by PCM programmer).
Now i have permanently mounted the cct. So now it does not heat up. Now i am sure about the wiring and that there can't be any errors. But still the LED doesn't light up.
Thanks you all and highly appreciated all your helps
Kushan _________________ Kushan Sharma
mlkushan@gmail.com |
|
|
Ttelmah Guest
|
|
Posted: Mon Dec 22, 2008 8:06 am |
|
|
Permanently mounting should have nothing to do with the chip heating. The chip heating, when a pin is driven, more than it does when the pin isn't driven, if the pin is only switched at a slow rate, _implies_ the line is driving a significant load. Check it with a voltmeter. Does it go high when you drive it high, and low when you drive it low?. What happens to the board current when you drive it?. Seriously, this is probably why it didn't work in the first place....
Best Wishes |
|
|
|