Jump to content
43oh

ADC10 Speed tests using hardware UART


Recommended Posts

Hi all,

 

Here is a little snippet of code I wrote to test the speed of the ADC10 at a variety of settings, and also to discover just how easy using the hardware UART turned out to be. I used the 2553 as it has a hardware UART.

 

It sets the MCLK to a variety of speeds (I used CCS to read the calibration constants in the flash and coded them into the program). Then counts the number of samples that can be taken in 1 second using all the possible values for the SHT bits.

 

The details are then written out to the UART at 9600 so I can see how speed affects the number of samples per second. To verify that the SHT settings are sufficient I also display the max/min readings taken. I had a potentiometer connected VCC/GND to pin P1.4 (INCH4).. Testing with different resistors between the POT and INCH4 I found that it wasn't until about 10K ohms that the ADC couldn't read the max Voltage at the fastest SHT settings.

 

These are the readings I got

Using Speed 1MHz
 Using ADC10SHT_0 (x4)
   There were 15,031 samples per sec - readings range from [1,020] to [1,023]
   There were 15,030 samples per sec - readings range from [1,018] to [1,023]
   There were 15,031 samples per sec - readings range from [1,020] to [1,023]
   There were 15,031 samples per sec - readings range from [1,020] to [1,023]
   There were 15,031 samples per sec - readings range from [1,020] to [1,023]
 Using ADC10SHT_1 (x8)
   There were 15,031 samples per sec - readings range from [1,020] to [1,023]
   There were 15,031 samples per sec - readings range from [1,018] to [1,023]
   There were 15,031 samples per sec - readings range from [1,020] to [1,023]
   There were 15,031 samples per sec - readings range from [1,020] to [1,023]
   There were 15,031 samples per sec - readings range from [1,020] to [1,023]
 Using ADC10SHT_2 (x16)
   There were 15,030 samples per sec - readings range from [1,018] to [1,023]
   There were 15,030 samples per sec - readings range from [1,019] to [1,023]
   There were 15,030 samples per sec - readings range from [1,018] to [1,023]
   There were 15,031 samples per sec - readings range from [1,018] to [1,023]
   There were 15,030 samples per sec - readings range from [1,018] to [1,023]
 Using ADC10SHT_3 (x64)
   There were 15,030 samples per sec - readings range from [1,017] to [1,023]
   There were 15,030 samples per sec - readings range from [1,017] to [1,023]
   There were 15,030 samples per sec - readings range from [1,017] to [1,023]
   There were 15,030 samples per sec - readings range from [1,017] to [1,023]
   There were 15,030 samples per sec - readings range from [1,017] to [1,023]
Using Speed 8MHz
 Using ADC10SHT_0 (x4)
   There were 120,640 samples per sec - readings range from [1,018] to [1,023]
   There were 120,408 samples per sec - readings range from [1,018] to [1,023]
   There were 120,308 samples per sec - readings range from [1,018] to [1,023]
   There were 120,420 samples per sec - readings range from [1,018] to [1,023]
   There were 119,489 samples per sec - readings range from [1,018] to [1,023]
 Using ADC10SHT_1 (x8)
   There were 122,614 samples per sec - readings range from [1,017] to [1,023]
   There were 122,614 samples per sec - readings range from [1,017] to [1,023]
   There were 122,615 samples per sec - readings range from [1,017] to [1,023]
   There were 122,615 samples per sec - readings range from [1,017] to [1,023]
   There were 122,614 samples per sec - readings range from [1,017] to [1,023]
 Using ADC10SHT_2 (x16)
   There were 113,886 samples per sec - readings range from [1,016] to [1,023]
   There were 113,886 samples per sec - readings range from [1,017] to [1,023]
   There were 113,885 samples per sec - readings range from [1,016] to [1,023]
   There were 113,885 samples per sec - readings range from [1,016] to [1,023]
   There were 113,885 samples per sec - readings range from [1,016] to [1,023]
 Using ADC10SHT_3 (x64)
   There were 50,897 samples per sec - readings range from [1,015] to [1,023]
   There were 50,897 samples per sec - readings range from [1,013] to [1,023]
   There were 50,897 samples per sec - readings range from [1,013] to [1,023]
   There were 50,896 samples per sec - readings range from [1,016] to [1,023]
   There were 50,897 samples per sec - readings range from [1,012] to [1,023]
