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

MCP3202 12-bit Dual Channel SPI ADC Driver (Full)

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
sshahryiar



Joined: 05 May 2010
Posts: 94
Location: Dhaka, Bangladesh

View user's profile Send private message Send e-mail Visit poster's website

MCP3202 12-bit Dual Channel SPI ADC Driver (Full)
PostPosted: Mon Apr 08, 2013 11:36 am     Reply with quote

MCP3202.h

Code:
#use spi(MASTER, DI=PIN_A3, DO=PIN_A2, CLK=PIN_A0, BITS=8, MSB_FIRST) 


#define CS      pin_A1   
 

#define CH0_CH1_DIFF 0             
#define CH1_CH0_DIFF 1                     
#define CH0                 2     
#define CH1                 3                   
#define ADC_off           4   
                             

void MCP3202_init();
unsigned long read_ad(unsigned char ch);



MCP3202.c

Code:
#include "MCP3202.h"   

                                     
void MCP3202_init()               
{                           
         output_low(CS);   
}   
                   

unsigned long read_ad(unsigned char ch) 
{                                 
      unsigned char cmd = 0;     
      unsigned char lowByte = 0;
      unsigned char highByte = 0;
      register unsigned long adcValue = 0; 
                   
      switch(ch)
      {
         case CH0:
         {
            cmd = 0x80;   
            break;
         }
         case CH1:
         {
            cmd = 0xC0;   
            break;
         }
         case CH0_CH1_DIFF:
         {
            cmd = 0x00;   
            break;
         }
         case CH1_CH0_DIFF:
         {
            cmd = 0x40;   
            break;
         }
         default:
         {
            return 0;
         }
      }
      
      output_low(CS);
      spi_xfer(0x01);               
      highByte = spi_xfer(cmd);
      lowByte = spi_xfer(0x00);
      output_high(CS);
      adcValue = make16(highByte, lowByte);       
      adcValue &= 0x0FFF;
      return adcValue;                   
}

_________________
https://www.facebook.com/MicroArena

SShahryiar
sshahryiar



Joined: 05 May 2010
Posts: 94
Location: Dhaka, Bangladesh

View user's profile Send private message Send e-mail Visit poster's website

Example Code
PostPosted: Mon Apr 08, 2013 11:45 am     Reply with quote

Code:
#include <16F87.h>


#device *= 16


#fuses NOWDT, INTRC, PROTECT, CPD, PUT, NOWRT
#fuses NOMCLR, BROWNOUT,  FCMEN, NOIESO, NOLVP


#use delay (clock = 8MHz)

                                       
#include <lcd420.c>
#include "MCP3202.c"   
               
                                 
void setup();                                 
double map(double v, float x_min, float x_max, float y_min, float y_max);
unsigned long adc_avg(short channel);
                                                                                   
                             
void main()                       
{                                   
    register float V = 0.0; 
    register float I = 0.0;                                                 
    setup();                                                                         
    while(TRUE)                                                                       
    {                     
          V = adc_avg(0);   
          V = map(V, 0, 4095, 0, 5);   
          I = adc_avg(1);
          I = map(I, 0, 4095, 0, 5);
          I = (V - I);
          lcd_gotoxy(1, 1);
          printf(lcd_putc, "V: %1.3f V ", V);
          lcd_gotoxy(1, 2);           
          printf(lcd_putc, "I: %1.3f A  ", I);     
          delay_ms(400);                                             
    };                                                               
}                     
                                                                                                                                     
                           
void setup()
{
    setup_oscillator(OSC_8MHZ);
    disable_interrupts(global);
    setup_WDT(WDT_off);
    setup_comparator(NC_NC_NC_NC);
    setup_CCP1(CCP_off);         
    setup_SPI(SPI_disabled);           
    setup_timer_0(0|0|0);   
    setup_timer_1(T1_disabled);
    setup_timer_2(T2_disabled,255,1);
    set_timer0(0);
    set_timer1(0);           
    set_timer2(0);             
    MCP3202_init();           
    lcd_init();
    lcd_putc("\f");                       
    delay_ms(200);           
}   


double map(double v, float x_min, float x_max, float y_min, float y_max)
{
    float m = 0.0;     
    m = ((y_max - y_min)/(x_max - x_min));
    return (y_min + (m * (v - x_min)));
}


unsigned long adc_avg(short channel)
{
   unsigned char samples = 0;
   unsigned long long avg = 0;
   while(samples < 64)
   {                               
      switch(channel)
      {
         case 0:
         {
            avg += read_ad(CH0);
            break;                       
         }               
         case 1:
         {
            avg += read_ad(CH1);
            break;
         }
      }                     
      samples++;
      delay_us(4);                         
   }
   avg >>= 6;
   return avg;
}     

_________________
https://www.facebook.com/MicroArena

SShahryiar
asmboy



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

View user's profile Send private message AIM Address

PostPosted: Mon Apr 08, 2013 4:11 pm     Reply with quote

can you explain your implementation of

map()??

i see
Quote:

double
Is a reserved word but is not a supported data type.


and wonder why this function uses float math??
float is very very code space and time intensive.

is there no better way to do this ??

would integer precision not
1- be sufficient
2- be what you get anyway, after all the float grinding?
( if this compiles it will still be CCS std float anyway and 'mapped' to a narrow set of float values as it is due to limit of 2^12-1 in the call setup)

i'm puzzled by this function as presented
asmboy



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

View user's profile Send private message AIM Address

PostPosted: Mon Apr 08, 2013 4:32 pm     Reply with quote

since you are showing 12 bit data all the time,
and fixed scaling...
what do you get if you use:

Code:


unsigned int16 map( unsigned int16 inarg){
 unsigned int32 t1;

    t1=(unsigned int32) (inarg *501);
   return (t1>>12);
}

// then  with V as your 12bits

printf ("result %1.2w \r\n"', map(V));



this is far more efficient and i believe not lacking in accuracy either
sshahryiar



Joined: 05 May 2010
Posts: 94
Location: Dhaka, Bangladesh

View user's profile Send private message Send e-mail Visit poster's website

Regarding "map" Function
PostPosted: Mon Apr 08, 2013 10:42 pm     Reply with quote

The "map" function is nothing basically new. Apart from using CCS for PIC micros I also often play with Arduinos. Arduino IDE has a built-in function called map to scale an input data range to another desired data range. It impressed me a lot and I decided to integrate it CCS too. I wrote a post for it a few months back here:

http://www.ccsinfo.com/forum/viewtopic.php?t=49501.

It may not be efficient in terms of code size but it can save a lot of time when you have to get something done easily, fast or in a segmented pattern. Imagine if you have multiple ADC inputs and you have to scale them differently from one another. In such cases map function comes handy and a programmer has to worry less for calculations. Also note a scenario in which your input-output relation is non-linear, rather like a curve. You can have them segmented in small straight line and use map for different segments to get an approximate desired output without getting your 8 bit micro to solve high order-resource consuming mathematical manipulation.

In short "map" is like a straight line equation and it finds out the dependent variable by equating the given ranges of both input and output.

Lastly if it was a reserved word for any compiler then the compiler should have given an error. I also tested it with MikroC and it gave no error just like CCS.

Thanks.
_________________
https://www.facebook.com/MicroArena

SShahryiar
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library 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