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

External ADC via SPI to PIC

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



Joined: 02 Mar 2010
Posts: 3

View user's profile Send private message MSN Messenger

External ADC via SPI to PIC
PostPosted: Wed Mar 03, 2010 7:42 am     Reply with quote

Hello, I am a starter of using CCS and PIC microcontrollers. I would like to interface an AD converter (AD7812) per SPI with the PIC 16F877A.
Before I start to run the program I would like to ask you, if you can have a look to my program code if there is some mistake in it. And I’ve got following basic questions:

1. If in CCS program it is programmed setup_spi = Master, is then automatically set the SPI port like SCLK=RC3, DOUT=RC5, DIN=RC4 and enable=RA5 as output?
The datasheet of the PIC 16F877A stats, that if the PIC runs in Master mode only the PIN's RC3=SCK, RC4=SDI, RC5=SDO are in use, but what makes the CCS compiler? Have I to set up the enable pin, so, that the slave device knows that a data transfer starts by enable on/off?
Or is it better to define all pin's by myself?

2. In the description of the AD converter is written that for serial data transfer the clock should be idle=0, data out (ADC) = data in (PIC) on the rising edge of the clock, data in (ADC)= data out (PIC) on the falling edge of the clock and therefore I decide to use SPI mode 1 ( MODE_0_1) is this correct?
Furthermore it is send MSB first, how should I deal with this/ is it ok how I have it programmed?

3. What is the meaning of SPI_SAMPLE at END?

Thanks a lot
R.B.

AD7812 datasheet:
http://www.analog.com/static/imported-files/data_sheets/AD7811_7812.pdf
Code:

// ////////////////////////////////////////////////////////////////////////////
// This is the first try for use an external 10 bit serial I/O AD converter   //
// with the SPI popssibility of both components (ADC= AD7812 and PIC=16F877A) //
// The connection is as followed:    ADC    PIC                               //
//  This connection is different    SCLK----SCK/RC3                           //
//  as it looks in the datasheet    DOUT----SDI/RC4                           //
//  of the AD 7812. But as it is     DIN----SDO/RC5                           //
//  described on lots of pages   ______                                       //
//  in the www it shold be       CONVST|                                      //
//  right                           RFS|-----RA5                              //
//                                  TFS|                                      //
// Furthermore it will be used an external oscilator (HS) of 20MHz. Also, to  //
// get the possibility to monitor the interested registers, it shold be used  //
// the ICD.                                                                   //
// Written by Ronny Barufke 02.03.2010                                        //
////////////////////////////////////////////////////////////////////////////////

/* PIC 16F877A setup */
#include <16F877A.h>
#device ICD=TRUE
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES DEBUG                    //Debug mode for use with ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18)
                                //used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected

#use delay(clock=20000000)

/* spi setup*/

setup_spi(SPI_MASTER | SPI_MODE_0_1 | SPI_CLK_DIV_4); //SPI mode 1 selected,
                                                      // SCLK clock=5MHz
#use spi (MSB_FIRST, SPI1)    // is it necessary to define the number of bits
                              //to 10? Datasheet of ADC serial interface
                              //timing diagram
                             
#define ADC_ENABLE PIN_A5     // is this also necessary? or it is done by any
#bit enable_tris=85.5         // other code before?

/* used varible for further programming */

int 16 adc_value;

/* Initialisation of AD converter */

void adc_init ()
 {
 
  int 8 value1, value2;
  enable_tris=0;
  ADC_ENABLE=1
  ADC_ENABLE=0
  spi_write(0x60);
  spi_write(0x40);
  delay_us(1.8);
  ADC_ENABLE=1
  ADC_ENABLE=0
  delay_us(2.5);
  value1=spi_read(0x40);
  value2=spi_read(0x40);
  value1=0;                        // no meaningfull data
  value2=0;                        // no meaningfull data
   
 }
// this void main (void) will be renamed later to adc_getv  the timeloop and  //
// repead of convertion is used to monitor the value register, later it will  //
// be canceled//

