| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Mar 16, 2011 3:13 am |   |  
				| 
 |  
				|  	  | hayee wrote: |  	  | PCM Programmer Its pin #7 of 18f252. /SS
 I have change the hardware from A0 to A5 on slave side, but I am not using that pin in the slave software, so will it work without declaring that pin? Is it necessary to change the pin of master from A0 to A5?
 | 
 Slave select, is _enabled by default_ on slave devices.
 It is possible to run SPI without slave select, _but_ very likely to go wrong, and makes code hard to ensure a resynchronise takes place, if a bit is missed. Your code is currently using SS, and won't work without it....
 
 Best Wishes
 |  |  
		|  |  
		| hayee 
 
 
 Joined: 05 Sep 2007
 Posts: 252
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Mar 16, 2011 4:53 am |   |  
				| 
 |  
				| This code is not working Master
 
  	  | Code: |  	  | #include <18f252.h>
 #fuses HS,NOWDT,NOLVP,PUT,NOBROWNOUT,protect
 #use delay(clock=20000000)
 #use rs232(xmit=PIN_C6, rcv=PIN_C7, baud=9600)
 
 #define SPI_SS PIN_A5
 
 #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)
 
 char c;
 int result;
 
 void main()
 {
 output_high(SPI_SS);
 
 setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_4);
 setup_adc_ports(NO_ANALOGS);
 
 while(1)
 {
 c=getc();
 c=toupper(c);
 
 switch(c)
 {
 case 'A':
 output_low(SPI_SS);
 spi_write(1);
 output_high(SPI_SS);
 delay_us(100);
 output_low(SPI_SS);
 result=spi_read(0);
 output_high(SPI_SS);
 printf("value =%u\r\n",result);
 break;
 
 case 'B':
 output_low(SPI_SS);
 spi_write(2);
 output_high(SPI_SS);
 delay_us(100);
 output_low(SPI_SS);
 result=spi_read(0);
 output_high(SPI_SS);
 printf("value =%u\r\n",result);
 break;
 
 case 'C':
 output_low(SPI_SS);
 spi_write(3);
 output_high(SPI_SS);
 delay_us(100);
 output_low(SPI_SS);
 result=spi_read(0);
 output_high(SPI_SS);
 printf("value =%u\r\n",result);
 break;
 }
 }
 }
 
 | 
 
 Slave
 
 
  	  | Code: |  	  | #include <18f252.h>
 #fuses HS,NOWDT,NOLVP,PUT,NOBROWNOUT,protect
 #use delay(clock=20000000)
 #use rs232(xmit=PIN_C6, rcv=PIN_C7, baud=9600)
 
 #byte SSPBUF = 0xFC9//register value for 18f252
 
 #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)
 
 int counter;
 int buffer;
 #int_ssp
 void ssp_isr(void)
 {
 
 int command;
 
 command=SSPBUF;
 
 switch(command)
 {
 case 1:
 SSPBUF=5;
 break;
 
 case 2:
 SSPBUF=46;
 break;
 
 case 3:
 SSPBUF=12;
 break;
 }
 output_toggle(PIN_C0);
 
 }
 
 void main()
 {
 setup_spi(SPI_SLAVE | SPI_MODE_0);
 clear_interrupt(INT_SSP);
 enable_interrupts(INT_SSP);
 enable_interrupts(GLOBAL);
 
 while(1)
 {
 
 }
 }
 
 | 
 
 But this code is working
 
 Master
 
  	  | Code: |  	  | #include <18f252.h>
 #fuses HS,NOWDT,NOLVP,PUT,NOBROWNOUT,protect
 #use delay(clock=20000000)
 #use rs232(xmit=PIN_C6, rcv=PIN_C7, baud=9600)
 
 #define SPI_SS PIN_A5
 
 #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)
 
 int counter;
 
 void main()
 {
 output_high(SPI_SS);
 
 setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_4);
 setup_adc_ports(NO_ANALOGS);
 
 while(1)
 {
 counter++;
 output_low(SPI_SS);
 spi_write(counter);
 output_high(SPI_SS);
 delay_ms(2000);
 
 }
 }
 
 | 
 
 Slave
 
  	  | Code: |  	  | #include <18f252.h>
 #fuses HS,NOWDT,NOLVP,PUT,NOBROWNOUT,protect
 #use delay(clock=20000000)
 #use rs232(xmit=PIN_C6, rcv=PIN_C7, baud=9600)
 
 //#byte SSPBUF = 0xFC9//register value for 18f252
 
 #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)
 
 int counter;
 int buffer;
 #int_ssp
 void ssp_isr(void)
 {
 
 buffer=spi_read();
 output_toggle(PIN_C0);
 
 }
 
 void main()
 {
 setup_spi(SPI_SLAVE | SPI_MODE_0);
 clear_interrupt(INT_SSP);
 enable_interrupts(INT_SSP);
 enable_interrupts(GLOBAL);
 
 while(1)
 {
 if(counter==1)
 {
 printf("buffer=%u",buffer);
 counter=0;
 }
 }
 }
 
 | 
 
 Dont know what is happening, where i am wrong?
 |  |  
		|  |  
		| nahumof 
 
 
 Joined: 09 Apr 2011
 Posts: 15
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Apr 13, 2011 6:25 pm |   |  
				| 
 |  
				| whats the advantage to use directly the register SSPBUF like the program of PCM (for select comands) instead use read spi and write spi tks
  |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Apr 14, 2011 2:12 pm |   |  
				| 
 |  
				| You are right.  The .LST file shown below shows that calling spi_read() and reading SSPBUF directly, both produce the same code:
 
  	  | Code: |  	  | .................... #int_ssp
 .................... void ssp_isr(void)
 .................... {
 ....................
 ....................  int command;
 ....................
 ....................  command=SSPBUF;
 00AE:  MOVFF  SSPBUF,command
 ....................
 ....................  command=spi_read();
 00B2:  MOVFF  SSPBUF,command
 ....................
 | 
 |  |  
		|  |  
		| nahumof 
 
 
 Joined: 09 Apr 2011
 Posts: 15
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Apr 14, 2011 3:33 pm |   |  
				| 
 |  
				| jejeje good to know   tks pcm
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Apr 15, 2011 1:58 am |   |  
				| 
 |  
				| If you go 'back in time', the functions differed, with the compiler SPI_READ always checking the data available bit before reading. Sensible if using the code in a main program, but pointless in an ISR, where the ISR triggering implies that a byte has been clocked in. Hence people wanting to avoid the extra test talked directly to the registers. It appears that at some point the compiler behaviour has been improved in this regard. 
 Best Wishes
 |  |  
		|  |  
		| nahumof 
 
 
 Joined: 09 Apr 2011
 Posts: 15
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Apr 15, 2011 9:05 am |   |  
				| 
 |  
				| so if I'm going to use ISR the best thing to do is work with the register directly... 
 I GET THIS .LST!!!
 
 ISR SPI READ
 
  	  | Code: |  	  | .................... #int_ssp
 .................... void ssp_isr(void)
 ....................  {
 ........................char a;
 .....................   a=spi_read();
 *
 0035:  MOVF   13,W
 0036:  BSF    03.5
 0037:  MOVWF  2C
 
 | 
 
 ISR USING SSPBUF
 
  	  | Code: |  	  | .................... #int_ssp
 .................... void ssp_isr(void)
 ....................  {
 ....................   char a;
 ....................   a=SSPBUF;
 *
 0035:  MOVF   13,W
 0036:  BSF    03.5
 0037:  MOVWF  2C
 
 | 
 
 SSPBUF IN MAIN without ISR
 
  	  | Code: |  	  | ....................  while(true)
 ....................    {
 ..........................char a;
 .......................   a=SSPBUF;
 035F:  MOVF   13,W
 0360:  MOVWF  72
 
 | 
 
 SPI_READ IN MAIIN without ISR
 
  	  | Code: |  	  | ....................   while(true)
 ....................    {char a;
 ....................    a=spi_read();
 035F:  MOVF   13,W
 0360:  MOVWF  72
 
 | 
 
 to me looks like the same... I'm wrong?
 ...where is sspbuf? ...
  |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Apr 15, 2011 9:13 am |   |  
				| 
 |  
				| No, as I said 'if you go back in time'. The early spi_read function tested the BF bit. CCS have dropped this, probably when they added the 'spi_data_is_in' function, so that you have the _option_ to test the bit if you want. As now coded, the spi_read is identical to the direct read. It was an annoyance in the early days when trying to code a SPI ISR, hence a lot of people took the safe route, and went to direct register I/O.
 
 Best Wishes
 |  |  
		|  |  
		| nahumof 
 
 
 Joined: 09 Apr 2011
 Posts: 15
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Apr 15, 2011 9:17 am |   |  
				| 
 |  
				| ok tks  |  |  
		|  |  
		| nahumof 
 
 
 Joined: 09 Apr 2011
 Posts: 15
 
 
 
			    
 
 | 
			
				| mmm |  
				|  Posted: Wed May 11, 2011 7:55 pm |   |  
				| 
 |  
				| Hi I had to rebuild my circuit because I was using 2 PIC'S comunicating with  software SPI, after a few bumps I get the answer. There is no way to get a software slave spi!!! using #use_SPI. 
 So I rebuild my slave for use hardware SPI. I connect to my software master SPI and now I realize that I have to waste one byte to get an answer from slave HW SPI!!! I just don't get it...
   
 I got 2 questions for you:
 
 1.- There is any way to set the speed of my master SPI with #use_spi besides the baud rate?
 
 2.- There is a way to send a byte from master get in slave and return to the answer to the master in one instruction? Or always I have to sent a dummy byte?
 
 master
 
  	  | Code: |  	  | #include <18f4550.h>
 #fuses HS,NOPUT,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOUSBDIV,PLL1,CPUDIV1,NOVREGEN
 #use delay(clock=8000000)
 
 #use spi(DO=PIN_D6,DI=PIN_D5,CLK=PIN_D4,MODE=0,BITS=8,MSB_FIRST)
 
 #define SPI_SS PIN_C0
 
 void inicializar()
 {
 set_tris_d(0b00100000);
 set_tris_c(0b00000000);
 delay_us(100);
 output_high(SPI_SS);
 output_low(PIN_D4);
 output_low(PIN_D6);
 output_float(PIN_D5);
 }
 
 void main()
 {
 int a=0;
 int ret;
 inicializar();
 
 while(true)
 {
 output_LOW(SPI_SS);
 SPI_XFER(0);                         //dumy waste of time!!!
 output_HIGH(SPI_SS);
 delay_us(200);
 output_LOW(SPI_SS);
 ret=SPI_XFER(a);                  //usefull data in and out!!!
 output_HIGH(SPI_SS);
 }
 }
 
 | 
 slave
 
  	  | Code: |  	  | #include <16f876A.h>
 #device ADC=8
 #fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG
 #use delay(clock=20000000)
 
 #byte SSPBUF=0x13
 #define SPI_MODE_0_0 0x4000
 
 #int_ssp
 void ssp_isr(void)
 {
 int comando;
 static int count;
 comando=SSPBUF;   //also i use comando=spi_read(count)
 count++;                                                //geting wrong data!!!
 SSPBUF=count;
 }
 
 inicializacion()
 {
 // habilita iterrupcion por spi
 clear_interrupt(INT_SSP);
 enable_interrupts(INT_SSP);
 enable_interrupts(GLOBAL);
 
 // Initialize the hardware SSP for SPI Slave mode.
 setup_spi(SPI_SLAVE |SPI_L_TO_H|SPI_XMIT_L_TO_H);
 }
 void main()
 {
 inicializacion();
 
 while(true)
 {}
 }
 | 
 result
 
   any help wold be great!!!
 |  |  
		|  |  
		| nahumof 
 
 
 Joined: 09 Apr 2011
 Posts: 15
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed May 11, 2011 8:36 pm |   |  
				| 
 |  
				| i need to return the same data i'm sending 
 i also try with spi_read();
 
 with no results...
  |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed May 11, 2011 9:32 pm |   |  
				| 
 |  
				|  	  | Quote: |  	  | 1.- There is any way to set the speed of my master SPI with #use_spi
 besides the baud rate?
 
 | 
 I don't see any method of setting the baud rate listed in the manual
 for #use spi, except for the BAUD=n method.
 
 I don't use the #use spi() method for hardware SPI.  I use setup_spi().
 
 
  	  | Quote: |  	  | 2.- There is a way to send a byte from master get in slave and return to
 the answer to the master in one instruction? Or always I have to sent a
 dummy byte?
 
 I need to return the same data i'm sending
 i also try with spi_read();
 with no results
 
 | 
 
 spi_read(); won't clock in any data to the Master.  You need to give it a
 parameter to make the Master generate the clock (SCLK).
 
 For example, the line below will transmit a 0x00 byte to the slave, and it
 will force the slave to transmit the byte in it's buffer to the master.
 
  	  | Code: |  	  | result = spi_read(0); | 
 
 SPI is just two shift registers.  The master has one, and the slave has
 one.  There is no way get back the transmitted data with just 8 clocks
 from the master.   It would take 16 clocks, total.  Look at this diagram
 http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Data_transmission
 Here is another diagram of the two SPI shift registers:
 http://elm-chan.org/docs/spi_e.html
 Here is an SPI tutorial from Microchip:
 http://ww1.microchip.com/downloads/en/devicedoc/spi.pdf
 |  |  
		|  |  
		| nahumof 
 
 
 Joined: 09 Apr 2011
 Posts: 15
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu May 12, 2011 10:52 am |   |  
				| 
 |  
				| tks for the answer and the info and yes i understoot everything you say but:
 the master send 0xff
 
 a=spi_xfer(0xff);
 
 and the slave get the 0xff and save into resp and return 0x05 to the master:
 
 resp=spi_read(0x05);
 
 what is the result for a? i guess it should be  0x05?
 I'm not getting 0x05!!! my code is wrong?
 slave
 
  	  | Code: |  	  | #include <16f876A.h>
 #device ADC=8
 #fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG
 #use delay(clock=20000000)
 
 #byte SSPBUF=0x13
 #define SPI_MODE_0_0 0x4000
 
 int resp;
 
 #int_ssp
 void ssp_isr(void)
 {
 resp=spi_read(0x05);
 }
 
 inicializacion()
 {
 // habilita iterrupcion por spi
 clear_interrupt(INT_SSP);
 enable_interrupts(INT_SSP);
 enable_interrupts(GLOBAL);
 
 // Initialize the hardware SSP for SPI Slave mode.
 setup_spi(SPI_SLAVE |SPI_MODE_0_0);
 }
 void main()
 {
 inicializacion();
 while(true)
 {}
 }
 | 
 master
 
  	  | Code: |  	  | #include <18f4550.h>
 #fuses HS,NOPUT,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOUSBDIV,PLL1,CPUDIV1,NOVREGEN
 #use delay(clock=8000000)
 
 #use spi(DO=PIN_D6,DI=PIN_D5,CLK=PIN_D4,MODE=0,BITS=8,MSB_FIRST)
 
 #define SPI_SS PIN_C6
 
 #byte porta=0xf80
 #byte portb=0xf81
 #byte portc=0xf82
 #byte portd=0xf83
 
 void inicializar()
 {
 set_tris_d(0b00100000);
 set_tris_c(0b00000000);
 delay_us(100);
 output_high(SPI_SS);
 output_low(PIN_D4);
 output_low(PIN_D6);
 output_float(PIN_D5);
 }
 
 void main()
 {
 int a;
 inicializar();
 
 while(true)
 {
 output_LOW(SPI_SS);
 a=SPI_XFER(0xff);
 output_HIGH(SPI_SS);
 delay_ms(2000);
 }
 }
 | 
 
 wrong result???
   [/code] 
 thanks
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu May 12, 2011 6:15 pm |   |  
				| 
 |  
				| I note the problems.  I'm still working on it. |  |  
		|  |  
		| nahumof 
 
 
 Joined: 09 Apr 2011
 Posts: 15
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri May 13, 2011 9:56 am |   |  
				| 
 |  
				| ok PCM tks 
 well after a few test i discover that my program send a byte (0x0f)to the slave and save a returning byte in B:
 B=SPI_XFER(0x0f);
 
 i receive the byte in the slave and return the same to master
 a=SSPBUF;
 
 when this happen i receive the half of whatever i send...
 
 if i send 0x0f i get 0x07
 if i send 0x08 i get 0x04
 if i send 0x02 i get 0x01
 
 only if i send 0xfx i get f something wrong
 if i send 0xf0 i get 0xf8
 
 i don't know what is causing this? maybe a configuration? speed?compiler?
 some help would be great
 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |