24-bit ADC on MINI-MAX/51-F board


The example reads 24-bit analog values and prints them to terminal. Target processor is MSC1211Y4.

Toolkit:SDCC 8051 Development System

Location:/bipom/devtools/SDCC/examples/mm51f/adc

Code Example


UINT ReadAdc_MM51F( UBYTE channel, UBYTE* buffer )
{
	register UINT adcValue;
	register UBYTE tempValue,i;
	register int decimation;
	// Timer Setup 

	PASEL = 0xFF;
	USEC   = 21; 					// 22 MHz Clock

	ACLK   = 17; 					// ACLK = 22,1184,000 / 18 = 1.2288MHz

									// modclock = 1.2288MHz / 64 = 19,200 Hz

	// Setup ADC 					

	PDCON &= 0xF7;					// turn on ADC

	ADMUX = (channel<<4)|0x08;		// Select Analog Channel

	// VRefOn, VRef Hi, Burnout Detect Off, PGA = 1

	ADCON0 = 0x38;		 								
	// unipolar auto, self calibration, offset, gain

	ADCON1 = 0x71;
	//Note that if decimation is too low, noise will appear...

	decimation = 1920;
	ADCON2 = decimation & 0xFF;			// LSB of decimation	

	ADCON3 = (decimation>>8) & 0x07;	// MSB of decimation	

	
	tempValue = 0;
	adcValue  = 0;
		
	for ( i = 0; i<5; i++ ) 
	{
		// Wait for four conversions for filter to settle after calibration

		while (!(AIE & 0x20));
		// read adc 

		adcValue = ADRESH;
		adcValue <<= 8;
		adcValue |= ADRESM;
		tempValue = ADRESL;		// discard 8 low bits

	}
	
	// Put 3-byte analog value to buffer

	*buffer++ = tempValue & 0xFF; 
	*buffer++ = adcValue & 0xFF;
	*buffer = (adcValue >> 8)  & 0xFF;
	
	return adcValue;
}

int main (void)
{
	UBYTE ndx;
	UBYTE buffer[3];

	unsigned result;

	float voltage;
	
	char msg[32];
	
	// Set the serial port to 19200 Baud

    serinit(CBR_19200);
	
	delay(500);

	/* Initialize I2C bus; this is used to communicate with secondary 
	 * microcontroller on the board to adjust LCD contrast.
	 */
	if( I2C_Repair() )
		{printf("I2C bus is stuck !");	for(;;);}		

	/* Adjust the contrast of LCD module (available levels: 0..15) */
	LCD_Contrast(12);     

	/* Initialize LCD display */	
	LCD_Init();

	/* Loop forever */
	for(;;)
	{
		// Read all analog channels

		printf("\n\r");
		
		for ( ndx =0; ndx < /*MAX_CHANNEL*/1; ndx++)
		{
			/* Perform a conversion on the given channel */
			ReadAdc_MM51F( ndx, buffer );
			
			printf("Ch%d=%02x%02x%02xH ", ndx, buffer[2], buffer[1], buffer[0] );

			/* Clear the screen ( this positions the cursor at top left corner ) */
			LCD_WriteCtrl(LCD_CLEAR_SCREEN);
			
			/************************************************************************
			   
			   Using only the most significant 16 bits of conversion,
			   the formula for proper scaling is:
			
				Voltage in Volts = 2.5 Volts X [16-bit ADC Result] / 65536				
				                      
			*************************************************************************/

			/* 16-bit ADC result is contained in buffer[1] and buffer[2].
			 * Multiply result by 1250 
			 */
			result = *((unsigned*)(&buffer[1]));			

			// Enable this line to display raw 16-bit value for debugging purposes 

			//printf( "\nresult=%u", result );


			voltage = 2.5 * result  65536;
			
			printf( " voltage=%f V", voltage );

			/* Print results to LCD */
			sprintf( msg, "Ch%d=%6.4f V", ndx, voltage );
			LCD_Write(msg);			
		}
	}
}