void main (void) {
   
           ADC_ENABLE=1
           ADC_ENABLE=0
           delay_us(2.5);
           value1=spi_read(0x40);
           value2=spi_read(0x40);
  /* here goes the bit opperation to get the 10 bit(of AD conversation into
  the 16bit adc_value  register. At this stage value1&value2 are monitored*/
           
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 03, 2010 3:21 pm     Reply with quote

Quote:

#define ADC_ENABLE PIN_A5

Pin A5 has no special meaning for an SPI Master. It's just an ordinary
i/o pin. Therefore, any i/o pin could be used. (But it's OK to use pin A5).

Quote:

setup_spi(SPI_MASTER | SPI_MODE_0_1 | SPI_CLK_DIV_4);
#use spi (MSB_FIRST, SPI1)

Don't use both methods of setting up the SPI. I suggest that you use
setup_spi(). It's easier. Delete the #use spi() statement.

Put these lines above main(). Use SPI_MODE_1 in your setup_spi()
statement:
Code:

// SPI mode definitions (for 16F and 18F PICs).
#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)



Quote:

#bit enable_tris=85.5 // other code before?

This line is not needed. The compiler will set the correct TRIS
automatically if you use output_low() and output_high().

Quote:

enable_tris=0;
ADC_ENABLE=1
ADC_ENABLE=0

Get rid of this code and use output_low() and output_high()
to control the enable pin.

Quote:

delay_us(1.8);
delay_us(2.5);

This syntax is not allowed. Only whole numbers are allowed.
See the CCS manual.

Here is a sample driver that may work. I don't have an AD7812 chip
to test, but I think this code follows the data sheet's instructions.
Code:

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

// AD7812 pins
#define AD7812_CONVSTB  PIN_A5

// SPI mode definitions (for 16F and 18F PICs).
#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)

// Function Prototypes
void ad7812_init(void);
int16 ad7812_read(void);

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

// Initialize the hardware SPI module to work with the
// AD7812, and init the \CONVST control signal.
// Since \CONVST is set to idle at a high level, the
// AD7812 will be operating in "Mode 1" which is for
// high-speed conversions (no power-down).
output_high(AD7812_CONVSTB);
setup_spi(SPI_MASTER | SPI_MODE_1 | SPI_CLK_DIV_4);
delay_ms(100);   

// Initialize the A/D chip.
ad7812_init();

// Read and display the A/D conversion result every 1/2 second.
while(1)
  {
   result = ad7812_read();
   printf("%lx \n\r", result);
   delay_ms(500);
  }

 
}

//=====================================
// FUNCTIONS

// Follow the init sequence shown in Figure 15 and
// described on page 13 of the AD7812 data sheet:
void ad7812_init(void)
{
// Do a short negative pulse on the \CONVST pin.
// Spec = 20ns minimum.  This code takes 600ns.
output_low(AD7812_CONVSTB);
output_high(AD7812_CONVSTB);

// Write 0x6040 to the AD7812 (per the data sheet).
spi_write(0x60);
spi_write(0x40);

// Wait for a 1.5us power-up delay.
delay_us(2);
}

//------------------------------
int16 ad7812_read(void)
{
int16 retval;
int8 lsb, msb;

// Do a short negative pulse on the \CONVST pin.
// Spec = 20ns minimum.  This code takes 600ns.
output_low(AD7812_CONVSTB);
output_high(AD7812_CONVSTB);

delay_us(3);  // Wait for conversion time (Spec = 2.3us min)

// Write 0x4040 to the AD7812, and read
// the conversion result at the same time.
// (Per AD7812 data sheet).
msb = spi_read(0x40);
lsb = spi_read(0x40);

// Combine the two bytes into a 16-bit value.
retval = make16(msb, lsb);

// Right justify the 10-bit A/D result.
retval >>= 6; 

return(retval);
}
R.B.



Joined: 02 Mar 2010
Posts: 3

View user's profile Send private message MSN Messenger

PostPosted: Wed Mar 03, 2010 4:11 pm     Reply with quote

Thanks a lot for this answer.
In this code what you post to me there is a program line which makes me confused.
Code:

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

I tried before I post my question, by using the Project wizard of the CCS compiler, to setup the SPI interface. And I've got also this line, where the RS 232 is setup. Why the compiler makes this? Because of this, I believed that my connection will be false and that I'm on the wrong way , but now I know that it will be ok? I will use the RS 232 as well, not yet, but later if my knowledges are far enough. Is there anything what I have to consider if I use this code what you post to me, for my current try? Or should I let it so as it is and work with?

Sorry for my english it is not my mother tongue, but I would like to improve it as well as my experience with the PIC Microcontroller.

Great thanks.
R.B.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 03, 2010 4:16 pm     Reply with quote

Pins C6 and C7 are the hardware UART pins on the 16F877A. It's
normal to use the hardware UART on the PIC to talk to a terminal
window on your PC.

What development board are you using ? Did you buy the board ?
If so, post the manufacturer and part number of the board.
Or, did you build the board yourself ?
R.B.



Joined: 02 Mar 2010
Posts: 3

View user's profile Send private message MSN Messenger

PostPosted: Wed Mar 03, 2010 4:52 pm     Reply with quote

Oh , it is used to talk with the PC. I would like to use the ICD 2 and will use the incircuit debugging by connecting the wire from the burner to the Pin's (RB7,RB6...), to monitor the interested register on the PC. This method i used one times only where I programmed the pic via MPLAB in assembler. But for my try I have to connect the pin's so as i state in my first post? And if this will work I decide to connect a LCD, then a Keypad... and finally I will try to transfer data via RS 232 to my PC and use this data in may be VISUAL Basic. But this is the thinking of the future, now I need to concentrate on the current task.
Sorry i am very tired, i spend the whole day in front of my PC.
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