|
|
View previous topic :: View next topic |
Author |
Message |
nigel_t
Joined: 20 Mar 2007 Posts: 1
|
SPI slave not receiving data from master |
Posted: Tue Mar 20, 2007 3:19 am |
|
|
Hi,
We have tried to set up a PIC18F4520 (on an eval board) as a slave in SPI mode and a DSP as a master. For some reason the PIC does not receive anything in its SSPBUF even though it is interrupted. When we look at the BF flag in the SSPSTAT register it never gets set. However if we use a PIC18F452 (on the same eval board) the code works perfectly so we know we are not configuring the slave as a master by accident plus the two devices are pin compatible. Comparing the register set for the two devices the only differrence appears to be the BF flag not being set but as to why it is bot being set is a mystery. We are not using the /SS select line and am running at 1.25Mbps. Does anyone know of why a 18F4520 should not work in this mode and has example code they can share where they have successfully used one as a slave.
I hope someone can help or its a case of surgically removing the 18F4520 and replacing it with a 18F452 on the actual target.
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Mar 20, 2007 4:45 am |
|
|
Which compiler version are you using?
Post a very short but complete and compilable program demonstrating your problem. |
|
|
mskala
Joined: 06 Mar 2007 Posts: 100 Location: Massachusetts, USA
|
|
Posted: Tue Mar 20, 2007 6:52 am |
|
|
I can't see why both won't work the same except for oscillator differences or compiler issues.
I just recently implemented a slave on an 18F4520 to test something else. This code uses 2 transactions to make the PIC look like a 128-byte RAM.
I am using SS, though.
Send (128-255) followed by the value to write, writes to reg 0-127.
Send (0-127) followed by any value to read a reg.
Output is to an LCD emulator, you don't need this. Also I used pin B2 to show that I was getting interrupts on scope. Everything works fine.
Code: |
#include <18F4520.h>
#device HIGH_INTS=TRUE
// using internal 8MHz osc
#fuses INTRC_IO,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
#use delay(clock=8000000)
#define SPI_MODE_0_0 0x4000 //CKP=0 CKE=1 clock idle=low, xmit on idle edge
#define SPI_MODE_0_1 0x0000 //CKP=0 CKE=0 clock idle=low, xmit on active edge
#define SPI_MODE_1_0 0x0010 //CKP=1 CKE=1 clock idle=high, xmit on idle edge
#define SPI_MODE_1_1 0x4010 //CKP=1 CKE=0 clock idle=high, xmit on active edge
#define VFD_RW PIN_E0
#define VFD_E PIN_E1
#define VFD_RS PIN_E2
#define LED_PIN PIN_C0
#define STATE_SPI_IDLE 0
#define STATE_SPI_WREG 1
#define STATE_SPI_RREG 2
#define STATE_SPI_FIN 3
static int8 spi_st;
// These work only for PIC18 devices
#byte SSPBUF = 0xFC9
#byte SSPCON = 0xFC6
#byte I2CBUF = 0xFC8
#byte SSPSTAT = 0xFC7
// Now the SSP handler code.
#DEFINE READ_SSP() (SSPBUF)
#DEFINE WAIT_FOR_SSP() while((SSPSTAT & 1)==0)
#DEFINE WRITE_SSP(x) SSPBUF=(x)
#DEFINE CLEAR_WCOL() SSPCON=SSPCON & 0x3F
// Variables used for the command buffer.
#define CMD_BUF_SIZE 16
static int8 cmd_buf[CMD_BUF_SIZE];
static int8 cmd_buf_beg;
static int8 cmd_buf_end;
#define cmd_ready (cmd_buf_beg != cmd_buf_end)
static int8 current_reg;
static int8 current_data;
static int8 r[128];
void vfd_w_inst(int8 value)
{
output_low(VFD_RS);
output_low(VFD_RW);
output_high(VFD_E);
output_d(value);
output_low(VFD_E);
}
void vfd_w_data(int8 value)
{
output_high(VFD_RS);
output_low(VFD_RW);
output_high(VFD_E);
output_d(value);
output_low(VFD_E);
}
void initdisp()
{
vfd_w_inst(0x3c); // function set, necessary first command
delay_us(2);
vfd_w_inst(0x0c); // display on, no cursor, no blink
delay_us(2);
vfd_w_inst(0x01); // clear display
delay_us(2);
vfd_w_inst(0x03); // cursor home
delay_us(2);
vfd_w_inst(0x06); // entry mode set
delay_us(2);
}
void displaynumber2(int8 num) // displays 8-bit number in decimal always 3 dig
{
int8 copy,a,b,c;
a=num/100;
copy=num-(a*100);
b=copy/10;
c=copy-(b*10);
vfd_w_data(a+48);
vfd_w_data(b+48);
vfd_w_data(c+48);
}
#int_timer0
void timer0_isr()
{ // blinking LED on off every approximately 1 second
led_timer++;
if (led_timer>15) {
output_bit(LED_PIN,led);
led=1-led;
led_timer=0;
}
}
#int_ssp HIGH // pre-empts other interrupts
void spi_isr()
{
int8 val;
output_high(PIN_B2);
switch (spi_st) {
case STATE_SPI_IDLE:
current_reg=spi_read();
if (current_reg>0x7f) {
spi_st=STATE_SPI_WREG;
WRITE_SSP(0);
} else {
spi_st=STATE_SPI_RREG;
current_data=r[current_reg]; // save val for creating command after next int
WRITE_SSP(current_data); // write buffer for next byte transfer but don't wait
}
output_low(PIN_B2);
break;
case STATE_SPI_WREG:
current_data=spi_read();
r[current_reg&0x7f]=current_data;
cmd_buf[cmd_buf_end++]=current_reg;
if (cmd_buf_end>=CMD_BUF_SIZE)
cmd_buf_end=0;
cmd_buf[cmd_buf_end++]=current_data;
if (cmd_buf_end>=CMD_BUF_SIZE)
cmd_buf_end=0;
spi_st=STATE_SPI_IDLE; // main prog should do something now
output_low(PIN_B2);
break;
case STATE_SPI_RREG:
val=spi_read(); // SPI read without writing buf, which was loaded before
cmd_buf[cmd_buf_end++]=current_reg;
if (cmd_buf_end>=CMD_BUF_SIZE)
cmd_buf_end=0;
cmd_buf[cmd_buf_end++]=current_data;
if (cmd_buf_end>=CMD_BUF_SIZE)
cmd_buf_end=0;
spi_st=STATE_SPI_IDLE;
output_low(PIN_B2);
break;
default:
break;
} //end switch
}
void main()
{
int8 i;
setup_oscillator(OSC_8MHZ);
led=0;
spi_st=STATE_SPI_IDLE;
output_low(PIN_B2); // this is my Int Service Routine flag
cmd_buf_beg = 0;
cmd_buf_end = 0;
setup_spi(SPI_MODE_0_0|SPI_SLAVE);
delay_ms(100);
initdisp();
vfd_w_data('R');
vfd_w_data('e');
vfd_w_data('a');
vfd_w_data('d');
vfd_w_data('y');
setup_timer_0(RTCC_INTERNAL|RTCC_8_BIT|RTCC_DIV_256); // at 8MHz, it times out (256 counts) in 32.768ms
clear_interrupt(INT_SSP);
enable_interrupts(INT_SSP); // interrupt on SPI transaction
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
while (1) {
if (cmd_ready) {
vfd_w_inst(0x03); // cursor home
if (cmd_buf[cmd_buf_beg]>0x7f) {
vfd_w_data('W');
vfd_w_data('r');
vfd_w_data('i');
vfd_w_data('t');
vfd_w_data('e');
} else {
vfd_w_data('R');
vfd_w_data('e');
vfd_w_data('a');
vfd_w_data('d');
vfd_w_data(' ');
}
vfd_w_data(' ');
displaynumber2(cmd_buf[cmd_buf_beg++]);
vfd_w_data(' ');
vfd_w_data('V');
vfd_w_data('a');
vfd_w_data('l');
vfd_w_data(' ');
displaynumber2(cmd_buf[cmd_buf_beg++]);
if (cmd_buf_beg>=CMD_BUF_SIZE)
cmd_buf_beg=0;
} else {
delay_ms(2);
}
}
} |
|
|
|
|
|
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
|