View previous topic :: View next topic |
Author |
Message |
AidanHockey5
Joined: 11 Jun 2017 Posts: 10
|
LTC6903 Software SPI using 12F683 |
Posted: Sun Jun 11, 2017 3:45 pm |
|
|
Hello,
I've been trying to get this LTC6903 programmable oscillator to play nice with a 12F683, but I've been having no luck. Perhaps it's my misunderstanding of how software SPI works in CCS.
Here is my code:
Code: |
//PIC12F683
#include <main.h>
#USE SPI (MASTER, CLK=PIN_A4, DI=PIN_A5, ENABLE=PIN_A2, MSB_FIRST, BITS=8, MODE=0, BAUD=100000 )
#define byte unsigned char
void SPIWrite(byte Byte1, byte Byte2)
{
spi_xfer(Byte1);
spi_xfer(Byte2);
}
void SetFrqManual(byte oct, byte dac)
{
if(dac <0 ) dac = 0;
if(oct < 0) oct = 0;
if(dac > 1023) dac = 1023;
if(oct > 15) oct = 15;
byte CNF = 0b00000000;
byte BitMap = (oct << 12) | (dac << 2) | CNF;
byte Byte1 = (byte)(BitMap>>8);
byte Byte2 = (byte)BitMap;
SPIWrite(Byte1, Byte2);
}
void main()
{
delay_ms(1000);
SetFrqManual(11, 830); //3.58MHz
}
|
The 12F683's only job is to set this LTC6903.
It seems like there is some semblance of communication happening, because the output frequencies of the 6903 do change, but they are very off.
The data sheet for the LTC6903 can be found here:
http://cds.linear.com/docs/en/datasheet/69034fe.pdf
I'm pretty stumped and have been searching these forums for an answer that works for me, but I've come up short.
I really appreciate the help! Thank you! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Sun Jun 11, 2017 4:05 pm |
|
|
hmm...
#USE SPI (MASTER, CLK=PIN_A4, DI=PIN_A5, ENABLE=PIN_A2, MSB_FIRST, BITS=8, MODE=0, BAUD=100000 )
I don't see where you tell the PIC which pin is to be the "Data Output" pin, the pin that SENDS data TO the peripheral....
Then again it's 90*F here all day.....
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 11, 2017 4:25 pm |
|
|
In addition to the DO pin issue, you have these other bugs:
1. You're attempting to pass a parameter of 830 to a function that can
only accept a byte (0 to 255):
Quote: | SetFrqManual(11, 830); //3.58MHz
void SetFrqManual(byte oct, byte dac)
{
...
}
|
If you look at the LTC6903 data sheet, and look at how the Bitmap word
is built, the 'dac' parameter really should be an 'int16'.
2. The declaration of 'Bitmap' is wrong. It clearly needs to be 'int16':
Quote: | byte BitMap = (oct << 12) | (dac << 2) | CNF; |
3. The first three tests below are invalid for an unsigned char.
An unsigned char can't ever be less than 0, and it can't ever be greater
than 255.
Quote: |
void SetFrqManual(byte oct, byte dac)
{
if(dac < 0) dac = 0;
if(oct < 0) oct = 0;
if(dac > 1023) dac = 1023;
if(oct > 15) oct = 15; |
Quote: |
Here are the warnings. Do you have warnings enabled for display in
your IDE (either the CCS IDE or MPLAB) ?
Quote: |
>>> Warning 205 "PCM_Test.c" Line 17(1,1): Unsigned variable is never less than zero
>>> Warning 204 "PCM_Test.c" Line 17(1,1): Condition always FALSE
>>> Warning 205 "PCM_Test.c" Line 18(1,1): Unsigned variable is never less than zero
>>> Warning 204 "PCM_Test.c" Line 18(1,1): Condition always FALSE
>>> Warning 206 "PCM_Test.c" Line 19(1,1): Variable of this data type is never greater than this constant
>>> Warning 204 "PCM_Test.c" Line 19(1,1): Condition always FALSE |
|
|
|
|
AidanHockey5
Joined: 11 Jun 2017 Posts: 10
|
|
Posted: Sun Jun 11, 2017 5:15 pm |
|
|
Ha, great eye PCM. I've been mulling over this for so long that I didn't realize I made so many silly mistakes. This is essentially ported-over Arduino code since there really isn't too much in the way of examples for the 6903.
Sadly, it seems that I'm still getting wrong values off the 6903.
With that being said, in #use SPI, DI=PIN_A5 was supposed to be DO. After reading the data sheet on the 6903 a little more, it looks like I may have to change my SPI mode. The data sheet reads:
Quote: | Writing Data (LTC6903 Only)
When the SEN line is brought LOW, serial data presented
on the SDI input is clocked in on the rising edges of SCK
until SEN is brought HIGH. On every eighth rising edge
of SCK, the preceding 8-bits of data are clocked into the
internal register. It is therefore possible to clock in only
the 8 {D15 - D8} most significant bits of data rather than
completing an entire transfer.
The serial data transfer starts with the most significant
bit and ends with the least significant bit of the data, as
shown in the Timing Diagrams section. |
Perhaps I need to change to either mode 1 or 3?
I also attempted to directly send over my (now int16) Bitmap that didn't seem to work.
I've made the following changes to my code:
Code: | #include <main.h>
#USE SPI (MASTER, CLK=PIN_A4, DO=PIN_A5, ENABLE=PIN_A2, MSB_FIRST, BITS=8, MODE=0, BAUD=100000 )
#define byte unsigned char
void SetFrqManual(byte oct, int16 dac)
{
byte CNF = 0b00000000;
int16 BitMap = (oct << 12) | (dac << 2) | CNF;
byte Byte1 = (byte)(BitMap>>8);
byte Byte2 = (byte)BitMap;
//spi_xfer(BitMap); //Perhaps this could work?
spi_xfer(Byte1);
spi_xfer(Byte2);
}
void main()
{
delay_ms(1000); //Debug delay for instruments to start up.
SetFrqManual(11, 830); //3.58MHz
} |
Again, thanks for the help. You're what makes CCS such a pleasure to use haha. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 11, 2017 5:57 pm |
|
|
Post your main.h. I want to see your #fuses and #use delay(). |
|
|
AidanHockey5
Joined: 11 Jun 2017 Posts: 10
|
|
Posted: Sun Jun 11, 2017 6:03 pm |
|
|
PCM programmer wrote: | Post your main.h. I want to see your #fuses and #use delay(). |
Code: |
#include <12F683.h>
#device ADC=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#use delay(internal=8MHz)
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 11, 2017 7:02 pm |
|
|
These are the #fuses I get with vs. 5.071. Check the end of your .LST
file. Make sure your fuses are the same. Also post your compiler vs.
Quote: | Configuration Fuses:
Word 1: 3CE4 INTRC_IO NOWDT PUT MCLR NOPROTECT NOCPD NOBROWNOUT IESO FCMEN |
According to the signal diagram for SPI, the SCK signal can start out
either high or low. So Mode 0 should be OK. But you can try Mode 3.
It's the alternate one.
Also, post your connections to the LTC6903 chip. There is an \OE pin.
Do you have that tied to ground ? It should be. Then the output signal
is available on the CLK pins. |
|
|
AidanHockey5
Joined: 11 Jun 2017 Posts: 10
|
|
Posted: Sun Jun 11, 2017 7:58 pm |
|
|
I'm driving an older SN76489 PSG chip with the output. You can assume that chip is hooked up correctly.
As for the fuses, mine are identical to yours. My compiler version is 5.008.
OE is tied to VCC and to ground via a 0.01uF cap. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 11, 2017 8:33 pm |
|
|
Setting OE high is correct. You have it correct. I read the description in
the data sheet too quickly.
I'll compare the code produced by vs. 5.008 to vs. 5.071 and see if there
are any differences. |
|
|
AidanHockey5
Joined: 11 Jun 2017 Posts: 10
|
|
Posted: Sun Jun 11, 2017 8:54 pm |
|
|
All good. By the way, in the #USE SPI: Would the baud rate have anything to do with this issue? The 6903's serial clock speed is 20 MHz, which is pretty high for the 12F683 @ 8 MHz.
Perhaps the section since I'm sending out 16 bits of data?
If it means anything, Code: | SetFrqManual(11, 831); | should produce 3.58MHz, but the 6903 is outputting about 56 KHz. This means that there is SPI data coming in and modifying the registers on the 6903, but the data is wrong.
It's weird how the Arduino's "Wire" library seemed to perform with flying colors while this little PIC is struggling. Perhaps hardware SPI is the key or maybe this little guy isn't fast enough.
I really appreciate the effort regardless :) |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 11, 2017 9:00 pm |
|
|
I think you have a problem with no output on pin GP2. To fix this, add
the following line shown in bold to the start of main():
Quote: |
void main()
{
setup_timer_0(T0_INTERNAL);
.
.
.
} |
|
|
|
AidanHockey5
Joined: 11 Jun 2017 Posts: 10
|
|
Posted: Sun Jun 11, 2017 9:07 pm |
|
|
Hmm bummer, no dice. Still getting that same wrong 56KHz value for
Code: | SetFrqManual(11, 831); |
I've even tried some lower values like:
Code: | SetFrqManual(1, 984); |
Which should give 4 KHz... but ends up outputting 67KHz... erm.. |
|
|
AidanHockey5
Joined: 11 Jun 2017 Posts: 10
|
|
Posted: Sun Jun 11, 2017 9:14 pm |
|
|
Just for fun, I decided to swap out my previous LTC 6903 and put in a fresh one. Same odd results. Just to rule out the possibility that the PIC was malfunctioning, I also replaced that too. Nope.
So at least I'm pretty confident in the hardware side of things. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 11, 2017 9:25 pm |
|
|
Actually I think you have hit upon it here:
Quote: | Perhaps the Code:
BITS=8
section since I'm sending out 16 bits of data |
You are using the built-in automatic Chip Select in the #use spi() line.
Since you have 8 bits selected, it is dropping and raising \CS on a
byte basis. But the Bitmap word is supposed to be sent with \CS low
for entire word. This is most likely the final actual problem.
1. Change the BITS to 16 in the #use spi() line.
2. Change your set freq function to this:
Code: | void SetFrqManual(byte oct, int16 dac)
{
byte CNF = 0b00000000;
int16 BitMap = (oct << 12) | (dac << 2) | CNF;
spi_xfer(Bitmap);
} |
|
|
|
AidanHockey5
Joined: 11 Jun 2017 Posts: 10
|
|
Posted: Sun Jun 11, 2017 9:36 pm |
|
|
OHHH my goodness I think I've got something.
Okay, so first off, I caved and picked a different PIC chip, this time with hardware SPI support. I chose a 16F690
TOTALLY overkill for something like this, but I'm mainly looking for hardware SPI. I set the and this time, I spi_xfer'ed the entire "BitMap" variable AND manually controlled CS low and CS High.
Boom. 3.58MHz on the dot.
Here is the code for the 16F690 that works for me.
Code: | //16F690
#include <main.h>
#USE SPI (MASTER, SPI1, MODE=0, BITS=16, STREAM=SPI_1, MSB_FIRST)
void SetFrqManual(unsigned int16 oct, unsigned int16 dac)
{
byte CNF = 0b00000000;
unsigned int16 BitMap = (oct << 12) | (dac << 2) | CNF;
output_low(PIN_C6);
spi_xfer(BitMap);
output_high(PIN_C6);
}
void main()
{
delay_ms(1000); //Debug delay for instruments to start up.
SetFrqManual(11, 831); //3.58MHz
} |
I'll try once more with the 12F683 and report back. |
|
|
|