Using Speed 12MHz
 Using ADC10SHT_0 (x4)
   There were 184,092 samples per sec - readings range from [1,013] to [1,023]
   There were 184,092 samples per sec - readings range from [1,013] to [1,023]
   There were 184,092 samples per sec - readings range from [1,012] to [1,023]
   There were 184,092 samples per sec - readings range from [1,013] to [1,023]
   There were 184,092 samples per sec - readings range from [1,013] to [1,023]
 Using ADC10SHT_1 (x8)
   There were 159,657 samples per sec - readings range from [1,013] to [1,023]
   There were 159,658 samples per sec - readings range from [1,013] to [1,023]
   There were 159,658 samples per sec - readings range from [1,013] to [1,023]
   There were 159,657 samples per sec - readings range from [1,013] to [1,023]
   There were 159,657 samples per sec - readings range from [1,013] to [1,023]
 Using ADC10SHT_2 (x16)
   There were 123,543 samples per sec - readings range from [1,014] to [1,023]
   There were 123,543 samples per sec - readings range from [1,014] to [1,023]
   There were 123,543 samples per sec - readings range from [1,014] to [1,023]
   There were 123,543 samples per sec - readings range from [1,014] to [1,023]
   There were 123,543 samples per sec - readings range from [1,014] to [1,023]
 Using ADC10SHT_3 (x64)
   There were 52,702 samples per sec - readings range from [1,014] to [1,023]
   There were 52,722 samples per sec - readings range from [1,013] to [1,023]
   There were 52,708 samples per sec - readings range from [1,012] to [1,023]
   There were 52,702 samples per sec - readings range from [1,011] to [1,023]
   There were 52,709 samples per sec - readings range from [1,013] to [1,023]
Using Speed 16MHz
 Using ADC10SHT_0 (x4)
   There were 203,974 samples per sec - readings range from [1,016] to [1,023]
   There were 203,979 samples per sec - readings range from [1,016] to [1,023]
   There were 204,158 samples per sec - readings range from [1,016] to [1,023]
   There were 204,059 samples per sec - readings range from [1,016] to [1,023]
   There were 204,135 samples per sec - readings range from [1,016] to [1,023]
 Using ADC10SHT_1 (x8)
   There were 171,828 samples per sec - readings range from [1,007] to [1,023]
   There were 171,828 samples per sec - readings range from [1,006] to [1,023]
   There were 171,828 samples per sec - readings range from [1,007] to [1,023]
   There were 171,828 samples per sec - readings range from [1,006] to [1,023]
   There were 171,828 samples per sec - readings range from [1,006] to [1,023]
 Using ADC10SHT_2 (x16)
   There were 131,106 samples per sec - readings range from [1,013] to [1,023]
   There were 131,185 samples per sec - readings range from [1,013] to [1,023]
   There were 131,061 samples per sec - readings range from [1,013] to [1,023]
   There were 131,128 samples per sec - readings range from [1,013] to [1,023]
   There were 131,135 samples per sec - readings range from [1,012] to [1,023]
 Using ADC10SHT_3 (x64)
   There were 54,328 samples per sec - readings range from [1,014] to [1,023]
   There were 54,336 samples per sec - readings range from [1,009] to [1,023]
   There were 54,326 samples per sec - readings range from [1,014] to [1,023]
   There were 54,324 samples per sec - readings range from [1,010] to [1,023]
   There were 54,332 samples per sec - readings range from [1,015] to [1,023]

 

And here is the code

/* ******************************************************************************************
* *																						*
* *	ADC-SpeedTest	-	This program samples the ADC at high speed using a variety of	*
* *						settings for Sample & Hold Times and CPU clock speed			*
* *																						*
* *						While doing this it keeps track of the highest/lowest readings	*
* *						(to ensure that the SHT values are sufficient to capture		*
* *						the full range.													*
* *																						*
* *						Once readings are taken they are written out using the hardware	*
* *						UART at 9600,8,1,none											*
* *																						*
* ******************************************************************************************	*/
#include 

volatile unsigned long 	samples = 0;			// How many samples have we had?
volatile int 			timer_ticks = 0;		// How many timer ticks have we had?

volatile long		max_reading=0;				// Whats the highest reading we have had?
volatile long		min_reading=1023;			// Whats the lowest reading we have had?
int					cur_sht = 0;				// What SHT are we using now?
int					sht_count = 0;				// How many runs at this SHT have we had?

int					cur_speed = 0;				// What speed are we running at?

const unsigned	SHT_vals[] = {
ADC10SHT_0,ADC10SHT_1,ADC10SHT_2,ADC10SHT_3	// What values do we need for each of the SHTs?
};

const char *SHT_strs[] = {						// Descriptive Strings for the SHTs
"ADC10SHT_0 (x4)",
"ADC10SHT_1 (x8)",
"ADC10SHT_2 (x16)",
"ADC10SHT_3 (x64)"
};

const char *SPEEDS_STR[] = {					// Descriptive strings for the processor speeds
"1MHz","8MHz","12MHz","16MHz"
};

