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 CCS Technical Support

need help regarding SPI ADC and PIC.

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



Joined: 02 Dec 2010
Posts: 22

View user's profile Send private message

need help regarding SPI ADC and PIC.
PostPosted: Thu Nov 17, 2011 2:36 am     Reply with quote

Hi all, I am new to CCS, I want help regarding interfacing and programming SPI ADC (MAX1416) . I am using pic18f252 micro. CCS version is 4.124

this is what i am doing to configure adc.

Code:
 #include <18f252.h>
#device icd=true
#fuses HS,NOLVP
#USE DELAY (CLOCK=20M)
#use rs232(baud=19200, xmit=PIN_c6, rcv=PIN_c7,parity=N)
//#use spi(Master, FORCE_HW)

void main(void)
{
   unsigned int16 data=0; unsigned int8 data1=0,data2=0;
   setup_spi (SPI_MASTER | SPI_CLK_DIV_64 | SPI_h_TO_l | SPI_XMIT_L_TO_H);
   
   
   while(true)
   {     
     
      spi_write(0b00100000);  // com regs
      spi_write(0b10100101);  // clk regs
         
      spi_write(0b00010000);  // com regs
      spi_write(0b00000100);  // setup regs
     
      spi_write(0b00111000);  // com regs ,data register selected
      data1 = spi_read(0);
      data2 = spi_read(0);
     
      data = make16(data2,data1);
      printf("data is %lu \r\n",data);
      delay_ms(500);
     
   }

}


But this is not working at all. Confused Please guide me if i m doing wrong in this code.

My hardware connection are as follows.
pic SDI ----> ADC's D0ut
pic SDO ----> ADC's Din
pic sck ----> ADC's Sclk
pic RC2 ---> ADC's drdy

ADC's CS is tied to ground, Reset pin is pulled up.


MAX1416 data sheet : http://datasheets.maxim-ic.com/en/ds/MAX1415-MAX1416.pdf

Thank You and Best regards.
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Thu Nov 17, 2011 5:26 am     Reply with quote

Start with your SPI setup.
The data sheet description, corresponds to CPOL=1, CPHA=1. Mode3, is standard SPI terminology, which from the following table:
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)

So this looks right.

Then working through Figure 11.

Step through register settings. Com, setup clock, com, setup. At this point your code 'diverges' from the example, which writes 0x44 to setup, while you write 0x04. So gain of 1, versus gain of 4. Still looks OK.

Then, you miss a critical bit. You need to wait for DRDY to go low, either going down the right hand side of the flowchart, and polling the software DRDY bit, till the conversion is complete, or reading the hardware bit. You miss this completely....
So:

Code:

      spi_write(0b00100000);  // com regs
      spi_write(0b10100101);  // clk regs
         
      spi_write(0b00010000);  // com regs
      spi_write(0b00000100);  // setup regs
     
      while (input(PIN_C2)==1) ; //wait for conversion to complete

      spi_write(0b00111000);  // com regs ,data register selected
      data1 = spi_read(0);
      data2 = spi_read(0);
     
      data = make16(data2,data1);
      printf("data is %lu \r\n",data);
      delay_ms(500);

Till this line drops the data is not ready, so your zero results make sense.

Best Wishes
zeeshan ahmed



Joined: 02 Dec 2010
Posts: 22

View user's profile Send private message

SPI Clock problem
PostPosted: Thu Nov 17, 2011 11:16 am     Reply with quote

Thanks Ttelmah for your time.

I made the changes in the code suggested by you.

The problem is still there, still i am getting zero. I checked the data and clock lines with an O scope. but there is no clock and data signal. Confused

I have checked my hardware and it seems ok.

Please let me know if i am doing something wrong.

Thank U.... Best wishes
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Fri Nov 18, 2011 4:51 am     Reply with quote

OK.
I'm reading this as you seeing no SCL clock at all out of the PIC?.
If so, then start at a lower level.
First, do a simple 'hello world' on your serial. No SPI at all. Does this work?. If so, you have proved:
1) The PIC is alive - so no clock problem/power problem etc..
2) The PIC is running at the right speed.
Then step along, and do a basic 'toggle' on each of the lines SDO, and SCL. Do these toggle OK?.
If so, you have proved there isn't a short or something stopping these from working.

Come back after these basic tests.

Best Wishes
zeeshan ahmed



Joined: 02 Dec 2010
Posts: 22

View user's profile Send private message

PostPosted: Fri Nov 18, 2011 4:58 am     Reply with quote

I found another problem. I observed using an O scope, that ADC'c Dout line remains in High impedance state all the time. While ADC's CS pin is tied to ground.

