Hello,
i have problems to get a 10-Bit result from the internal adc of the AT89C51CC03.
I always got only a 8-Bit result, though setting the PSIDLE-Bit. Also i did not need the adc-eoc-interrupt to continue after the conversion, as it is explained in the device manual.
So it seems to me, i made something wrong in setting up the adc for 10-Bit resolution.
I include the following code, which should not run with disabled eoc-interrupt. But it runs !!!
#include "AT89C51CC03.h" unsigned int i; void main(void) { ADCF = 0x20; /* configure channel P1.5(AN5) for ADC */ ADCLK = 0x00; /* init prescaler for adc clock */ ADCON = 0x20; /* Enable the ADC */ EA = 0; /* disable interrupts */ EADC = 0; P31 = 1; // signal running via txd pin for (i=0; i< 20000; i++); while(1) { ADCON &= ~0x07; /* Clear the channel field ADCON[2:0] */ ADCON |= 0x05; /* Select channel 5 */ ADCON |= 0x40; /* 10 bit mode */ ADCON |= 0x08; /* Start conversion */ P31 = ~P31; // signal running via txd pin while (!(ADCON & 0x10)); ADCON &= 0xef; for (i=0; i< 20000; i++); } }
So please contact me, if you have any ideas, hints, solutions, etc.
have considered to use a "driver" for the ADC hardware ? this works on AT89C51AC3 @29.4912MHz X1 mode. also it takes care of the watchdog. minor adjustments for the Keil compiler may be needed.
// ADC 0-3V 8bit Standard or 10bit Best Precision at port P1[7..0] __bit adc_eoc = 0; // ADC end of conversion volatile unsigned char adc_val=0x00; // ADC value 8bit Standard Precision volatile unsigned int adc_value=0x00; // ADC value 10bit conversion Best Precision void ADC_ISR(void) __interrupt(ADC_VECTOR) __using (3) { ADCON &= ~ADEOC; // Set by Hardware at end of conversion. Clear by software adc_val = ADDH; // ADDH contains 8bit standard value of ADC adc_value = ADDH << 2; // ADDH:ADDL contains 10 bit value of ADC adc_value |= (ADDL & 0x03); // mask ADDL[1..0] lower bits best precision adc_eoc = 1; // Set adc_eoc semaphore to inform end of conversion } void initadc(unsigned char ADCFchannels) // setup P1 pins for ADC. call: initadc(CH6|CH7) 8BITS=8CHANNELS { ADCON = 0x00; // clear ADCF = 0x00; // clear all channels ADCF |= (ADCFchannels); // set CH6, CH7 as Analog Inputs ADCLK = 0x00; // ADCLK[4..0] PRS4..0 = 0 => X1 =Fxtal/128 // F_XTAL = 29.491200 MHz / 128 = 230.400 KHz ADCON |= ADEN; // ADCON.ADEN = Enable (Disable for low power consumption) // Tsetup =4usec before the first convertion EADC = 1; // IEN1.EADC Enable ADC Interrupt // EA=1 global interrupt enable should handled in main } unsigned char adcreadstd (unsigned char ADCONchannel) // Standard Precision call by channel to be converted 0..7 { ADCON &= ~(SCH2|SCH1|SCH0); // clear all SCH clannels 3BITS=8CHANNELS ADCON |= ADCONchannel; // Select channel ADCON.[SCH2..0] ADCON &= ~PSIDLE; // Standard converion 8bit clear ADCON.PSIDLE=0 ADCON |= ADSST; // Start conversion. Cleared by hardware after completion. while (!adc_eoc) resetWDT(); return (adc_val); } unsigned int adcreadpre (unsigned char channel) // Best Precision call by channel to be converted 0..7 { ADCON &= ~(SCH2|SCH1|SCH0); // clear all SCH clannels ADCON = channel; // Select channel ADCON.[SCH2..0] ADCON |= (PSIDLE|ADSST); // Best Precision convertion 10bit ADCON.PSIDLE=1, ADCON.ADSST=1 // PSIDLE stop MCU but not peripherals. The ADC_ISR wakes system while (!adc_eoc) resetWDT(); return (adc_value); }