View previous topic :: View next topic |
Author |
Message |
colin382
Joined: 03 Jun 2020 Posts: 37 Location: UK
|
SPI on 18F16Q41 |
Posted: Thu Jan 25, 2024 8:35 am |
|
|
Using Workshop compiler v5.105 on Windows 10
Several attempts to use SPI have failed,what am I doing wrong?
Latest code in entirety:
#include <18F16Q41.h>
#fuses NOWDT
#use delay(clock=16M)
#include <stdlib.h>
#pin_select SDO1=PIN_A2 // chip pin 17
#use spi(MODE=0, BITS=8)
int8 i = 0;
void main() {
output_high(PIN_C2); // enable SPI
while(TRUE){
spi_write(i++);
output_toggle(PIN_A4); // check activity
}
}
code compiles with no errors or warnings, PinA4 toggles, but nothing
from SPI pins (or any other pin)
Replacing #use line with:
#use spi(SPI1, MODE=0, BITS=8)
results in an error: Option invalid Not valid for H/W
BUT SPI1 is listed as a valid option in the help file. |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Thu Jan 25, 2024 9:01 am |
|
|
SPI requires CLOCK, DATA OUT, and DATA IN.
You did not set a pin for the clock. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Thu Jan 25, 2024 9:34 am |
|
|
have a look in the CCS manual as well as examples that they supply !
lots of 'need to know info' there . |
|
|
colin382
Joined: 03 Jun 2020 Posts: 37 Location: UK
|
|
Posted: Thu Jan 25, 2024 9:42 am |
|
|
Thanks for the advice,
I replaced the #use spi line with
#use spi(MODE=0, BITS=8, CLK=PIN_B6, DI=PIN_B4, DO=PIN_A2)
// chip pin 11 13 17
but still no clock or data seen. The hardware is good, other test code that
just toggles these pins works.
I also tried spi_init(100000); just after main(), but the compiler
complains, wanting a comma. So I think this means I have to define a stream
Adding stream = flash to the options in #use spi and in spi_init is OK but now I get error "undefined identifier"
Other forum topics suggest that compiler versions around 5.1xx have problems with the PPS pins in some PICs, maybe I should upgrade. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Thu Jan 25, 2024 10:47 am |
|
|
Several things:
First you need to setup #PIN_SELECT for all three pins. Then just use
SPI1 in the #use spi.
Then add bits=8 to the #use spi.
Then use spi_xfer, not xpi_write.
If you look at the manual, you will find that #use spi, refers you to spi_xfer
not to spi_read or spi_write. Spi_read and spi_write are the old commands
for use with the setrup_spi command. Mixing the two sets of commands is
a 'may not work, and certainly will not work properly' way of working.
Code: |
#include <18F16Q41.h>
#fuses NOWDT
#use delay(clock=16M)
#include <stdlib.h>
#pin_select SDO1=PIN_A2 // chip pin 17
#pin_select SDI1=PIN_B4
#pin_select SCK1=PIN_B6
#use spi(SPI1, MODE=0, BITS=8)
int8 i = 0;
void main()
{
output_high(PIN_C2); // enable SPI
while(TRUE)
{
spi_xfer(i++);
output_toggle(PIN_A4); // check activity
}
}
|
|
|
|
colin382
Joined: 03 Jun 2020 Posts: 37 Location: UK
|
Solved! |
Posted: Thu Jan 25, 2024 11:55 am |
|
|
@temtronic: RTFM is always good advice, but in this case the FM was in conflict with the compiler. Having read the manual and the help file I reached the conclusion that if I stayed with the hardware it would not be necessary to define the pins to be used. That didn't work, and because I have plans for the SPI1 hardware pins, I chose to go to SPI2 and then define the pins much as Ttelmah described. That didnt work either!
Then I came back to find Ttelmah's solution which worked straight off the bat. Kudos Ttelmah. BUT when I translated across by changing "SPI1"to "SPI2" with no other changes it still didn't work!
I'll rework my other pin assignments to use SPI1
Thanks to all who offered advice. This forum is BRILLIANT. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Thu Jan 25, 2024 12:00 pm |
|
|
the other little 'gotcha' ...
...is that not all pins are remappable to all peripherals on PPS PICs.
these 'new' PICs have loads of nice features but, yes, kinda helps to 'look over' the datasheet. |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Thu Jan 25, 2024 12:36 pm |
|
|
Please post your code for SPI2.
Keep in mind you have to do all of the changes, not just SPI1 -> SPI2:
SPI1 -> SPI2
SCK1 -> SCK2
SDO1 -> SDO2
SDI1 -> SDI2 |
|
|
colin382
Joined: 03 Jun 2020 Posts: 37 Location: UK
|
|
Posted: Thu Jan 25, 2024 4:37 pm |
|
|
@guageguy
Here you go:
#include <18F16Q41.h>
#fuses NOWDT
#use delay(clock=16M)
#include <stdlib.h>
#pin_select SDO2=PIN_A2 // chip pin 17
#pin_select SDI2=PIN_B4
#pin_select SCK2=PIN_B6
#use spi(SPI2, MODE=0, BITS=8)
int8 i = 0;
void main()
{
output_high(PIN_C2); // enable SPI
while(TRUE)
{
spi_write(i++);
output_toggle(PIN_A4); // check activity
}
} |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Fri Jan 26, 2024 2:52 am |
|
|
I've already told you exactly why this will not work.
You are using spi_write. spi_write is _NOT_ repeat _NOT_ the command
for use with #USE SPI.
Look at the manual. Select the entry for #use spi. Now look at the bottom
of the page, where it lists the commands 'related' to this. It shows:
Quote: |
See Also:
spi_xfer(), spi_transfer(), spi_transfer_write(), spi_transfer_read(), spi_transfer_done(), spi_transfer_clear()
|
No mention at all of spi_write.
As I said before "Mixing the two sets of commands is a 'may not work,
and certainly will not work properly' way of working."
Code: |
#include <18F16Q41.h>
#fuses NOWDT
#use delay(internal=16M)
#include <stdlib.h>
#pin_select SDO2=PIN_A2 // chip pin 17
#pin_select SDI2=PIN_B4
#pin_select SCK2=PIN_B6
#use spi(SPI2, MODE=0, BITS=8)
int8 i = 0;
void main()
{
output_high(PIN_C2); // enable SPI
while(TRUE)
{
spi_xfer(i++);
output_toggle(PIN_A4); // check activity
}
}
|
Also learn to use the code buttons, and be explicit on how the 'clock' is
to be generated.
You do not use spi_write, with #use spi. |
|
|
colin382
Joined: 03 Jun 2020 Posts: 37 Location: UK
|
|
Posted: Fri Jan 26, 2024 5:20 am |
|
|
@Ttelmah
OK, sorry to miss the sublties of your code. Clearly one has to not only RTFM, but read what is NOT in the FM.
Taking on board your observations re spi_xfer() vs spi_write(), out of curiosity I checked out SPI1 and SPI2 with both instructions.
SPI1 works with either, SPI2 only works with spi_xfer(). Good to know.
Thanks for your help. |
|
|
|