View previous topic :: View next topic |
Author |
Message |
lifespeed
Joined: 17 Aug 2005 Posts: 19
|
SPI slave trouble, port 2 18F8722 |
Posted: Fri Oct 07, 2005 3:22 pm |
|
|
I'm having trouble reading in valid data on the second SPI port of the PIC18F8722. Compiler is ver 3.234.
SPI port 1 is currently used to write to 5 other ICs, one of which can also be successfully read using 3-wire SPI with the PIC providing the clock. So, it does seem SPI works . . .
However, this product needs to behave as an SPI slave to the outside world. So, I attempted to configure the SPI port 2 as slave, with the external clock (about 30 KHz in this case) latching the data on the rising edge. I am failing miserably, I cannot even seem to get the spi_data_is_in2() to go true when the three bytes are clocked in while SS2 (D7) is held low by the external master. I have checked the waveforms at the ICE2000 emulator, and they are correct even tho slightly rounded by RC time constants.
A bit-banging routine was written using D5,6 and 7 which successfully imports the data, but I would really prefer to use hardware SPI as this provides a better assurance that data will be received even if the PIC is off doing something else when it starts clocking in.
Will the PIC clock data out on port 2 in 2-wire mode while receiving input, fighting the input data, or will it output the data on SDO2 (RD4) in 3-wire mode causing no trouble with the SDA2 (RD5) input data?
Quote: | setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_timer_4(T4_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
set_tris_a(0x00); // RA0-RA7 are outputs
set_tris_f(0x00); // so are RF0-RF7
set_tris_h(0x01); //
set_tris_d(0x80); // D7 is SS2...
set_tris_c(0x10); // RC4 is an input
setup_spi(SPI_MASTER | SPI_CLK_DIV_64 | SPI_XMIT_L_TO_H | SPI_L_TO_H);
setup_spi2(SPI_SLAVE | SPI_CLK_DIV_64 | SPI_XMIT_L_TO_H | SPI_L_TO_H); |
Here is the read SPI portion:
Quote: | while (1)
{
// read desired frequency
//strcpy(FreqString, "13.0");
i = 1;
while ( !spi_data_is_in2() );
hdr = (char)spi_read2();
for (i = 0; i < 11; i++)
{
ChanString[i] = (char)spi_read2();
} |
_________________ Lifespeed
Last edited by lifespeed on Fri Oct 07, 2005 4:02 pm; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 07, 2005 3:44 pm |
|
|
What's your PCH compiler version ? |
|
|
lifespeed
Joined: 17 Aug 2005 Posts: 19
|
|
Posted: Fri Oct 07, 2005 4:01 pm |
|
|
Compiler is 3.234, pretty new. _________________ Lifespeed |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 07, 2005 4:43 pm |
|
|
The problem is with your parameters for SPI slave mode.
Some of those parameters are only intended for Master mode.
CCS doesn't do any checking. So what's happening is that
you're putting the MSSP into i2c slave mode by accident.
The following code will put it into SPI slave mode, with the
\SS pin enabled.
Code: | setup_spi2(SPI_SLAVE | SPI_L_TO_H); |
|
|
|
lifespeed
Joined: 17 Aug 2005 Posts: 19
|
|
Posted: Fri Oct 07, 2005 5:03 pm |
|
|
Thanks! I would have never guessed, and I sure didn't see that in the CCS manual. I would much prefer hardware SPI to bit-banging.
_________________ Lifespeed |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 07, 2005 5:28 pm |
|
|
I saw the problem by looking at the .LST file and the SPI section
of the data sheet.
Code: | ... setup_spi2(SPI_SLAVE | SPI_CLK_DIV_64 | SPI_XMIT_L_TO_H | SPI_L_TO_H);
0078 9A63 00612 BCF F63.5
007A 9895 00613 BCF F95.4
007C 8A95 00614 BSF F95.5
007E 8E95 00615 BSF F95.7
0080 8C95 00616 BSF F95.6
0082 0E26 00617 MOVLW 26 <--- Problem
0084 6E63 00618 MOVWF F63 // SSP2CON1 register
0086 0E40 00619 MOVLW 40
0088 6E64 00620 MOVWF F64
|
Then I looked at the parameters for the setup_spi() function in the
18F8722.H file. CCS obviously has the correct value of 0x24 for
slave mode. So with that information I looked at the data sheet
again and did a couple test compilations, and decided that some
of the parameters can only be used with SPI Master mode.
So that's how I found the answer.
Code: |
#define SPI_MASTER 0x20
#define SPI_SLAVE 0x24
#define SPI_L_TO_H 0
#define SPI_H_TO_L 0x10
#define SPI_CLK_DIV_4 0
#define SPI_CLK_DIV_16 1
#define SPI_CLK_DIV_64 2
#define SPI_CLK_T2 3
#define SPI_SS_DISABLED 1
#define SPI_SAMPLE_AT_END 0x8000
#define SPI_XMIT_L_TO_H 0x4000 |
|
|
|
lifespeed
Joined: 17 Aug 2005 Posts: 19
|
|
Posted: Fri Oct 07, 2005 6:24 pm |
|
|
I'm glad you explained how you came to that conclusion. That technique might help me solve problems in the future.
Thanks again, _________________ Lifespeed |
|
|
lifespeed
Joined: 17 Aug 2005 Posts: 19
|
SPI slave still not working correctly |
Posted: Thu Oct 13, 2005 1:42 pm |
|
|
I am still having trouble getting valid data in using SPI2 slave mode. As best I can tell, it tends to skip the first bit of a 3-byte series, and zero the last bit. The last data bit of the series does not remain high until 50% past the 33 KHz clock, leading me to believe that data latching is not really happening halfway thru the active clock, as stated. Based on the bit patterns, it looks as though the data are latched in between the active clocks ??? Please help! The product is useless without comms to the outside world
Attached is the code, MSSP register states, a scope screenshot, and several bit patterns sent and read. I have tried SPI_H_TO_L, although the data is being sent on a rising-edge clock.
I should note I am using an ICE2000 emulator running at 25 MHz with HS external clock. Also, I'm sending MSB first, although if the bit order were reversed I would think I could easily see it?
I also noticed using spi_read2() with an argument such as
spi_read2(0x55) causes only one byte instead of three to be read in, then another 3-byte send reads in the remaining two bytes:
Quote: | sending EF FF FF
sb[i] = spi_read2();
CF FF FE
sending EF FF FF
sb[i] = spi_read2(0x55);
FF
sending EF FF FF again
sb[i] = spi_read2(0x55);
FF CF FE |
here are the bit patterns:
Quote: | send EF FF FF
get CF FF FE
send CF FF FF
get 8F FF FE
send C7 FF FF
get 87 FF FE
send AA AA AA
get 00 00 00
send 55 55 55
get 01 01 00
send 66 66 66
get 68 68 68 |
MSSP registers:
Quote: | SSP2STAT = 0x00
SSP2CON1 = 0x24
SSP2CON2 = 0x00 |
Quote: | set_tris_a(0x00); // RA0-RA7 are outputs
set_tris_f(0x00); // so are RF0-RF7
set_tris_h(0x03); //
set_tris_d(0xE0); // D5, D6, D7 are inputs
set_tris_c(0x10); // RC4 is an input
setup_spi2(SPI_SLAVE | SPI_L_TO_H ); |
Quote: | for (i = 0; i < 3; i++)
{
while ( !spi_data_is_in2() );// have to make this an interrupt, wait until it goes low
if (spi_data_is_in2())
{
sb[i] = spi_read2();
}
} |
[/img] _________________ Lifespeed |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
lifespeed
Joined: 17 Aug 2005 Posts: 19
|
|
Posted: Fri Oct 14, 2005 4:47 pm |
|
|
I am using the PCM18SX0 processor module. So far I am unable to find an errata sheet for it, although I hope it does not have the bug described for the PCM18AX0/BX0.
I have been looking at the clock and data (supplied by a National Instruments digital I/O card, the picture is in a previous post) as well as the timing diagrams on p. 210-211 of the PIC18F8722 datasheet. I am using CKP=0, CMP=0. It looks like the transition edge of the data is very near the 50% point between leading edges of the clock. The clock is not 50% duty cycle, which shouldn't matter, but then the falling edge of the clock is *not* where the data is latched in.
Also, the first bit seems to often get screwed up. Is this because the 50% point between clock edges is unknown without the second clock? _________________ Lifespeed
Last edited by lifespeed on Sun Oct 16, 2005 5:35 pm; edited 1 time in total |
|
|
Guest
|
|
Posted: Sat Oct 15, 2005 5:47 pm |
|
|
OK, here's the scoop. Despite the info on page 210 of the PIC datasheet indicating only two of the four clock timing modes are available, all 4 modes are really available. Not thru the compiler, CCS only supports two modes. A direct write to the registers SSP2STAT and SSP2CON1 to set CKE=0 and CKP=1 accomplished a valid read on the rising edge of the clock. |
|
|
Ttelmah Guest
|
|
Posted: Sun Oct 16, 2005 2:40 am |
|
|
You do presumably realise that there is nothing 'special' about the defines used by CCS, and that you can perfectly well create your own?. The top byte is what goes to the SSPSTAT register, and the low byte is what goes to SSPCON1. In fact CKE=0, CKP=1, is available from the CCS defines, as just SPI_H_TO_L. SPI_X_TO_X, control the bit fed to CKP, and the 'SPI_XMIT_L_TO_H' value controls the bit for CKE. Nowhere in the data sheet that I can see, does it indicate that only two of the clock modes are available....
Best Wishes |
|
|
lifespeed
Joined: 17 Aug 2005 Posts: 19
|
|
Posted: Sun Oct 16, 2005 5:33 pm |
|
|
Ttelmah wrote: | You do presumably realise that there is nothing 'special' about the defines used by CCS, and that you can perfectly well create your own?. The top byte is what goes to the SSPSTAT register, and the low byte is what goes to SSPCON1. In fact CKE=0, CKP=1, is available from the CCS defines, as just SPI_H_TO_L. SPI_X_TO_X, control the bit fed to CKP, and the 'SPI_XMIT_L_TO_H' value controls the bit for CKE. Nowhere in the data sheet that I can see, does it indicate that only two of the clock modes are available....
Best Wishes |
Apparently my understanding of 'SPI_XMIT_L_TO_H' was imperfect. I did not realize it was affecting the CKP bit. Maybe a little more technical definition in the CCS manual wouldn't hurt . . .
I do insist that p. 210 of the PIC datasheet shows the slave mode with only two of the four clock modes.
However I am very happy to be enlightened, thanks to all for your help. _________________ Lifespeed |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Oct 16, 2005 5:45 pm |
|
|
Actually, if you look at Figures 19-5 and 19-6, they show the four
SPI clock modes for the slave. This is on page 214 with the Acrobat
reader.
In other words, instead of showing all four modes in one timing
diagram as they do with the Master, for the Slave they split it
into two diagrams. |
|
|
|