| 
	
	|  |  |  
	
		| 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
 
 |