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

18f4520 SPI AD7376
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ouch_



Joined: 27 Mar 2013
Posts: 12

View user's profile Send private message

18f4520 SPI AD7376
PostPosted: Fri Mar 29, 2013 9:11 am     Reply with quote

Hello! I'm new here and beginner in PIC uC

I need help with a problem I have no idea how to solve.

I'm trying to control a digipot AD7376 via SPI from PIC 18F4520.

the signals seem correct in SPI pins, according to AD7376 datasheet (shown below)
but the digipot only works ok when sending odd decimal data (binary final 1)

AD7376 uses a 7-bit serial input data. Extra MSB bits are ignored.

spi_write (x);

231 or 11100111 works
232 or 11101000 not
233 or 11101001 works
234 or 11101010 not
235 or 11101011 works
236 or 11101100 not
...









Code:
#include <18F4520.h>
#use delay(clock=10000000)
#FUSES NOWDT, HS, NOPROTECT, NOBROWNOUT, NOPUT, NOCPD, STVREN, NODEBUG, NOLVP,
NOWRT, NOWRTD, NOIESO, NOFCMEN, NOPBADEN, NOWRTC, NOWRTB, NOEBTR, NOEBTRB,
NOCPB, NOMCLR, NOXINST

VOID main (VOID)
{
   setup_spi ( SPI_MASTER | SPI_H_TO_L | SPI_XMIT_L_TO_H | SPI_CLK_DIV_64 ); //mode 3
   
   output_high (pin_b0); //chip select
     
   delay_ms (1000);
   
   WHILE (1)
   {     
      output_low (pin_b0); //chip select
      spi_write (3);
      output_high (pin_b0); //chip select
     
      delay_ms (5000); //time for measure     
   }
}





any idea what might be happening?
thanks all.
Regards.

-- CCS C ver 4.065
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Fri Mar 29, 2013 9:41 am     Reply with quote

Wrong SPI mode.....

Look at the manufacturers data. They show the clock idle _low_. Yours is idling high....

Much better to use SPI mode numbers. The data sheet for the pot shows mode0. Now if you add:
Code:

#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)

and change your setup to:
Code:

setup_spi ( SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_64 ); //mode0


Your timings should be better.

You are transmitting on the right edge, but starting from the wrong beginning....

Best Wishes
ouch_



Joined: 27 Mar 2013
Posts: 12

View user's profile Send private message

PostPosted: Fri Mar 29, 2013 11:56 am     Reply with quote

Hello Ttelmah,
first, very thanks!

I was using the same #defines you showed, but with SPI_MODE_3 in setup_spi. only modified to be more objective here.

testing here now, in SPI_MODE_0 nothing works.
only odd decimal in SPI_MODE_3 again.

with this guy seems to work:
http://www.instructables.com/id/Using-an-Arduino-to-Control-or-Test-an-SPI-electro/

looks like my timings. he used mode3.

according to the datasheet of ad7376:
"The 7-bit serial word must be loaded MSB first. The
format of the word is shown in Figure 2. The positive edge
-sensitive CLK input requires clean transitions to avoid clocking
incorrect data into the serial input register. Standard logic
families work well. When CS is low, the clock loads data into
the serial register upon each positive clock edge."

I d'ont understand the problem. Sad

thanks thanks thanks
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Fri Mar 29, 2013 12:15 pm     Reply with quote

You may be raising CS too soon.
It should be mode0 from the data sheet, though the example you show is using 3. Some chips don't care and will use either mode.
SPI is MSB first.
Try:
Code:

VOID main (VOID)
{
   int8 dummy;
   setup_spi ( SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_64 );
   
   output_high (pin_b0); //chip select
     
   delay_ms (1000);
   
   WHILE (1)
   {     
      output_low (pin_b0); //chip select
      dummy=spi_read (3);
      output_high (pin_b0); //chip select
     
      delay_ms (5000); //time for measure     
   }
}

Using spi_read, makes the function wait till the transfer is finished (since it waits to clock the non-existent return byte in).

Best Wishes
ouch_



Joined: 27 Mar 2013
Posts: 12

View user's profile Send private message

PostPosted: Fri Mar 29, 2013 1:00 pm     Reply with quote

the same Sad

results:
setup_spi ( SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_64 );
spi_write (3); = none
spi_write (4); = none

setup_spi ( SPI_MASTER | SPI_MODE_1 | SPI_CLK_DIV_64 );
spi_write (3); //103k = OK
spi_write (4); = none

setup_spi ( SPI_MASTER | SPI_MODE_2 | SPI_CLK_DIV_64 );
spi_write (3); = none
spi_write (4); = none

setup_spi ( SPI_MASTER | SPI_MODE_3 | SPI_CLK_DIV_64 );
spi_write (3); //103k = OK
spi_write (4); = none
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Fri Mar 29, 2013 1:53 pm     Reply with quote