const char SPEEDS_UCABR0[] = {					// Values to use for UCABR0 for each proc speed (9600 baudrate)
104, 0x41, 0xE2, 0x82
};

const char SPEEDS_UCABR1[] = {					// Values to use for each UCABR1
0, 0x03, 0x04, 0x06
};

const int SPEEDS_CCR[] = {						// CCR Values to use for each proc speed (to trigger at 1/1000th sec)
1000-1, 8000-1, 12000-1,16000-1
};

const char SPEEDS_BCS[] = {						// BCS Values to use for each processor speed (Grabbed from the calib section of the flash)
0x86, 0x8D, 0x8E, 0x8F
};
const char SPEEDS_DCO[] = {						// DCO values to use for each processor speed (Grabbed from the calib section of the flash)
0xD6, 0x94, 0x9D, 0x95
};

void serial_puts(const char *);					// Put a string (NULL Terminated) out via the UART
void serial_putch(char);						// put a single char out via the UART 
void serial_putl(long);							// Write a long number as ascii out via the UART
void show_sht(void);							// Write the SHT settings out of the serial port
void show_speed(void);							// Write the CPU Speed settings out of the serial port
void set_speed(void);							// Set the processor speed and associated variables

void main(void) {
WDTCTL = WDTPW + WDTHOLD;					// Hold the WDT

BCSCTL1 = CALBC1_16MHZ;						// Set the CPU to 16MHz
DCOCTL = CALDCO_16MHZ;

ADC10CTL0 &= ~ENC;							// Disable ADC conversion (Can't configure if enabled)

ADC10CTL0 = SREF_0 | ADC10SHT_0 | ADC10ON | ADC10IE;	// GND to Vcc, 4 x ADC10CLK Ticks, ADC on, Enable Interrupt
ADC10CTL1 = INCH_4 | SHS_0 | ADC10DIV_0 | ADC10SSEL_0 | CONSEQ_0;	// ADC Chan 4, ADC10 SC, /1 CLK, ADC10 OSC, Sing Chan/Sing Conv

P1SEL = BIT1 + BIT2;						//  Enable P1.1, P1.2 as Hardware UART
P1SEL2 = BIT1 + BIT2;

UCA0CTL1 |= UCSSEL_2;						// UART clocked from SMCLK
UCA0BR0 = 0x82;								// 16,000,000/9600 = 0x682
UCA0BR1 = 0x06;

UCA0MCTL = UCBRS0;							// No modulation
UCA0CTL1 &= ~UCSWRST;						// reset usci

CCTL0 = CCIE;								// Enable interrupts on Timer
TACTL = TASSEL_2 | ID_0 | MC_1;				// SMCLK, /1, Up to CCR0
CCR0 = 16000 - 1;							// One Thousandth of a second

set_speed();								// Set clock speed, baudrate divisors etc
show_speed();								// Send speed details to UART
show_sht();									// Send SHT details to UART

while(1) {
	min_reading = 1023;						// Clear min/max readings
	max_reading = 0;
	samples = 0;							// And counters
	timer_ticks = 0;
	TACTL |= TACLR;							// Reset the timer
	CCTL0 |= CCIE;							// Enable timer interrupts
	ADC10CTL0 |= ENC | ADC10SC;				// Enable ADC and Start conversion
	_bis_SR_register(CPUOFF | GIE);			// Pause CPU and enable interrupts

	ADC10CTL0 &= ~ENC;						// Turn off the encoder
	CCTL0 &= ~ CCIE;						// Disable interrupts
	while(ADC10CTL1 & ADC10BUSY);			// While til pending ADC done
	ADC10CTL0 &= ~ADC10IFG;					// Ensure pending ifgs are cleared

	serial_puts("    There were ");
	serial_putl(samples);
	serial_puts(" samples per sec - readings range from [");
	serial_putl(min_reading);
	serial_puts("] to [");
	serial_putl(max_reading);
	serial_puts("]\n\r");
	if(++sht_count == 5) {					// Take readings for 5 seconds per Speed/SHT combo
		sht_count = 0;
		cur_sht++;
		if(cur_sht == 4) {					// There are 4 SHT settings per speed
			cur_sht = 0;
			cur_speed++;
			if(cur_speed == 4) {			// And we have 4 speeds
				cur_speed = 0;
			}
			set_speed();					// Set speed details
			show_speed();					// Show the details
		}
		show_sht();							// Show the SHT settings
		ADC10CTL0 = SREF_0 | SHT_vals[cur_sht] | ADC10ON | ADC10IE;		// Setup ADC10
	}			
}
}