Secondly Drdy line continously toggling, which shows that the new conversion result is available. Now Sclk and Din Lines are working properly. But the result is still garbage.

Please Help....
Thanks alot.
zeeshan ahmed



Joined: 02 Dec 2010
Posts: 22

View user's profile Send private message

PostPosted: Fri Nov 18, 2011 5:05 am     Reply with quote

Thanks Ttelmah ...
I have done all the basic tests. PIC is doing Good. I found no problem in hardware. Serial Port test & I/O operation of Spi port is also successful.
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Fri Nov 18, 2011 5:27 am     Reply with quote

OK.
Now, if the chip was reset, it should wake up _not_ performing automatic conversions. The fact it is performing such conversions, saya:
1) Possibly the chip is not waking up properly.
or
2) The chip _is_ receiving the SPI packet from the PIC.

So. I'd suggest two things:
First, try having a reset circuit, to hold the chip in reset for a few moments after power is applied. Capacitor on the reset pin, pull up resistor, diode across this to discharge the capacitor when power is removed, and pause the code for a few mSec on start to ensure the chip has time to start. Before you pause, set the SCK line high. This then ensures that the line is high when the chip wakes up, and avoids getting out of sync at this point.

Then just change your code a little. Look at figure11 again, and realise you only have to loop back to checking the DRDY bit, not re-initialise the chip every time round the loop.

Best Wishes
zeeshan ahmed



Joined: 02 Dec 2010
Posts: 22

View user's profile Send private message

Still facing problem
PostPosted: Sat Nov 19, 2011 1:47 am     Reply with quote

Thank You Ttelmah...

I did what you told me. But the problem is still there. Sad

I noticed one thing that, whenever I try to read 8 bit register e.g clock register, controller works perfect, and Dout line shows correct data. But whenever I try to read 16bit register i.e Data register, Dout line goes in high impedance. I think this is due to the reason that SPI supports 8 bit data transfer.
Now my code is

Code:

#include <18F252.h>
#fuses HS, NOWDT, PUT, BROWNOUT, NOLVP   
#use delay(clock = 20000000)   
#use rs232 (baud=9600, rcv=pin_c7, xmit=pin_c6)

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

//========================================
void main()
{
   int16 data=0; int8 data1=0,data2=0; 
   setup_spi(SPI_MASTER | spi_mode_3 | SPI_CLK_DIV_64);
   output_high(pin_c3);        // clock high
   delay_ms(1000);

    spi_write(0b00100000);  // com regs
    spi_write(0b10100101);  // clk regs
    spi_write(0b00010000);  // com regs
    spi_write(0b01000100);  // setup regs
         
while(1)
  {
         
      while (input(PIN_C2)==1) ; //wait for conversion to complete

      spi_write(0b00111000);  // com regs ,data register selected
      data1 = spi_read(0x00);
      data2 = spi_read(0x00);
     
      data =  make16(data2,data1);
      printf("data is %lu\r\n",data);
  }
}


I have connected a capacitor and diode on reset pin.
Also I can observe clock signal of 2.493MHz at pin 3 of ADC, which shows proper configuration.

Please help.
Thank you & best Regards
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Sat Nov 19, 2011 3:38 am     Reply with quote

There is nothing special about a 16bit transfer versus an 8bit one. SPI, is synchronous, so 'synchronises' to the clock it is sent. An 8bit transfer sends 8 clocks without a break, while a 16bit transfer just has a slightly longer clock between the 8th and 9th bit, as the first byte is read, and the second loaded. There is no minimum speed for SPI transfers (there are for some chips, but these are still plenty long enough to pause for a moment like this), so the pause doesn't matter at all.

Now, two things worry me about the data sheet:
The first is which chip is 5v, versus 3.3v. The number of places where the 1415, is listed as the 5v chip is 'scarey'.....
Then the question of CS. If you have got a separate pin available, I'd drive this. So when you see DRDY go low, then drop CS, and perform the transfer, and when you finish the transfer raise CS. Using SPI without a CS, is always very fussy. Problem is that if the chip 'sees' an extra clock transition for any reason at all (noise, timing during power-up, etc. etc.), then the slave device, and the master device _will_ be out of sync. All the timing diagrams in the data sheet show CS being used, though the sheet refers to using the chip in 3wire mode, without it.

As a general comment, the data sheet says the high byte is sent first, so you have your variables reversed in the make16 operation.

Realistically, if it doesn't work with CS to add synchronisation, there has to be a hardware fault somewhere. Your code now corresponds exactly to the data sheet flowchart. When you tested that you could toggle SDO, and SCL, did you test that these were actually toggling at the pins of the ADC?. Similarly with all other connections. Triple check.

Best Wishes
zeeshan ahmed



