|
|
View previous topic :: View next topic |
Author |
Message |
sshahryiar
Joined: 05 May 2010 Posts: 94 Location: Dhaka, Bangladesh
|
MCP3202 12-bit Dual Channel SPI ADC Driver (Full) |
Posted: Mon Apr 08, 2013 11:36 am |
|
|
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
|
Example Code |
Posted: Mon Apr 08, 2013 11:45 am |
|
|
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
|
|
Posted: Mon Apr 08, 2013 4:11 pm |
|
|
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
|
|
Posted: Mon Apr 08, 2013 4:32 pm |
|
|
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
|
Regarding "map" Function |
Posted: Mon Apr 08, 2013 10:42 pm |
|
|
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 |
|
|
|
|
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
|