|
|
View previous topic :: View next topic |
Author |
Message |
SeeCwriter
Joined: 18 Nov 2013 Posts: 160
|
SPI2 on 18F67K22 |
Posted: Wed Dec 19, 2018 10:14 am |
|
|
I'm using v5.081 PCWHD with a PIC18F67K22, and trying unsuccessfully to use the SPI2 interface.
In another thread about using SPI, I read that you can't use spi_write with a #use spi declaration, nor can you use spi_xfer with the setup_spi function. That spi_write can only be used with setup_spi, and spi_xfer can only be used with #use spi. If that's true, the compiler manual should say so.
In any case, when I try to use SPI2, a call to spi_write, or a call to spi_xfer hangs the cpu forever. It never returns from those calls.
For example:
Code: |
#use delay( clock=64000000, internal=16000000 )
#use spi (MASTER, SPI2, MODE=1, BITS=8, STREAM=SPI_2, FORCE_HW)
spi_xfer( SPI_2, value );
|
or
Code: |
#use delay( clock=64000000, internal=16000000 )
setup_spi2(SPI_MASTER|SPI_H_TO_L|SPI_CLK_DIV_64);
spi_write2( value );
|
In both cases, the program crashes as the spi_xxx call. Am I missing something? |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Wed Dec 19, 2018 10:33 am |
|
|
It's quite possible and very likely that the compiler is accessing the wrong registers for SPI2.
Options -> Project -> Output Files, select Symbolic for the List File. Recompile. Have a look at the list file and see if spi_xfer() is accessing the proper register when you attempt to transfer something over SPI2. It's a safe bet that it isn't. From memory the standard driver waits on the state of a bit before commencing (or at some point during the procedure). If it's addressing the wrong register(s), then that would explain the hanging you're seeing. |
|
|
SeeCwriter
Joined: 18 Nov 2013 Posts: 160
|
|
Posted: Wed Dec 19, 2018 11:22 am |
|
|
This is from the listing. I don't think I have access to the source code of spi_xfer.
.................... spi_xfer( SPI_2, val[0] );
004D4: MOVFF val,??65535
004D8: CALL @SPI_XFER_1_8
.................... spi_xfer( SPI_2, val[1] );
004DC: MOVFF val+1,??65535
004E0: CALL @SPI_XFER_1_8 |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Wed Dec 19, 2018 11:34 am |
|
|
Near the very top of the processor.h file is a #nolist. Comment it out, then recompile.
Also, in your test program, put in a #use SPI for SPI1, and also put in a spi_xfer(SPI1, whatever) into your program.
You know that SPI1 accesses work properly so you can see the disassembly for that and compare to SPI2. |
|
|
SeeCwriter
Joined: 18 Nov 2013 Posts: 160
|
|
Posted: Wed Dec 19, 2018 12:50 pm |
|
|
The source code from the CCS libraries still does not show up in the list file. But I think you're right, the wrong register(s) is being used.
I changed the #use spi declaration to add FORCE_SW, and now SPI2 works. It's fast enough for my purposes.
I also sent an email to tech support informing of the problem. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Wed Dec 19, 2018 12:52 pm |
|
|
It correctly loads the byte into SSPBUF2.
Then loops rotating SSP2STAT right into carry, and since 'BF' is the bottom
bit, should exit the loop, when BF goes off.
The code is right!...
Are you sure the SCK2 pin is not shorted?. It'll lock if this pin is stuck,
since it is the actual signal going 'out' of the chip, that is looped back to
operate the shift register. If this pin is shorted, the SPI will hang as
you describe. |
|
|
SeeCwriter
Joined: 18 Nov 2013 Posts: 160
|
|
Posted: Wed Dec 19, 2018 12:59 pm |
|
|
Yes, I'm sure SCL2 is not shorted. I'm using the same SPI2 pins for the FORCE_SW configuration, and it's all working fine.
#use spi (MASTER, SPI2, MODE=1, BITS=8, BAUD=38400, DI=PIN_D5, DO=PIN_D4, CLK=PIN_D6, STREAM=SPI_2, FORCE_SW) |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Wed Dec 19, 2018 1:01 pm |
|
|
SeeCwriter wrote: | Yes, I'm sure SCL2 is not shorted. I'm using the same SPI2 pins for the FORCE_SW configuration, and it's all working fine.
#use spi (MASTER, SPI2, MODE=1, BITS=8, BAUD=38400, DI=PIN_D5, DO=PIN_D4, CLK=PIN_D6, STREAM=SPI_2, FORCE_SW) |
BAUD=38400
Are you sure about that? The SPI clock speed is very, very limited in terms of what it can provide, and 38,400 is pretty "weird". Usually on the order of several MHz. |
|
|
SeeCwriter
Joined: 18 Nov 2013 Posts: 160
|
|
Posted: Wed Dec 19, 2018 1:32 pm |
|
|
I tried 9600, and the compiler complained it was too slow. So I tried 38400. A 3-byte write is 1ms. The clock is 16.45kHz.
What would you suggest as a better value? |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Wed Dec 19, 2018 1:36 pm |
|
|
Oh, okay. Really low speed, low power. I was thinking standard application, tens of MHz clock, so SPI should also be on the order of MHz.
Just for the heck of it, can you leave off the clock specification entirely and revert to the HW SPI module just to see if that makes any difference at all? |
|
|
SeeCwriter
Joined: 18 Nov 2013 Posts: 160
|
|
Posted: Wed Dec 19, 2018 1:42 pm |
|
|
I removed the BAUD setting, and now SCL2 is 833.3KHz. So why is 38400 so unusual? |
|
|
SeeCwriter
Joined: 18 Nov 2013 Posts: 160
|
|
Posted: Wed Dec 19, 2018 1:44 pm |
|
|
No, I can't switch to hardware SPI. It doesn't work. Only with FORCE_SW set does SPI2 work. |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Wed Dec 19, 2018 2:16 pm |
|
|
I guess the value isn't unusual, the relatively slow speed is. SPI clocks usually run "on the order" of a few MHz. For example, 5 MHz or 1 MHz or perhaps even 20 MHz. The SPI hardware clock divisor for most PICs usually has options for /2, /4, /8, /16. There may be one or two additional division factors, but the choices are pretty limited.
I saw the 38,400 and given my erroneous assumption that your PIC's clock was "on the order of several tens of MHz", my first impression was that wow, that's a really weird SPI clock. In fact, it's also slower than IIC on the slow setting. Given that SPI is a faster bus/protocol than IIC, it really struck me as weird. However, given your very low processor clock, no it's not unusual I suppose.
Something else just leapt to mind, however. On a relatively recent project a member of my team discovered that the SPI EEPROM he was interfacing with behaved properly if clocked "quickly" but not "slowly". This is a battery powered application, so very low power, very low clock speed. The application can also derive external power from a running vehicle, and when it detects external power, extra functionality is "unlocked" and the processor runs as fast as it will go. He found when the system had external power, everything behaved, but when the application reverted solely to battery power that the EEPROM's data seemed to get scrambled. He eventually tried upping the processor's speed during SPI transactions with the EEPROM, and the problem went away. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Thu Dec 20, 2018 1:51 am |
|
|
OK.
Now have triple checked, and spi_xfer, is doing exactly what it should.
The TRIS is setup correctly, the SSP2CON1 register has the port enabled.
It defaults to selecting Fosc/4 (without a baud rate). The slowest baud
rate the hardware can produce is Fosc/32768, by using the TMR2 output
(assuming this is not being used for something else...).
Now, I remember another 'nearby' chip, has an erratum, where the BF
bit does not set correctly. Just starting to wonder if this chip actually has
the same problem on SPI2, and nobody has noticed!...
On that basis I've written a quick 'replacement' for spi_xfer (actually
more like spi_write), setup to use the interrupt bit instead. Replace the
spi_xfer line with this (doesn't use the stream name just talks directly
to the hardware), and see if anything changes. If it does then the chip
has a bug....
Code: |
#BYTE SSP2STAT=getenv("SFR:SSP2STAT")
#BIT BF2=SSP2STAT.0
#BYTE SSP2BUF=getenv("SFR:SSP2BUF")
//#define USE_BF //Leave this enabled to use the BF bit as CCS does
//Simple send and receive from SPI2, using BF or SSP2IF to detect
//transmission complete
unsigned int8 send_spi2(unsigned int8 value)
{
unsigned int8 val;
val=SSP2BUF; //read buffer to clear BF
#IFNDEF USE_BF
clear_interrupt(INT_SSP2); //Clear SSP2 interupt
#ENDIF
SSP2BUF=val; //write data - shold start sending at once
#IFDEF USE_BF
while (BF2==0)
; //wait for transmission using BF
#ELSE
while (!interrupt_active(INT_SSP2))
; //or wait using SSP2IF
#ENDIF
return SSP2BUF; //and return value received
}
|
|
|
|
SeeCwriter
Joined: 18 Nov 2013 Posts: 160
|
|
Posted: Thu Dec 20, 2018 8:59 am |
|
|
You're absolutely right, the spi_xfer code is correct. The problem is in my code. I am using port D for different things, and have a #use FIXED_IO declaration that sets the various pins of port D accordingly. But I didn't include the SPI2 pins because I was expecting the #use spi to configure the SPI2 pins as needed. Well, that doesn't happen. As soon as I write to any of the pins of port D, the SPI2 quits working. Once I added the SPI2 pins to the FIXED_IO declaration SPI2 worked. |
|
|
|
|
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
|