Joined: 02 Dec 2010
Posts: 22

View user's profile Send private message

Problem Solved
PostPosted: Wed Nov 23, 2011 12:27 am     Reply with quote

Many Thanks "Ttelmah"

Controlling the CS line solved the problem. Now I am able to read data through ADC. I also reversed the variables. I am bit banging the spi port to get the data in.

For bit banging I use this function.
Code:

      for(i=0;i<=15;i++)
      {
         output_low(pin_c3);
         delay_cycles(1);
         shift_left(bdta,2,input(PIN_c4));
         output_high(pin_c3);
         delay_us(.8);
      }

This function is working properly, and I am not getting garbage.

But using SPI read function,
Code:

      data1 = spi_read(0x00);
      data2 = spi_read(0x00);

I am getting alternate ADC result and 0x00.
e.g.
Hyper terminal shows

0 // garbage
62309 // valid adc data
0
62308 // valid adc data
0

Please tell me what is the reason behind getting a 0.

Thank you again.
Best wishes.
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Wed Nov 23, 2011 3:56 am     Reply with quote

You don't show in the new code, where you are operating the CS line, when using the hardware SPI?.
This must be raised, before you go back to testing for DRDY.
I suspect what is happening is CS is not being operated correctly, so DRDY thinks the read has not yet completed, and stays low. The code then loops a second time, and reads blank values, since a new conversion has not occurred.

Best Wishes
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Wed Nov 23, 2011 6:21 am     Reply with quote

Ttelmah wrote:
You don't show in the new code, where you are operating the CS line...
This must be raised, before you go back to testing for DRDY.
I suspect what is happening is CS is not being operated correctly, so DRDY thinks the read has not yet completed, and stays low.


I've looked at the data sheet and its not clear as to how the CS line should be used. It talks about "an operation" on the SPI without stating what that really means.

There isn't really any seperate "reads" and "writes" with SPI. When the master clocks SCK, data is transferred in both directions at once, reads can and in many devices do happen at the same time as writes. While CCS does give you spi_read() and spi_write() they are essentially the same thing. You can just use spi_read() for everything:

Received_Byte = spi_read(Transmitted_Byte);

All you need to do is ignore the byte read if its not got anything importanat in it, and transmit whatever you want (a "dont care") when you just want to send. You have to give spi_read() something to send, anything, as otherswise it doesn't generate any clocks on SPI masters. You can use spi_read() without a sent byte on SPI slaves, and it will then wait for the master to clock the byte to it.

The newer software SPI stuff doesn't have reads and writes, it just has spi_xfer(), xfer being short for "transfer".

Anyway, I suspect that for this ADC, you may have to do "writes" (or transfers ignoring any data that's read) and "reads" (or transfers where you don't care what's sent) as completely separate SPI sequences. What I mean is that you may have to raise CS after the "write" and then drop it for the following "read":

Wait for data ready...
Drop CS.
Send 0x38 to ask for data.
Maybe wait a little here depending on ADC timing requirements. A few cycles only that is.
Raise CS (this ends the "write" "operation")
Drop CS for the read.
Read the data as two bytes.
Raise CS (ends the "read" "operation")

Your bit bashing code drops CS before the read and raises it after, just like the process above. Your spi_read version doesn't do this, as far as I can see you keep CS low. It may be that the ADC is ignoring the first read after the write, and only giving you the data next time around.

This doesn't make much sense with the "keeping CS low all the time" mode however... but you couldn't get that to work.... so....

One more thing. DRDY is cleared by reading the data. So, while the data sheet doesn't say so, you really need to wait for it to clear after you read otherwise your loop may go round and read again immediately. This may be what's happening with your code, as spi_read() is faster and more code efficient than bitbashing, so its more likely to go round twice before DRDY clears, only the second time there's no data as the ADC hasn't finished its conversion. So, maybe try adding a wait for DRDY to clear after reading. On the other hand the time for DRDY to clear, t8 on the datasheet, is just 100ns so it should be clear before the PIC has finished reading the data.

There's nothing magic about bitbashing. The hardware version should work perfectly, and is far more efficient and is simpler.

Maybe something here will help. Experiment and tell us what you find.

RF Developer
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Wed Nov 23, 2011 8:44 am     Reply with quote

Yes.
If you look again at the data sheets, you will see that DRDY, is meant to go high, 100nSec after CS goes high on the read. This is why I as saying he does not show what he is doing with CS on the reads. It needs to go high when he completes the reads, or there doesn't seem to be any guarantee it will have gone high when it is next checked, and as you say, this will then result in a second read. I suspect what then happens is after just one clock, the line does rise, but by then the master has started reading, and then just gets the 0 value.

Best Wishes
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