|
|
View previous topic :: View next topic |
Author |
Message |
Ttelmah
Joined: 11 Mar 2010 Posts: 19534
|
|
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: 19534
|
|
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: 19534
|
|
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
|