CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

SPI Help [Solved]

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
mazen82



Joined: 10 Sep 2009
Posts: 22

View user's profile Send private message

SPI Help [Solved]
PostPosted: Mon Nov 22, 2010 1:17 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Nov 22, 2010 1:20 pm     Reply with quote

What line of code does it hang in ? Post the line.
Preferably, post the routine.
mazen82



Joined: 10 Sep 2009
Posts: 22

View user's profile Send private message

SPI Problem
PostPosted: Mon Nov 22, 2010 1:23 pm     Reply with quote

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: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Nov 22, 2010 1:44 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Nov 22, 2010 1:53 pm     Reply with quote

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: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Nov 22, 2010 1:55 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Nov 22, 2010 2:25 pm     Reply with quote

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: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Nov 22, 2010 2:28 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Nov 22, 2010 2:43 pm     Reply with quote

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: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Nov 22, 2010 3:39 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Nov 22, 2010 3:50 pm     Reply with quote

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: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Nov 22, 2010 3:55 pm     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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