AT89C51 Accelerometer Project

Discussion in 'The Projects Forum' started by myztic_man, Apr 27, 2009.

  1. myztic_man

    Thread Starter Member

    Apr 27, 2009
    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).


    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:


    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...
  2. StayatHomeElectronics

    Well-Known Member

    Sep 25, 2008
  3. -SK-


    Apr 14, 2009
    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.
  4. myztic_man

    Thread Starter Member

    Apr 27, 2009
    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;
    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!
  5. StayatHomeElectronics

    Well-Known Member

    Sep 25, 2008
    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.
  6. myztic_man

    Thread Starter Member

    Apr 27, 2009
    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 */

    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 */