|
|
View previous topic :: View next topic |
Author |
Message |
buchtsucht
Joined: 14 May 2010 Posts: 20
|
How can I get continuous clock signal from SPI / dsPIC33f |
Posted: Fri May 14, 2010 8:36 am |
|
|
Hi,
dsPic33f have a fantastic PLL, to create nearly every clock frequency from a given clock signal.
So I want:
(a) A dsPIC33fFJ32GP running with 21,855 Mhz
(b) A Pin of the PIC toggeling constant and exactly with 21,855 div 2 = 10,925 Mhz as clock source for a RF-circuit.
(a) Was no Problem by configurating the PLL: 10 Mhz TCXO div 2 * 35 div 8 = 21,875 Mhz
(b) Did not work: My idea was: Using the CLOCK(SCKx) output from the IDE Module in Framed configuration, as described in http://ww1.microchip.com/downloads/en/DeviceDoc/70206C.pdf Page 17...20
There you can read:
Note:
The SCKx signal clock is not free running for normal SPI modes.
It only runs for 8 or 16 pulses when the SPIxBUF is loaded with data;
However, it is continuous for Framed mode.
The problem is, I cant get that continuous clock output. If I select FRMEN=1 in SPI1CON2 register to enter the Framed Mode, the SPI-Block seems to be dead.
I have done nothing with SPI before and informations are rare for dsPIC33f.
So I don´t know what to do anymore. And I am not a great expert, eaven If I like to experiment with dsPIC....
Code: |
#include <33FJ64GP802.h>
#FUSES NoWDT // Watch Dog Timer
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES CKSFSM //Clock Switching is enbled
#FUSES PR_PLL //Primary Oscillator with PLL
#word SPI1STAT=0x0240
#word SPI1CON1=0x0242
#word SPI1CON2=0x0244
#use delay (clock=10000000)
//#use FAST_IO (B)
#Pin_select SCK1OUT=PIN_B8 // CLK
#Pin_select SDO1=PIN_B9 // DATA
#Pin_select SS1OUT=PIN_B7 // Slave Select
int a; long aa;
void Main(){
set_Tris_B(0b1100000000000000);
setup_oscillator(OSC_CRYSTAL,21855000,10000000);
//5432109876543210
SPI1STAT=0b1000000000000000;
SPI1CON2=0b1000000000100000;
SPI1CON1=0b0000000000100000;
spi_write(0x80);
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Fri May 14, 2010 10:19 am |
|
|
Don't know for the PIC33, but for some of the lesser PICs with this ability, three bits would need to be set, and one cleared:
Master mode needs to be selected (MSTEN=1).
Frames SPI would need to be enabled (you mention this).
The SPI itself needs to be enabled (SPIEN=1).
The framed operation also needs to be selected as 'master' (SPIFSD=0)
You shouldn't need to write a byte to the SPI, the clock runs continuously in this mode.
Obviously the corresponding TRIS bits also need to be setup, and since most of these PIC support pin remapping, the peripheral has to be selected to the required pins.
Now, you seem to show most of this.
So I''d triple check your settings. Start simpler, and actually set the SPI to a 'standard' mode, and repeatedly send bytes, and see if you then get clock and data. Only once you have this working, switch to trying for the framed mode.
Best Wishes |
|
|
buchtsucht
Joined: 14 May 2010 Posts: 20
|
|
Posted: Fri May 14, 2010 10:55 am |
|
|
Thank you, it is a little bit late, but I will try tomorrw your advised sequence.
Quote: |
Start simpler, and actually set the SPI to a 'standard' mode, and repeatedly send bytes, and see if you then get clock and data. Only once you have this working, switch to trying for the framed mode.
|
=> Standard mode works fine, only framed did not work. |
|
|
buchtsucht
Joined: 14 May 2010 Posts: 20
|
|
Posted: Fri May 14, 2010 11:53 pm |
|
|
I tried again, exactly using your settings - no success!!
And I checked my settings 20 times - I can´t find anything!
I wrote a program, that tests all possible settings of the three registers and let it run with oscilloscope on the SPI clock PIN => not only one short signal appeared at all settings!
I found a small mistake: I used only 3 Pins, but frame needs 4 Pins. But it did not help too.
If I add SPI_write(255); the Processor seems to stop operating !??!
(PIN B13 rises four times from low to high and then stays high for ever / MPLAB 8.50 and PCWHD 4.106)
Adding SPI_read(0); is the same.
Code: |
#include <33FJ64GP802.h>
#FUSES NoWDT // Watch Dog Timer
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES CKSFSM //Clock Switching is enbled
#FUSES PR_PLL //Primary Oscillator with PLL
#word SPI1STAT=0x0240
#word SPI1CON1=0x0242
#word SPI1CON2=0x0244
#use delay (clock=10000000)
#use FAST_IO (B)
//#USE STANDARD_IO (B)
#Pin_select SCK1OUT=PIN_B8 // CLK
#Pin_select SDO1=PIN_B9 // DATA output
#Pin_select SS1OUT=PIN_B7 // Slave Select OUTPUT
//#Pin_select SS1IN=PIN_B7 // Slave Select INPUT
#Pin_select SDI1=PIN_B10 //Data Input
int a; long aa;
void Main(){
setup_oscillator(OSC_CRYSTAL,21855000,10000000);
//5432109876543210
set_Tris_B(0b1100000000000000);
SPI1STAT =0b1000000000000000 ;
SPI1CON1 =0b0000000000100010 ;
SPI1CON2 =0b1000000000000000 ;
while(1)
{
output_low (PIN_B13);output_high(PIN_B13);
output_low (PIN_B13);output_high(PIN_B13);
output_low (PIN_B13);output_high(PIN_B13);
output_low (PIN_B13);output_high(PIN_B13);
SPI_write(255);
}
}
====================================================
1: #include <33FJ64GP802.h>
0000 040200 goto 0x000200
2:
3: #FUSES NoWDT // Watch Dog Timer
4: #FUSES IESO //Internal External Switch Over mode enabled
5: #FUSES CKSFSM //Clock Switching is enbled
6: #FUSES PR_PLL //Primary Oscillator with PLL
7:
8: #word SPI1STAT=0x0240
9: #word SPI1CON1=0x0242
10: #word SPI1CON2=0x0244
11:
12: #use delay (clock=10000000)
13: #use FAST_IO (B)
14: //#USE STANDARD_IO (B)
15:
16: #Pin_select SCK1OUT=PIN_B8 // CLK
17: #Pin_select SDO1=PIN_B9 // DATA output
18: #Pin_select SS1OUT=PIN_B7 // Slave Select OUTPUT
19: //#Pin_select SS1IN=PIN_B7 // Slave Select INPUT
20: #Pin_select SDI1=PIN_B10 //Data Input
21:
22: int a; long aa;
23:
24: void Main(){
0200 A8E081 bset.b 0x0081,#7
0202 21F0A0 mov.w #0x1f0a,0x0000
0204 B7A6A8 mov.w 0x0000,0x06a8
0206 209000 mov.w #0x900,0x0000
0208 B7A6C6 mov.w 0x0000,0x06c6
020A 207080 mov.w #0x708,0x0000
020C B7A6C8 mov.w 0x0000,0x06c8
020E 200460 mov.w #0x46,0x0000
0210 B7E742 mov.b 0x0000,0x0742
0212 200570 mov.w #0x57,0x0000
0214 B7E742 mov.b 0x0000,0x0742
0216 A8C742 bset.b 0x0742,#6
0218 EFA32C setm.w 0x032c
021A 23F80F mov.w #0x3f80,0x001e
021C 23FFF0 mov.w #0x3fff,0x0000
021E B7A020 mov.w 0x0000,0x0020
0220 000000 nop
25: setup_oscillator(OSC_CRYSTAL,21855000,10000000);
0222 2005D4 mov.w #0x5d,0x0008
0224 883A24 mov.w 0x0008,0x0744
0226 2010D4 mov.w #0x10d,0x0008
0228 883A34 mov.w 0x0008,0x0746
26:
27: //5432109876543210
28: set_Tris_B(0b1100000000000000);
022A 2C0004 mov.w #0xc000,0x0008
022C 881644 mov.w 0x0008,0x02c8
29: SPI1STAT =0b1000000000000000 ;
022E 280004 mov.w #0x8000,0x0008
0230 881204 mov.w 0x0008,0x0240
30: SPI1CON1 =0b0000000000100010 ;
0232 200224 mov.w #0x22,0x0008
0234 881214 mov.w 0x0008,0x0242
31: SPI1CON2 =0b1000000000000000 ;
0236 280004 mov.w #0x8000,0x0008
0238 881224 mov.w 0x0008,0x0244
32:
33:
34: while(1)
35: {
36: output_low (PIN_B13);output_high(PIN_B13);
023A A9A2CD bclr.b 0x02cd,#5
023C A8A2CD bset.b 0x02cd,#5
37: output_low (PIN_B13);output_high(PIN_B13);
023E A9A2CD bclr.b 0x02cd,#5
0240 A8A2CD bset.b 0x02cd,#5
38: output_low (PIN_B13);output_high(PIN_B13);
0242 A9A2CD bclr.b 0x02cd,#5
0244 A8A2CD bset.b 0x02cd,#5
39: output_low (PIN_B13);output_high(PIN_B13);
0246 A9A2CD bclr.b 0x02cd,#5
0248 A8A2CD bset.b 0x02cd,#5
40: SPI_write(255);
024A EFE248 setm.b 0x0248
024C AF2240 btsc.b 0x0240,#1
024E 37FFFE bra 0x00024c
0250 A9C240 bclr.b 0x0240,#6
41:
42: }
0252 37FFF3 bra 0x00023a
43: }
44:
45:
0254 FE4000 pwrsav #0
|
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sat May 15, 2010 8:39 am |
|
|
I have no experience with the dsPIC33, but Paragraph 11.6.3.3 'Configuration Bit Pin Select Lock' makes me feel a bit suspicious. Here a mechanism is described preventing accidental port mappings by allowing to write to the port map registers only once. In the default state this IOL1WAY fuse is, restricting users to one write session until the next 'device reset'.
Do you have a debugger or something so that you can stop in the main loop and read back the configured port remapping settings? Do these have the expected contents?
What if you add the IOL1WAY fuse?
Quote: | If I add SPI_write(255); the Processor seems to stop operating !??! | See your posted assembly code: At line 40 the processor waits in a loop for SPI1STAT.1 to become low, indicating the just added byte moved into the transmit buffer and transmission has started.
This indicates a problem with the SPI module. Most likely some SPI error condition is not cleared.
You say the SPI module did work in normal mode, how was the SPI module configured then? Did you write directly to the SPI registers or did you use the CCS functions for SPI setup? The CCS functions will clear the receive and transmit error flags, this is missing in your code. |
|
|
buchtsucht
Joined: 14 May 2010 Posts: 20
|
|
Posted: Tue May 18, 2010 4:02 am |
|
|
Thanks for your answers, I read them several times.
@ckielstra
You was right: <<clearing SPI error flags>> helped me to find the solution!
Now everything is working perfect! Yeaaaaa!!!!
You can use your dsPIC as "low jitter fractional n frequency divider/multiplier" (or blink a LED up to 20.000.000 times per second) without any CPU-resources, if you do it like this:
Example:
10,000000 MHz Input Frequency at OSC1 from TCXO
28,000000 MHz Processor clock
14,000000 MHz at PIN 8
Wish you all fun with programming PICs!
Code: |
#include <33FJ64GP802.h>
#FUSES NoWDT // Watch Dog Timer
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES CKSFSM //Clock Switching is enbled
#FUSES PR_PLL //Primary Oscillator with PLL
//uses NoIOL1WAY
#word SPI1STAT=0x0240 // SPI Status and control register
#bit SPIEN =SPI1STAT.15 // 1=Enable SPI module
#bit SPISIDL=SPI1STAT.13 // 1=Stop SPI in IDLE mode
#bit SPIROV =SPI1STAT.6 // 1=receive overflow has occured
#bit SPITBF =SPI1STAT.1 // 1=transmit not started SPI1TXB is full
#bit SPIRBF =SPI1STAT.1 // 1=Receive is not complete SPI1RXB is impty
#word SPI1CON1=0x0242
#bit DISSCK =SPI1CON1.12 // 1=Disable SCK-PIN / PIN is I/O
#bit DISDO =SPI1CON1.11 // 1=Disable SDO-PIN / PIN is I/O
#bit MODE16 =SPI1CON1.10 // 1=Communication is 16 Bit wide
#bit SMP =SPI1CON1.9 // 1=Input data sampled at end of data output time
#bit CKE =SPI1CON1.8 // Clock edge select
#bit SSEN =SPI1CON1.7 // 1=SSx PIN used for slave modus
#bit CKP =SPI1CON1.6 // Clock polarity select
#bit MSTEN =SPI1CON1.5 // 1=Master mode
#bit SPRE0 =SPI1CON1.4 // divide clock frequncy div 1..8
#bit SPRE1 =SPI1CON1.3 // divide clock frequncy div 1..8
#bit SPRE2 =SPI1CON1.2 // divide clock frequncy div 1..8
#bit PPRE0 =SPI1CON1.1 // 0=divide clock frequncy additional div 16
#bit PPRE1 =SPI1CON1.0 // 0=divide clock frequncy additional div 4
#word SPI1CON2=0x0244
#bit FRMEN =SPI1CON2.15 // 1=Enable Framed mode
#bit SPIFSD =SPI1CON2.15 // 1=Frame sync input slave
#bit FRMPOL =SPI1CON2.15 // 1=Frame sync input is active low
#bit FRMDLY =SPI1CON2.15 // 1=Frame sync pulse with first bit
#use delay (clock=10000000)
#use FAST_IO (B)
//#USE STANDARD_IO (B)
#Pin_select SCK1OUT=PIN_B8 // CLK
//#Pin_select SDO1=PIN_B9 // DATA output
//#Pin_select SS1OUT=PIN_B7 // Slave Select OUTPUT
//#Pin_select SDI1=PIN_B10 //Data Input
int a; long aa;
void Main(){
setup_oscillator(OSC_CRYSTAL,28000000,10000000);
//5432109876543210
set_Tris_B(0b1100010000000000);
SSEN=0;
SPIROV=0;
//5432109876543210
SPI1CON1 =0b0000000000111111;
FRMEN=1; // 1=Enable Framed mode
SPIEN=1;
while(1)
{ }
}
|
|
|
|
|
|
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
|