|
|
View previous topic :: View next topic |
Author |
Message |
Pichuqy_1
Joined: 03 Aug 2010 Posts: 38
|
Library to A/D (ADC101S021) by SPI |
Posted: Tue Aug 03, 2010 10:12 pm |
|
|
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
|
|
Posted: Wed Aug 04, 2010 12:12 pm |
|
|
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
|
|
Posted: Wed Aug 04, 2010 12:29 pm |
|
|
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
|
|
Posted: Wed Aug 04, 2010 1:32 pm |
|
|
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
|
|
Posted: Wed Aug 04, 2010 1:42 pm |
|
|
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
|
|
Posted: Wed Aug 04, 2010 5:19 pm |
|
|
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
|
|
Posted: Wed Aug 04, 2010 6:14 pm |
|
|
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
|
|
Posted: Thu Aug 05, 2010 2:08 pm |
|
|
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
|
|
Posted: Thu Aug 05, 2010 2:49 pm |
|
|
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
|
|
Posted: Thu Aug 05, 2010 3:44 pm |
|
|
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
|
|
Posted: Thu Aug 05, 2010 5:28 pm |
|
|
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.
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Aug 05, 2010 10:32 pm |
|
|
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
|
|
Posted: Fri Aug 06, 2010 5:33 am |
|
|
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
|
|
Posted: Fri Aug 06, 2010 1:18 pm |
|
|
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
|
|
Posted: Fri Aug 06, 2010 1:34 pm |
|
|
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. |
|
|
|
|
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
|