If you look at it the data sheet picture again, it shows an eighth data bit after the seven bits are sent.
To send '3' to the chip, you need to rotate this by one, and send '6'.

Best Wishes
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri Mar 29, 2013 3:08 pm     Reply with quote

also try adding a 47 ohm resistor in series with the control lines to both SDI and your clock line between the pic and digipot . helps enormously to prevent glitching with HS switching .
ouch_



Joined: 27 Mar 2013
Posts: 12

View user's profile Send private message

PostPosted: Fri Mar 29, 2013 5:45 pm     Reply with quote

Ttelmah wrote:
If you look at it the data sheet picture again, it shows an eighth data bit after the seven bits are sent.
To send '3' to the chip, you need to rotate this by one, and send '6'.


asmboy wrote:
also try adding a 47 ohm resistor in series with the control lines to both SDI and your clock line between the pic and digipot . helps enormously to prevent glitching with HS switching .


very thanks! but it not work Sad I changed the digipot, same result.
I'll try via software spi...
ouch_



Joined: 27 Mar 2013
Posts: 12

View user's profile Send private message

PostPosted: Fri Mar 29, 2013 10:28 pm     Reply with quote

trying with software spi:

Code:
#include <18F4520.h>
#use delay(clock=10000000)
#FUSES NOWDT, HS, NOPROTECT, NOBROWNOUT, NOPUT, NOCPD, STVREN, NODEBUG, NOLVP,
NOWRT, NOWRTD, NOIESO, NOFCMEN, NOPBADEN, NOWRTC, NOWRTB, NOEBTR, NOEBTRB,
NOCPB, NOMCLR, NOXINST

#USE SPI (MASTER, CLK=PIN_C3, DI=PIN_C4, DO=PIN_C5, MODE=3, BITS=8, STREAM=SPI_1, MSB_FIRST)

VOID main (VOID)
{

   output_high (pin_b4); //chip select
     
   delay_ms (1000);
   
   WHILE (1)
   {     
      output_low (pin_b4);  //chip select
      spi_xfer(124);
      output_high (pin_b4); //chip select
     
      delay_ms (5000); //time for measure     
   }
}


with MODE=0 not work,
in MODE=3 works exactly on hardware spi

but if i remove the delay_ms (5000); works some odd values: 126, 124, 122
Shocked
ouch_



Joined: 27 Mar 2013
Posts: 12

View user's profile Send private message

PostPosted: Sun Mar 31, 2013 5:09 pm     Reply with quote

tested in another pic I have here,
18f4431 with internal osc,

same result. Sad
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 31, 2013 5:15 pm     Reply with quote

What do you mean by "not work" ?

How are you testing it ?

What do you observe to see if it works or does not work ?

The circuit schematic that you posted is very minimal.
What are the connections to the other pins, such as Vdd, Vss, A, B, W,
\RS and \SHDN ?
ouch_



Joined: 27 Mar 2013
Posts: 12

View user's profile Send private message

PostPosted: Sun Mar 31, 2013 6:12 pm     Reply with quote

hello PCM programmer,

first, very thanks!

I'm testing with a resistance meter, between W and A, between W and B.

when I say working, I have a resistence value equivalent to the decimal value sent.
sending "1", read the values on meter: 101k between W-A, and 0.1k between W-B,
sending "127," read values: 0.1K between W-A and 102k between W-B, like a "real" pot.

when I say "not work", I have no reading between WA and WB, seems fully open.


the pins on the AD7376:

Vdd: +15Vdc
Vss: -15Vdc
GND: GND
A, B, W: resistance meter

\RS: nothing
\SHDR: nothing
SDO: nothing

I also did tests with Vdd:+5Vdc, Vss:GND, \RS: +5vdc, \SHDR: +5vdc
in both tests, was a "traditional" power supply: transformer, 4700u cap, 7815, 7915, 7805 regulators, protection diodes etc ... clean.
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Mon Apr 01, 2013 1:07 am     Reply with quote

I must admit, I think I'd drive this using software, rather than trying to use the SPI.
If you study the data sheet, the behaviour of the shift register suggests that it really should have CS raised after the seventh bit rather than the eighth to work ideally.
However their illustration shows a sequence that SPI should manage fine.
Table 7, tells you that in fact the starting level of the clock doesn't matter (x) in the row. and what happens at each state. Bits are latched at each rising edge in the clock, but the word is transferred at the rising edge of CS.
Using eight bits, the top bit should have shifted out the top of the register when this happens, so shouldn't matter at all. The data sheet confirms this with "Extra MSB bits are ignored".
However it sounds as if the chip doesn't really behave like this...
So trying seven bits instead:
Code:

