|
|
View previous topic :: View next topic |
Author |
Message |
wei Guest
|
Unable to send data out of SPI slave |
Posted: Wed Nov 26, 2008 12:03 pm |
|
|
Hi,
I have a 18F452 master and a 16F873A slave talking to each another on a spi bus. I programmed the master a while back, and it was reliably talking to a SPI UART and a digital compass module. Now I added a 16F873A slave to the bus, and I cannot get the slave to send a response. Specifically, I can receive correct data from the master but is unable to send the response. Here is the code for the slave.
Code: |
#include <16F873A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#define NORTHLED PIN_B7
#define WESTLED PIN_B6
#define SOUTHLED PIN_B5
void init_LED();
unsigned int8 flag;
void init_LED()
{
output_low(NORTHLED);
output_low(WESTLED);
output_low(SOUTHLED);
}
#INT_SSP
void isr()
{
unsigned int8 rcv_data;
if (spi_data_is_in())
{
rcv_data = spi_read();
if (rcv_data == 0x04)
{
output_high(WESTLED); //LED lights up here, reached this line
delay_ms(1);
spi_write(0xBB);
output_high(SOUTHLED); //This line doesn't execute, LED doesn't light
}
}
}
void main()
{
flag = 0;
setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_XMIT_L_TO_H); //Mode 0, same as master
init_LED();
output_high(NORTHLED);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
while(1);
}
|
It is stuck when sending back a command to the master. Looking at the LST file, I suspect the BF flag is not set when the slave received the clock pulses. I have verified with a scope that the SS line and SCLK line was correctly generated by the Master. But the DOUT line at the slave went high and stayed there 1ms after byte 0x04 was received. ie. spi_write(0xBB); made DOUT high without waiting for the master's clock pulses.
Here is the code snippet from the master (supposed to work so I didn't post the full code)
Code: |
output_low(CS_LINE);
spi_write(0x04);
delay_ms(10);
data = spi_read(1);
|
Expectedly, 0xFF was returned because DOUT line was driven high by slave.
Any ideas?
Thanks |
|
|
Ttelmah Guest
|
|
Posted: Wed Nov 26, 2008 1:44 pm |
|
|
First, you don't need to check 'data_is_in' in the ISR. The interrupt will occur, _when_ the master has clocked a byte to the slave.
Personally, I don't 'like' the CCS routines for ISR use, they add a lot of checking, which can lead to problems.
All you need, is:
Code: |
#byte SSPBUF = 0xFC9
#byte SSPCON1 = 0xFC8
#bit OV=SSPCON1.6
#INT_SSP
void isr(void) {
unsigned int8 rcv_data;
rcv_data = SSPBUF;
if (rcv_data == 0x04) {
SSPBUF=0xBB;
}
}
if (OV) OV=0;
}
|
The OV test, will clear an overrun error if it occurs.
The slave will set the first bit of the outgoing data immediately. It has to do this _in advance_ of the clock from the master.
Best Wishes |
|
|
wei Guest
|
|
Posted: Fri Nov 28, 2008 2:19 am |
|
|
Thanks to Ttelmah for your help. I have found out what was wrong with the SPI slave. It turns out the SPI hardware required a high to low transition on the SS line every time a byte is received, or else the data in SSPBUF won't be clocked out. I must have missed this line in the datasheet. |
|
|
|
|
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
|