AT89C51 Accelerometer Project

Thread Starter

myztic_man

Joined Apr 27, 2009
21
Hey guys.
Just seem to be running into some coding errors while trying to display values of a Triple Axis accelerometer (ADXL330).
I am using the AT89C51AC3 Micro.

The problem I am having is that I can't seem to cycle through each 'channel' to perform an ADC. (i need one for each axis, X, Y and Z). It works fine with just one channel in operation, but as soon as I try to have it cycle through several it throws a wobbly and gives me all kinds of strange results..
At the moment I am simply trying to print the values on the LCD screen (LCD screen is working no problem).

Code:

in Main:
{
P1=0x00; //This is the ADC port
ADCF = 0x07; //Configure Ports: ADC0, ADC1 and ADC2
ADCON = 0x20; //Enable ADC

while (TRUE)
{
char s [33];
unsigned int Result = Sample_ADC(AD0);
unsigned int Result2 = Sample_ADC(AD1);
unsigned int Result3 = Sample_ADC(AD2);
sprintf(s,"x:%d y:%d z:%d " , Result, Result2, Result3); //x: y:
}

Where:

unsigned int Sample_ADC(channel)
{
unsigned int Sample;
//Start a Conversion:
ADCON &= 0xF8; //Clear Field
ADCON |= channel; //Channel
ADCON |= 0x08; //Start Conversion

while ((ADCON & 0x10) != 0x10)
/* Do Nothing */;
ADCON &= 0xEF; //Clear conversion flag
Sample = (ADDH<<2)+(ADDL); //Read value from ADDH and ADDL registers.
return Sample;
}

Anyone got any ideas? I guess you would need a pretty good knowledge of this chip...
 

-SK-

Joined Apr 14, 2009
25
When you say 'strange results', what specifically happens? Does it display the same value for all channels, or just a wrong value? Or letters instead of numbers?
Since one channel works, your number conversion works. I would suggest the following approach:
1. run one channel at a time, but make sure all 3 work (stayathome's idea)
2. measure the analog output of the accelerometer manually to see if that is the source of the problem, or the code is.
If the accel works, then something with your channel selection is probably wrong. Is there anything else multiplexed with the other ADC pins that could possibly be switched in elsewhere in your code?
If accel doesn't work.....get a new one I guess.

If both work one at a time, try giving some delay between the sampling of each channel.
 

Thread Starter

myztic_man

Joined Apr 27, 2009
21
Thanks for your help guys, really appreciate it.

I have gone back to trying to do each channel individually and I am running into problems... It seems to be to do with my channel addressing (and this would explain the 'strange results' I was getting as I am probably selecting incorrect channels).

From the code in the sheet StayatHome recommended:

/* configure channel P1.6(AN6) and P1.7(AN7) for ADC */
ADCF = 0xC0;
......while(1)
{
ADCON &= ~0x07; /* Clear the channel field ADCON[2:0] */
ADCON |= 0x06; /* Select channel 6 */
ADCON &= ~0x40; /* standard mode */
ADCON |= 0x08; /* Start conversion */
}

The Command:
ADCON &= ~0x07; /* Clear the channel field ADCON[2:0] */
What exactly is this doing?
What is the purpose of the &= ~ ??

once again, thanks!
 
ADCON &= ~0x07;

ADCON = ADCON & ~0x07;

ADCON = ADCON & ~00000111 /* ~ gives one's complement which essentially flips the bits

ADCON = ADCON & 11111000

The line, ADCON &= ~0x07, sets the bits ADCON[2:0] to zero, clears the channel field, which leaving the rest of the bits alone.
 

Thread Starter

myztic_man

Joined Apr 27, 2009
21
Solution Found!

Turns out I was addressing each ADC Port incorectly..
ADCF (used to configure which ports are used as ADC) begins from 0x01, so 0x01 corresponds to having ADC.0 enabled.. However when actually performing the conversion the channel is selected via ADCON, which begins from 0x00 (0x00 being ADC.0).
I had messed these up as I did not realise that each was different.. Anyway, everything is ok now!

Working code:

void main() {
ADCF = 0x07; /* Configure Ports: ADC.0, ADC.1 & ADC.2 */
ADCON = 0x20; /* Enable ADC, Standard Mode Conversion (as opposed to 'high precision') */
value_AN0 = Sample_ADC(0x00); /* ADC.0 - x axis on my accelerometer */
value_AN1 = Sample_ADC(0x01); /* ADC.1 - y axis */
value_AN2 = Sample_ADC(0x02); /* ADC.2 - z axis */
}

/*ADC FUNCTION*/
unsigned int Sample_ADC(unsigned int selectChan)
{
unsigned int Sample;
ADCON &= 0xF8; /* Clear channel selection field */
ADCON |= selectChan; /*Select the channel to perform ADC */
ADCON |= 0x08; /* Start ADC Conversion */
while ((ADCON & 0x10) != 0x10); /* Wait for conversion to finish */
ADCON &= 0xEF; /* Clear conversion flag */
Sample = (ADDH<<2)+(ADDL); /* Read value from ADDH and ADDL registers. */
return Sample; /* Return the Digital Value */
}
 
Top