View previous topic :: View next topic |
Author |
Message |
mazen82
Joined: 10 Sep 2009 Posts: 22
|
SPI Help [Solved] |
Posted: Mon Nov 22, 2010 1:17 pm |
|
|
I am using a PIC 18f97j60 with digital isolators (ADUM3100 for fast switching) to talk to MCP3909.
On the PICC side, it is powered from a different source which is always on. The MCP3909 side is powered by the AC power which is not always on.
When the AC power is turned off, the SPI communication hangs.
Is there a way around that besides the use of the watchdog timer to reset?
Any help is greatly appreciated.
Last edited by mazen82 on Mon Nov 22, 2010 3:59 pm; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Nov 22, 2010 1:20 pm |
|
|
What line of code does it hang in ? Post the line.
Preferably, post the routine. |
|
|
mazen82
Joined: 10 Sep 2009 Posts: 22
|
SPI Problem |
Posted: Mon Nov 22, 2010 1:23 pm |
|
|
Code: | void mcp_collect()
{
MCP3909_CS = 0;
ac_v_upper_byte = spi_read2(0);
ac_v_lower_byte = spi_read2(0);
ac_i_upper_byte = spi_read2(0);
ac_i_lower_byte = spi_read2(0);
MCP3909_CS = 1;
} |
It hangs on spi_read2(0)
the function mcp_collect() is called out in the isr routine every 132us.
I figure it shouldnt matter if the mcp3909 loses power cause then the read function would return zero's. |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Mon Nov 22, 2010 1:44 pm |
|
|
it depends... what device is doing the clocking? I'm assuming it's the PIC... but your problem sounds like the remote device is supplying the clock...
so let's clear that up first...
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
mazen82
Joined: 10 Sep 2009 Posts: 22
|
|
Posted: Mon Nov 22, 2010 1:53 pm |
|
|
the PIC is supplying the clock.
I have:
SDI
SDO
CLK
MCP_CS --- MCP3909 Chip Select
MCP_MCLR --- MCP3909 MCLR
the MCP3909 is running of a crystal (3.579MHz) for its internal timing used. The PIC crystal is 25MHz.
When both sides are powered SPI works perfectly.
Here are the setting lines for the spi:
setup_spi2(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_4);
SSP_SMP = 1;
SSP_CKE = 0;
SSP2CON1 = 32; |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Mon Nov 22, 2010 1:55 pm |
|
|
Ok, as PCM Programmer would say at this point,
Post a short example that demonstrates the problem along with your compiler version.
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
mazen82
Joined: 10 Sep 2009 Posts: 22
|
|
Posted: Mon Nov 22, 2010 2:25 pm |
|
|
the PIC is supplying the clock.
I have:
SDI
SDO
CLK
MCP_CS --- MCP3909 Chip Select
MCP_MCLR --- MCP3909 MCLR
the MCP3909 is running off a crystal (3.579MHz) for its internal timing used. The PIC crystal is 25MHz.
When both sides are powered SPI works perfectly.
Here are the setting lines for the spi:
setup_spi2(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_4);
SSP_SMP = 1;
SSP_CKE = 0;
SSP2CON1 = 32; |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Mon Nov 22, 2010 2:28 pm |
|
|
that's not a short example. (it's like a re-post of the last post).
Your example should compile cleanly and provide a no-frills example that breaks. _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
mazen82
Joined: 10 Sep 2009 Posts: 22
|
|
Posted: Mon Nov 22, 2010 2:43 pm |
|
|
Sorry about the earlier post, compiler version is 4.090
here is the code:
Code: |
#include "C:\Program Files\PICC\DMM\18F97J60.H"
#device ICD=TRUE
#device adc=10
#use delay(clock=25M)
#fuses HS
#FUSES WDT128
#fuses NOIESO
#fuses NOFCMEN
#fuses PRIMARY
#fuses ETHLED
#fuses NOWDT
#fuses NOPROTECT
#fuses DEBUG
#fuses NOSTVREN
#FUSES CCP2C1
#define INSTR_FREQ (CLOCK_FREQ/4)
#include "C:\Program Files\PICC\DMM\PIC18.h"
#use STANDARD_IO(A) // Refresh pin direction every use
#use STANDARD_IO(B)
#use STANDARD_IO(C)
#use STANDARD_IO(D)
#use STANDARD_IO(E)
#use STANDARD_IO(J)
#bit ac_side_vcc = PORTD.0
#bit MCP3909_MCLR = LATD .1
#bit LEDON = LATD .2
#bit RD3 = PORTD.3 // output - LCD backlight
#bit MCP3909_SDI = LATD .4
#bit MCP3909_SDO = PORTD.5
#bit MCP3909_SCK = LATD .6
#bit RD7 = LATD .7
#define DDIRD 0x29
#define INITD 0x00
#define X0 0x0C
#define X1 0x0D
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
int8 ac_v_array_pntr,ac_i_array_pntr;
signed int16 ac_v_array[128], ac_i_array[128];
int8 ac_v_upper_byte, ac_v_lower_byte, max_v_pntr, xyz, xyz1, count_65535;
int16 ac_v;
signed int16 ac_v_signed, ac_i_signed;
void main()
{
setup_adc_ports(ALL_ANALOG|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
PORTA = INITA;
PORTB = INITB;
PORTC = INITC;
PORTD = INITD;
PORTE = INITE;
PORTF = INITF;
PORTH = INITH;
PORTJ = INITJ;
TRISB = DDIRB;
TRISC = DDIRC;
TRISD = DDIRD;
TRISE = DDIRE;
//TRISF = DDIRF;
TRISH = DDIRH;
TRISJ = DDIRJ;
//timer 4 setup
T4CON = 0x78; // no prescale, post scaler/16
//T2CON = 0x20; //10mhz
delay_cycles(2);
TMR4ON = 1; // and turn on the timer
PR4 = 39;
PR4 = 51;
setup_spi2(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_4);
setup_spi2(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_4);
SSP_SMP = 1;
SSP_CKE = 0;
SSP2CON1 = 32;
//*****Initialize MCP3909
MCP3909_MCLR = 1; //inverted during isolation xfer
delay_ms(1);
MCP3909_MCLR = 0;
delay_us(1);
MCP3909_MCLR = 1;
MCP3909_CS = 0;
spi_write2(0xa4);
MCP3909_CS = 1;
delay_ms(1);
while(1)
{
if(ac_v_array_pntr>127)
{
ac_v_array_pntr = 0;
}
if(ac_i_array_pntr>127)
ac_i_array_pntr = 0;
}//end of while 1
}//end of main
#int_timer4
isr_timer4()
{
MCP3909_CS = 0;
ac_v_upper_byte = spi_read2(0);
ac_v_lower_byte = spi_read2(0);
ac_i_upper_byte = spi_read2(0);
ac_i_lower_byte = spi_read2(0);
MCP3909_CS = 1;
ac_v = ac_v_upper_byte<<8;
ac_v += ac_v_lower_byte;
ac_v_signed = ac_v;
ac_i = ac_i_upper_byte<<8;
ac_i += ac_i_lower_byte;
ac_i_signed = ac_i;
ac_v_array[ac_v_array_pntr] = ac_v_signed;
ac_v_array_pntr++;
ac_i_array[ac_i_array_pntr] = ac_i_signed;
ac_i_array_pntr++;
} |
|
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Mon Nov 22, 2010 3:39 pm |
|
|
No problem:
Ok, couple of commands/questions...
1: Compiler Version?
2: Are you actually using a debugger right now? If not: comment out ICD=TRUE and #fuses DEBUG (or change to NODEBUG)
3: I'm not a fan of putting something in an ISR that could cause a race condition. You have an SPI routine inside an ISR based on time. If the SPI routine doesn't finish when you expect, and the ISR fires again. What happens? (I know some will have answers, but the point is -- it's a question that needs to be considered) whereas....
Write the routine so the ISR sets a flag like if (!get_sample) { get_sample = 1; }
In your main loop, have something that says if (get_sample) { do some work; get_sample = 0; }
4: Are you using the analog inputs as analog inputs? Remember, inputs shouldn't really be left floating and while these are in analog mode, one of the things I do with unused pins is to make them OUTPUTs which now forces them to 0|1. At least they're not floating inputs.
So. With that.
The last item missing from your code is:
enable_interrupts (INT_TIMER4);
enable_interrupts (GLOBAL);
You have to enable interrupts to service the timer interrupt. Otherwise the time WILL run if you enable it -- and the INTERRUPT flag will get set on overflow.. but no code execution will take place because of those items missing.
Let me know how that goes. _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
mazen82
Joined: 10 Sep 2009 Posts: 22
|
|
Posted: Mon Nov 22, 2010 3:50 pm |
|
|
All software versions are 4.090
I took it out of the interrupt and used your suggestion by putting it in the main loop, this seems to have helped it tremendously.
thank you. |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Mon Nov 22, 2010 3:55 pm |
|
|
Excellent. If your problem is Solved, might I suggest that you edit the original post's subject line to include [SOLVED] for people so they know you figured it out.
Makes it easier to sort the sometimes huge lists of results when searching a problem.
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
|