#include <18F4520.h>
#use delay(clock=10000000)
#FUSES NOWDT, HS, NOPROTECT, NOBROWNOUT, PUT, NOCPD, STVREN, NODEBUG, NOLVP,
NOWRT, NOWRTD, NOIESO, NOFCMEN, NOPBADEN, NOWRTC, NOWRTB, NOEBTR, NOEBTRB,
NOCPB, NOMCLR, NOXINST
//as a comment, always have PUT with a crystal...

#define CS PIN_C0
#define SDO PIN_C5
#define SCL PIN_C3

void load_byte(int8 val)
{
   int8 mask=0x40; //start with the seventh bit
   int8 count;
   output_low(SCL);
   output_low(CS); //select the register
   //clock out seven bits
   for (count=0;count<7;count++)
   {
      if ((val ^ mask)!=0)
          output_high(SDO);
      else
          output_low(SDO);
      output_high(SCL); //latch the bit
      mask/=2; //next bit
      output_low(SCL);
   }
   output_high(CS); //load the byte to the pot
}

VOID main (VOID)
{
   int8 val;
   output_high (CS); //chip select
   output_low(CLK);
     
   delay_ms (1000);
   
   WHILE (TRUE)
   {     
      for (val=0;val<128;val++)
      {
         load_byte(val);
         delay_us(50);
      }
   }
}

Should give a sawtooth output, at about 150Hz.

I must say the data sheet is a "curate's egg", with some really noticeable contradictions in what it says/shows.

Best Wishes
ouch_



Joined: 27 Mar 2013
Posts: 12

View user's profile Send private message

PostPosted: Mon Apr 01, 2013 4:55 pm     Reply with quote

thanks Ttelmah,

but in your code, I did not understand where the value is to be sent.
sorry, I'm beginner.

trying manually, I wrote a code that is looped off and on PIN_C3 with delays of 3us between them, to generate the clock, etc ... can laugh of me! rssss looks good in scope.

and it works! (decimal "8")

Code:
#define CS PIN_C0
#define SDO PIN_C5
#define SCL PIN_C3

#define time (3)

VOID main (VOID)
{
   
   WHILE (TRUE)
   {       
      output_high(CS);
      output_high(SDO);
      output_high(SCL);
   
      delay_ms (5000);
     
      // start
   
      output_low(CS);
      delay_us (1);
     
      //------bit 7 - MSB //00001000
      //                    ^   
      output_low(SCL);
     
      output_low(SDO);
      delay_us (time);
           
      output_high(SCL);
     
      delay_us (time);
     
      //------bit 6 - //00001000
      //                 ^
      output_low(SCL);
     
      delay_us (time);
     
      output_high(SCL);
     
      delay_us (time);
     
      //------bit 5 - //00001000
      //                  ^     
      output_low(SCL);
     
      delay_us (time);
     
      output_high(SCL);
     
      delay_us (time);
     
      //------bit 4 - //00001000
      //                   ^
      output_low(SCL);
     
      delay_us (time);
     
      output_high(SCL);
     
      delay_us (time);
     
      //------bit 3 - //00001000
      //                    ^                         
      output_high(SDO); //UP
     
      output_low(SCL);
     
      delay_us (time);
     
      output_high(SCL);
     
      delay_us (time);
     
      output_low(SDO); //DOWN
     
      //------bit 2 - //00001000
      //                     ^     
      output_low(SCL);
     
      delay_us (time);
     
      output_high(SCL);
     
      delay_us (time);
     
      //------bit 1 - //00001000
      //                      ^
      output_low(SCL);
     
      delay_us (time);
     
      output_high(SCL);
     
      delay_us (time);
     

      //------bit 0 - //00001000
      //                       ^
      output_low(SCL);
     
      delay_us (time);

      output_high(SCL);
     
      delay_us (time);
     

      //--------------------------------------------
     
      delay_us (time);
      output_high(CS);
     
   }
}



and now?
ouch_



Joined: 27 Mar 2013
Posts: 12

View user's profile Send private message

PostPosted: Mon Apr 01, 2013 8:48 pm     Reply with quote

Working:

Code:
#USE SPI (MASTER, CLK=PIN_C3, DI=PIN_C2, DO=PIN_C5, MODE=3, BITS=8, STREAM=SPI_1, MSB_FIRST)

VOID main (VOID)
{
   WHILE (TRUE)
   {
      output_low (PIN_C0);
      spi_xfer(254);
      output_high (PIN_C0); 
   }
}



Not Working:

Code:
#USE SPI (MASTER, CLK=PIN_C3, DI=PIN_C2, DO=PIN_C5, MODE=3, BITS=8, STREAM=SPI_1, MSB_FIRST)

VOID main (VOID)
{
   WHILE (TRUE)
   {
      output_low (PIN_C0);
      spi_xfer(254);
      output_high (PIN_C0);
     
      delay_ms (5000); // <<<< diference
   }
}


why? Shocked Question
any delay cause the problem!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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