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

Library to A/D (ADC101S021) by SPI
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
Pichuqy_1



Joined: 03 Aug 2010
Posts: 38

View user's profile Send private message MSN Messenger

Library to A/D (ADC101S021) by SPI
PostPosted: Tue Aug 03, 2010 10:12 pm     Reply with quote

Hi. I'm trying to use an A/D by SPI, ADC101S021
http://www.national.com/pf/AD/ADC101S021.html#Overview

But I can not understand how to create the library for this.
This is what I could do:
Code:

#include <16F887.h>
#device adc=10
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)

#include <HDM64GS12.c>
#include <graphics.c>

#define ADC101S021_CS      PIN_A5
//#define SPI_MODE_0_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
//#define SPI_MODE_0_1 (SPI_L_TO_H)
//#define SPI_MODE_1_0 (SPI_H_TO_L)
//#define SPI_MODE_1_1 (SPI_H_TO_L | SPI_XMIT_L_TO_H)

void main()
{
   float  adc=0,valor;
   CHAR A5[ ]="A5";

   
   setup_spi(spi_master|SPI_H_TO_L|SPI_XMIT_L_TO_H|spi_clk_div_16);   
   
   setup_adc_ports(sAN0|sAN1|sAN3);           
   setup_adc (adc_clock_internal);             
   setup_adc(ADC_CLOCK_DIV_8);               
   delay_us(10);

   While(1){
   output_low(ADC101S021_CS);
   valor=spi_read();
   delay_ms(1000);
   output_high(ADC101S021_CS);   
}
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Aug 04, 2010 12:12 pm     Reply with quote

The ADC101S021 is a simple chip so I quickly wrote a driver for it.
I don't have this chip to test, but the driver below will probably work.

Make the following connections between the 16F887 and the ADC chip:
Code:

PIC pin   ADC pin
 SDI       DATA
 SCK       SCLK
 PIN_C2    \CS

The PIC and the ADC chip must also have a ground connection between
them (Vss on PIC to GND on ADC).

Here is a test program:
Code:

#include <16F887.h>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#define ADC101S0121_CS  PIN_C0

// SPI mode definitions.
#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)

//---------------------------------------------
int16 read_adc101s021(void)
{
int8 lsb;
int8 msb;
int16 result;

output_low(ADC101S0121_CS);
msb = spi_read(0);
lsb = spi_read(0);
output_high(ADC101S0121_CS);

result = make16(msb, lsb);  // Combine msb and lsb into 16-bits

result >>= 2;  // Right-justify the result (per data sheet)

result &= 0x3FF;  // Only the lower 10 bits are valid data

return(result);
}

//==========================================
void main()
{
int16 adc_result;

output_high(ADC101S0121_CS);  // Initialize \CS to inactive state

// The ADC chip uses SPI mode 3 (per the data sheet).
// The SPI clock must be from 1 to 4 MHz (per data sheet).
// 20 MHz PIC oscillator divided by 16 gives 1.25 MHz for SCLK.
setup_spi(SPI_MASTER | SPI_MODE_3 | SPI_CLK_DIV_16);
delay_ms(10);

while(1)
  {
   adc_result = read_adc101s021();
   printf("%lu \n\r", adc_result);
   delay_ms(500);
  }

}
Pichuqy_1



Joined: 03 Aug 2010
Posts: 38

View user's profile Send private message MSN Messenger

PostPosted: Wed Aug 04, 2010 12:29 pm     Reply with quote

Hi PCM programmer, thanks for the reply. Let me try it, and then I am gonna tell you if it works.
Pichuqy_1



Joined: 03 Aug 2010
Posts: 38

View user's profile Send private message MSN Messenger

PostPosted: Wed Aug 04, 2010 1:32 pm     Reply with quote

I'm trying but it doesn't work. I think there is a mistake in this part of the code:

#include <16F887.h>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#define ADC101S0121_CS PIN_C0


I'm using the CS PIN A5, but neither works.
Look, the device that use this AD is this:
http://www.parallax.com/StoreSearchResults/tabid/768/txtSearch/27922/List/0/SortField/4/ProductID/588/Default.aspx

Thanks a lot.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Aug 04, 2010 1:42 pm     Reply with quote

Quote:
I'm trying but it doesn't work.

Describe the failure.

Are you using my posted code, exactly, or did you modify it ?

Have you ever made your PIC board do anything, such as blink an LED ?
Pichuqy_1



Joined: 03 Aug 2010
Posts: 38

View user's profile Send private message MSN Messenger

PostPosted: Wed Aug 04, 2010 5:19 pm     Reply with quote

Yes. I've done a lot of work with PIC and CCS C, but I've never used the SPI before. I'm new in this topic. I always use the PROTEUS to simulate my works with PICS but now, with this ADC, i can´t do that. The program that I'm using is the same as you gave me with some difference. It doesn't work because when I move the Gyroscope, the value don't change.
Code:

#include <16F887.h>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include <HDM64GS12.c>
#include <graphics.c>

#define ADC101S0121_CS  PIN_A5

// SPI mode definitions.
#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)


//---Sequence that converts the value of adc in a text to represent the GLCD screen.

void displayVoltage(int adc)
{

   char voltage[9];
      char unidad [] ="LISY300:";
      sprintf(voltage, "%f", (float)adc);
      voltage[4] = '\0';
      glcd_text57(0, 0, voltage, 1, 1);
      glcd_text57(80, 0, unidad, 1, 1);
}

//---------------------------------------------
int16 read_adc101s021(void)
{
int8 lsb;
int8 msb;
int16 result;

output_low(ADC101S0121_CS);
msb = spi_read(0);
lsb = spi_read(0);
output_high(ADC101S0121_CS);

result = make16(msb, lsb);                 // Combine msb and lsb into 16-bits

result >>= 2;                             // Right-justify the result (per data sheet)

result &= 0x3FF;                          // Only the lower 10 bits are valid data

return(result);
}

//==========================================
void main()
{
int16 adc_result;

output_high(ADC101S0121_CS);                 // Initialize \CS to inactive state

// The ADC chip uses SPI mode 3 (per the data sheet).
// The SPI clock must be from 1 to 4 MHz (per data sheet).
// 20 MHz PIC oscillator divided by 16 gives 1.25 MHz for SCLK.

setup_spi(SPI_MASTER | SPI_MODE_3 | SPI_CLK_DIV_16);
delay_ms(10);

while(1)
  {
   adc_result =read_adc101s021();
//   printf("%lu \n\r", adc_result);
//   delay_ms(500);
 
   glcd_init(on);                        
   displayVoltage(adc_result);             
   delay_ms(500);

}

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Aug 04, 2010 6:14 pm     Reply with quote

Quote:

It doesn't work because when I move the Gyroscope, the value don't change.

1. Post the value that you get.

2. Did you build the PIC board yourself, or did you buy the PIC board ?
If you bought it, post the Manufacturer and model number of the board.

3. Post a list of connections between the PIC and the Gyro board.
Don't post the signal names. Post the pin numbers (and connector labels).
Look at the boards to see the connections. Trace the connections with
your eyes or your hands, so you post the actual connections that you see.

4. What is the Vdd voltage used for the PIC and for the ADC ?
Measure them with a voltmeter. Measure it on the Vdd pin of each
chip (PIC and ADC), with respect to ground.

5. What is your CCS compiler version ?
Pichuqy_1



Joined: 03 Aug 2010
Posts: 38

View user's profile Send private message MSN Messenger

PostPosted: Thu Aug 05, 2010 2:08 pm     Reply with quote

Hi PCM programmer. I´m sure that the board is ok.

The value that I get is 1022, and it is not posible. So, I've study the code and I've found a mistake... look
Quote:

int16 read_adc101s021(void)
{
int8 lsb;
int8 msb;
int16 result;

output_low(ADC101S0121_CS);
msb = spi_read(0);
lsb = spi_read(0);
output_high(ADC101S0121_CS);

result = make16(msb, lsb); // Combine msb and lsb into 16-bits

result >>= 2; // Right-justify the result (per data sheet)

result &= 0x3FF; // Only the lower 10 bits are valid data

return(result);
}

I think it must be: result >>= 3; isn't it?

thank you.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Aug 05, 2010 2:49 pm     Reply with quote

The ADC data sheet says:
Quote:

Sixteen SCLK cycles are required to read a complete sample
from the ADC. The sample bits (including leading or trailing
zeroes) are clocked out on falling edges of SCLK, and are
intended to be clocked in by a receiver on subsequent rising
edges of SCLK. The ADC will produce three leading zero bits
on SDATA, followed by ten data bits, most significant first.
After the data bits, the ADC will clock out two trailing zeros.

http://www.national.com/ds/DC/ADC101S021.pdf

Do you whatever you want to do.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Aug 05, 2010 3:44 pm     Reply with quote

Quote:
I´m sure that the board is ok.
Famous last words....

Quote:
The value that I get is 1022, and it is not posible.
Why do you think this is not possible? A 10-bit converter can return values in the range 0-1023. So 1022 means you are measuring a value almost equal to the supply voltage.

Here on this forum we are willing to help you, but from your answers it sounds like you are behaving stubborn. Probably this is a misunderstanding because English is not your first language, neither as it is mine. If you want more help, then you'll have to answer the open questions nr. 2 to 5 from PCM Programmer.
Pichuqy_1



Joined: 03 Aug 2010
Posts: 38

View user's profile Send private message MSN Messenger

PostPosted: Thu Aug 05, 2010 5:28 pm     Reply with quote

My apologies. Do not get angry with me. English is not my first language and I have some troubles expressing my ideas. I just want to learn it.
I'm electronic engineering student.

I'll try to tell you my problems.

2_ I build the PIC board myself.
4_ The Vdd voltage used for the PIC is 5 V and for the ADC is 3.3 V . The datasheet say: (Internally the LISY300AL Gyroscope generates approximately 1.6V on its analog output when it is still.
This value is affected very little by temperature so compensation is not required. The output of the
LISY300AL is fed into a National Semiconductor ADC101S021 10-bit ADC. This ADC has a high-speed (4
MHz) SPI interface and the signal pins can operate at 3.3V and 5V. Both the gyroscope and the ADC are
internally regulated to 3.3V. )
. So (3.3V/1024=0.0032) and (1.6V/0.0032=496 converter steps approximately). But I see 1022.
5_ My CCS compiler version is 4.105.

I'll check all the conection and the program. Thanks a lot for your help. I promess you improve my English.
Crying or Very sad
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Aug 05, 2010 10:32 pm     Reply with quote

Quote:

The Vdd voltage used for the PIC is 5 V and for the ADC is 3.3 V

These voltage levels are a problem. When using hardware SPI, the
PIC's SDI pin requires a Vih (high level input voltage) of .8 x Vdd = 4.0
volts. Your ADC can't drive the SDI pin to the correct level.

There are two solutions:

1. Add a level converter chip:
If you want to use hardware SPI in the PIC, then need to use the previous
program I posted. You also need a TTL to 5v CMOS level converter buffer
between the SDO pin on the ADC and the SDI pin on the PIC.
You could use a 74HCT125, and run it from +5v. This buffer will convert
the ADC's 3.3v CMOS levels to the 5v CMOS levels required by the PIC.
The enable pin on the 74HCT125 should be connected to Ground.


2. Use software SPI on the PIC. In that case, the SDI on the PIC is
used as an ordinary i/o pin. In that mode, Vih is only is only 2.0v
for the SDI pin, and it will work with the ADC.

Here is a software SPI driver for the ADC101S021. It uses your existing
connections between the PIC and the ADC, so you shouldn't have to
change anything. I haven't tested this in hardware, but I think it might work.

The ADC data sheet says the SCLK should be between 1 MHz and 4 MHz,
but it also says it's allowed to go as low as 25 KHz. The duty cycle is
supposed to be between 40 to 60%. I've tried to make it be 50% in
the code below. So with a 20 MHz crystal, the for() loop takes about
10 us, which gives an SCLK frequency of about 100 KHz. I don't know
what effect this will have on the ADC result. But if you don't want to add
the level-converter chip, then you can try this method. See if it works OK:
Code:

#include <16F887.h>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#define ADC_CS    PIN_A5
#define ADC_SDO   PIN_C4   
#define ADC_SCLK  PIN_C3 

//---------------------------------------------
int16 read_adc_word(void)
{
int8 i;
int16 result;

output_low(ADC_CS);

// Read 16 bits of data using SPI mode 3.
for(i=0; i<16; i++)
   {
    output_low(ADC_SCLK); 
    delay_cycles(18);      // Force a 50% duty cycle
    output_high(ADC_SCLK);
    shift_left(&result, 2, input(ADC_SDO));
   }

output_high(ADC_CS);

result >>= 2;  // Right-justify the result (per data sheet)

result &= 0x3FF;  // Only the lower 10 bits are valid data

return(result);
}



// Initialize \CS and SCLK to their inactive states.
void adc_init(void)
{
output_high(ADC_CS); 
output_high(ADC_SCLK);
output_float(ADC_SDO);

delay_ms(10);
}

//==========================================
void main()
{
int16 adc_result;

adc_init();  // Call this first

while(1)
  {
   adc_result = read_adc_word();
   printf("%lu \n\r", adc_result);
   delay_ms(500);
  }

}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Aug 06, 2010 5:33 am     Reply with quote

Another option for the voltage level problem is to reduce the voltage of the PIC16F887 to the same 3.3V as the ADC. According to figure 17.1 of the data sheet you will then have to reduce the PIC clock frequency to 10MHz or lower.

Doing it like this everything (PIC, ADC and gyro) will be running of the same voltage and will get you rid of the separate 5V power supply.
Pichuqy_1



Joined: 03 Aug 2010
Posts: 38

View user's profile Send private message MSN Messenger

PostPosted: Fri Aug 06, 2010 1:18 pm     Reply with quote

Hi PCM programmer and ckielstra. Thanks for help me.
This is the circuit that I'm using.:


PCM programmer: I've tried to use software SPI, with the program that you give me but it's show me 30 approximately. I'm gonna buy the 74HCT125 and I'll try with it.

ckielstra: I think that I can't use 3.3 V with the PIC because the GDM12864 doesn't work. I've tried it but nothing.

Thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Aug 06, 2010 1:34 pm     Reply with quote

1. What is your compiler version ?

2. I don't see any 100 nF (0.1 uF) capacitors on the Vdd pins of the PIC.
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