/* **********************************************************************************************
* 																								*
* set_speed(void) - 	Sets the DCO/BCS registers so MCLK is desired speed,					*
* 						UART baudrate divisors for 9600											*
* 						CCR0 so ticks are 1/1000 seconds										*
* 						NOTE: Must pause to allow the clocks to settle down						*
*																								*
* **********************************************************************************************	*/

void set_speed(void) {
BCSCTL1 = SPEEDS_BCS[cur_speed];			// Set MCLK to desired speed
DCOCTL = SPEEDS_DCO[cur_speed];

UCA0BR0 = SPEEDS_UCABR0[cur_speed];			// set bitrate divisors depending on speed
UCA0BR1 = SPEEDS_UCABR1[cur_speed];

CCR0 = SPEEDS_CCR[cur_speed];				// And CCR so each tick is 1/1000 seconds

__delay_cycles(20000);						// Wait for clocks etc to settle down
}

/* **********************************************************************************************
* *	show_sht(void)	-	Writes out description of the SHT settings to the UART				*
* **********************************************************************************************	*/

void show_sht(void) {
serial_puts("  Using ");
serial_puts(SHT_strs[cur_sht]);
serial_puts("\n\r");
}

/* **********************************************************************************************
* *	show_speed(void)-	Writes out description of the CPU speed settings to the UART		*
* **********************************************************************************************	*/

void show_speed(void) {
serial_puts("Using Speed ");
serial_puts(SPEEDS_STR[cur_speed]);
serial_puts("\n\r");
}

/* **********************************************************************************************
* *	serial_putl(long val)	-	Writes out a long number as ASCII through the UART			*
* *								For ease of reading the numbers there are ',' chars			*
* *								written out as thou separators								*
* *								Leading 0s are skipped										*
* *																							*
* *	NOTE:-	At the moment all numbers are assumed to be +ve (can't have a -ve number of		*
* *			readings so not needed in this project											*
* *																							*
* **********************************************************************************************	*/

void serial_putl(long val) {
long	digit;
char	ch;
char	had_digit = 0;
digit = 1000000;							// Allow for upto 1M Samples per sec
while(digit >0 ) {
	ch = val / digit;
	if(had_digit && (digit == 100000 || digit == 100)) {
		serial_putch(',');					// If a digit has been written then put a thou sep
	}
	if(ch >0 || had_digit || digit == 1) {	// Skip 0s if not had a char left and not on units
		serial_putch('0' + ch);
		had_digit = 1;
	}
	val -= digit * ch;
	digit /= 10;
}
}

/* **********************************************************************************************
* *																							*
* *	serial_puts(const char *ptr)	-	Writes out a NULL terminated string through the UART*
* *																							*
* **********************************************************************************************	*/

void serial_puts(const char *ptr) {
while(*ptr) {								// Go until we are at the NULL
	serial_putch(*(ptr++));					// put out the single char
}
}

/* **********************************************************************************************
* *																							*
* *	serial_putch(char c)	-	Writes out a single ASCII char through the UART				*
* *																							*
* **********************************************************************************************	*/

void serial_putch(char c) {
while ( !(IFG2 & UCA0TXIFG) )				// Wait if there is a transmission ongoing
	;
UCA0TXBUF = c;								// Put the char into the UART TX buffer
}

/* **********************************************************************************************
* *																							*
* *	ADC_ISR(void)	-	ISR for when the ADC has completed a conversion						*
* *						It keeps track of the min and max readings							*
* *						And keeps track of the number of readings taken						*
* *																							*
* **********************************************************************************************	*/

#pragma vector=ADC10_VECTOR
__interrupt void ADC_ISR(void) {
ADC10CTL0 |= ADC10SC;						// Start Conversion as soon as possible here
if(ADC10MEM > max_reading) {
	max_reading = ADC10MEM;					// Keep track of highest reading
}
if(ADC10MEM < min_reading) {
	min_reading = ADC10MEM;					// And the minimum
}
samples++;									// And bump the number of reaings
}

/* **********************************************************************************************
* *																							*
* *	TIMERA_ISR(void)	-	ISR for the timer CCR0											*
* *							simple routine.. keeps track of the number of ticks				*
* *							All ticks should be 1/1000 sec									*
* *							When 1000 ticks have happened the CPU is re-enabled so the 		*
* *							details can be sent out of the UART								*
* *																							*
* **********************************************************************************************	*/

#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMERA_ISR(void) {
timer_ticks++;								// Bump the count
if(timer_ticks == 1000) {
	__bic_SR_register_on_exit(CPUOFF + GIE);	// After 1000 ticks re-enable the processor
}
}

 

I hope someone finds this snippet useful

 

Dan

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...