DanAndDusty 62 Posted July 8, 2011 Share Posted July 8, 2011 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 Mac, mbeals and oPossum 3 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.