View previous topic :: View next topic |
Author |
Message |
jojos
Joined: 30 Apr 2007 Posts: 64
|
mcp3208 A/D 12 bit problem |
Posted: Mon Nov 26, 2007 2:54 am |
|
|
Hello. I am using the MCP3208 A/D converter on my project.
The problem that i am facing up is i cant get a correct result from the A/D.
I am using the exact code from the drivers section of ccs compiler.
I have changed the Pin assignment to meet mine.
Generally i sample my inputs every 2 sec (the sampling i generated
from my 2 sec interrupt routine of Timer 1.
Now to test the A/D i sample only one channel. So i give the instruction
"a2dsolar1=read_analog(0)" and the result in a2dsolar1.
I am showing it on my 2x20 lcd screen.On the screen i can see this:
A symbol for the //thousand digit like : ; < and the next 3 digits are
numbers. I have checked the routine that converts the number to my
lcd screen format and it is correct.
Here is my code:
Code: |
///every 2 sec the interrupt of timer 1 calls getanalog
//in the init i configure the PORTA
//set_tris_a(0b00100010);
void main()
{
init();
adc_init();
loop:
//show a2dsolarvariable
goto loop;
}
void getanalog(void)
{
a2dsolar1=read_analog(0);
}
/////////////////and the mcp3208 code
#ifndef MCP3208_CS
#define MCP3208_CLK PIN_A0
#define MCP3208_DOUT PIN_A1
#define MCP3208_DIN PIN_A2
#define MCP3208_CS PIN_A3
#endif
void adc_init() {
output_high(MCP3208_CS);
delay_ms(1);
}
void write_adc_byte(BYTE data_byte, BYTE number_of_bits) {
BYTE i;
delay_us(2);
for(i=0; i<number_of_bits; ++i) {
output_low(MCP3208_CLK);
if((data_byte & 1)==0)
output_low(MCP3208_DIN);
else
output_high(MCP3208_DIN);
data_byte=data_byte>>1;
delay_us(50);
output_high(MCP3208_CLK);
delay_us(50);
}
}
BYTE read_adc_byte(BYTE number_of_bits) {
BYTE i,data;
data=0;
for(i=0;i<number_of_bits;++i) {
output_low(MCP3208_CLK);
delay_us(50);
shift_left(&data,1,input(MCP3208_DOUT));
output_high(MCP3208_CLK);
delay_us(50);
}
return(data);
}
long int read_analog_mcp(BYTE channel, BYTE mode) {
int l;
long int h;
BYTE ctrl_bits;
delay_us(200);
if(mode!=0)
mode=1;
output_low(MCP3208_CLK);
output_high(MCP3208_DIN);
output_low(MCP3208_CS);
if(channel==1) // Change so MSB of channel #
ctrl_bits=4; // is in LSB place
else if(channel==3)
ctrl_bits=6;
else if(channel==4)
ctrl_bits=1;
else if(channel==6)
ctrl_bits=3;
else
ctrl_bits=channel;
ctrl_bits=ctrl_bits<<1;
if(mode==1) // In single mode
ctrl_bits |= 1;
else // In differential mode
ctrl_bits &= 0xfe;
ctrl_bits=ctrl_bits<<1; // Shift so LSB is start bit
ctrl_bits |= 1;
write_adc_byte( ctrl_bits, 7); // Send the control bits
h=read_adc_byte(8);
l=read_adc_byte(4)<<4;
output_high(MCP3208_CS);
return((h<<8)|l);
}
long int read_analog( BYTE channel ) // Auto specifies single mode
{
return read_analog_mcp( channel, 1);
}
|
What could be wrong?
Do i have to do something else to get my data?I just call read_analog
and i wait to return to me some int16 variable. Thank you. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Nov 26, 2007 5:55 pm |
|
|
Quote: | The problem that i am facing up is i cant get a correct result from the A/D. I am using the exact code from the drivers section of ccs compiler. |
1. Post the printf() statement that you are using to display the adc value
on your LCD.
2. Post your PIC
3. Post your compiler version. |
|
|
jojos
Joined: 30 Apr 2007 Posts: 64
|
|
Posted: Wed Nov 28, 2007 6:58 am |
|
|
Ok i found the problem.I had to shift >>4 the result of the read_analog function to get the correct result.Thank you again |
|
|
|