This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430G2553 ADC

I am having trouble with some code I am trying to use an an MSP430G2553IN20 chip that is in the MSP430G2 Launchpad.  I am trying to read the value from P1.0 using the ADC and then output that via the UART to the hyperterminal on the Widows 7 desktop.  It is connected to the USB drive currently, and once it is working I plan to use the UART to send it via bluetooth.  I am reading in the voltage in from a voltage sensor or function generator.

//---------------------------------------------------------------
// Console I/O through the on board UART for MSP 430X4XXX
//---------------------------------------------------------------

#include"msp430g2553.h"
#include"stdio.h"

// Global Variables
int adc[10] = {0}; //Sets up an array of 10 integers and zero's the values
int avg_adc = 0;

// Function Prototypes
void Init_UART(void);
unsigned char INCHAR_UART(void);
void OUTA_UART(unsigned char A);
void adc_Setup();
void adc_Sam10();

int main(void){
	// volatile to prevent optimization
	volatile float ThresholdVoltage = 2.8;	//Threshold voltage that is needed to show that there is an input voltage
	volatile int n;  // Index counter
	volatile float VoltageIn;
	volatile float CurrentIn;
	volatile float PowerIn;
	volatile int SampleSize = 10;

	WDTCTL = WDTPW + WDTHOLD;			// Stop watchdog timer
	Init_UART();
	adc_Setup();						// Fucntion call for adc_setup

	for(;;)		// Infinite for loop
	{
		adc_Sam10();	// Function call for adc_samp

				// Add all the sampled data and divide by 10 to find average
		for(n = 0; n < SampleSize; n++)
		{
			avg_adc = avg_adc + adc[n];
		}

		VoltageIn = (avg_adc / SampleSize) * 0.00458984375;

		if (VoltageIn > ThresholdVoltage)
		{
			VoltageIn = VoltageIn - ThresholdVoltage;		// removing the 2.5 extra voltage from the sample
			CurrentIn = VoltageIn / 0.185;			// Gets the current from the voltage using the 0.185 modifier
			PowerIn = CurrentIn * VoltageIn;		// Gets the power for that sample

			OUTA_UART(0x20);		// format the display and the output
			OUTA_UART(0x3D);
			OUTA_UART(0x20);
			OUTA_UART(PowerIn);			// sends the average power for that second to the UART (bluetooth device)
			OUTA_UART(0x0D);
			OUTA_UART(0x0A);
		}
	}
}

// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
  __bic_SR_register_on_exit(CPUOFF);        // Clear CPUOFF bit from 0(SR)
}

// ADC set-up function
void adc_Setup()
{
	 /* Configure ADC Channel */
	 ADC10CTL1 = INCH_5 + ADC10DIV_3 ; // Channel 5, ADC10CLK/4
	 ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON + ADC10IE; //Vcc & Vss as reference
	 ADC10AE0 |= BIT5; //P1.5 ADC option

//	ADC10CTL1 = CONSEQ_2 + INCH_0;						// Repeat single channel, A0
//	ADC10CTL0 = ADC10SHT_2 + MSC + ADC10ON + ADC10IE;	// Sample & Hold Time + ADC10 ON + Interrupt Enable
//	ADC10DTC1 = 0x0A;									// 10 conversions
//	ADC10AE0 |= 0x01;									// P1.0 ADC option select
}

// ADC sample conversion function
void adc_Sam10()
{
    ADC10CTL0 &= ~ENC;				// Disable Conversion
    while (ADC10CTL1 & BUSY);		// Wait if ADC10 busy
    ADC10SA = (int)adc;				// Transfers data to next array (DTC auto increments address)
    ADC10CTL0 |= ENC + ADC10SC;		// Enable Conversion and conversion start
    __bis_SR_register(CPUOFF + GIE);// Low Power Mode 0, ADC10_ISR
}

void OUTA_UART(unsigned char A){
//---------------------------------------------------------------
//***************************************************************
//---------------------------------------------------------------
// IFG2 register (1) = 1 transmit buffer is empty,
// UCA0TXBUF 8 bit transmit buffer
// wait for the transmit buffer to be empty before sending the
// data out
	do{
		}while ((IFG2&0x02) == 0);
	// send the data to the transmit buffer
	UCA0TXBUF = A;
}

unsigned char INCHAR_UART(void){
//---------------------------------------------------------------
//***************************************************************
//---------------------------------------------------------------
// IFG2 register (0) = 1 receive buffer is full,
// UCA0RXBUF 8 bit receive buffer
// wait for the receive buffer is full before getting the data
do{
}while ((IFG2&0x01) == 0);
// go get the char from the receive buffer
return (UCA0RXBUF);
}

void Init_UART(void){
//---------------------------------------------------------------
// Initialization code to set up the uart on the experimenter
// board to 8 data,
// 1 stop, no parity, and 9600 baud, polling operation
//---------------------------------------------------------------
P2SEL  =0x30;		// transmit and receive to port 2 b its 4 and 5
				// Bits p2.4 transmit and p2.5 receive
UCA0CTL0  =0; 	// 8 data, no parity 1 stop, uart, async
				// (7)=1 (parity), (6)=1 Even, (5)= 0 lsb first,
				// (4)= 0 8 data / 1 7 data,
				// (3) 0 1 stop 1 / 2 stop, (2-1) -- UART mode,
				// (0) 0 = async
UCA0CTL1 = 0x41;
				// select ALK 32768 and put in
				// software reset the UART
				// (7-6) 00 UCLK, 01 ACLK (32768 hz), 10 SMCLK,
				// 11 SMCLK
				// (0) = 1 reset
UCA0BR1 = 0; 		// upper byte of divider clock word
UCA0BR0 = 3; 		// clock divide from a clock to bit clock 32768/9600
				// = 3.413
				// UCA0BR1:UCA0BR0 two 8 bit reg to from 16 bit
				// clock divider
				// for the baud rate
UCA0MCTL = 0x06;
				// low frequency mode module 3 modulation pater
				// used for the bit clock
UCA0STAT = 0; 	// do not loop the transmitter back to the
				// receiver for echoing
				// (7) = 1 echo back trans to rec
				// (6) = 1 framing, (5) = 1 overrun, (4) =1 Parity,
				// (3) = 1 break
				// (0) = 2 transmitting or receiving data
UCA0CTL1 = 0x40;
				// take UART out of reset
IE2 = 0;			// turn transmit interrupts off
//---------------------------------------------------------------
//***************************************************************
//---------------------------------------------------------------
				// IFG2 register (0) = 1 receiver buffer is full,
				// UCA0RXIFG
				// IFG2 register (1) = 1 transmit buffer is empty,
				// UCA0RXIFG
				// UCA0RXBUF 8 bit receiver buffer
				// UCA0TXBUF 8 bit transmit buffer
}

  • The code compiles and runs, but when I try and look at the values in the ACD's they are either all "Error: unable to read" or zero.  What am I don't wrong?

  • You say ‘read  the value from P1.0” but the code is written to read from A5 input (which is on P1.5).
    Your code is using floating point math. While this is not critical, you should, if ever possible, use integer math. 1800mV is as good as 1.8V, but can be done with integer arithmetic, which is by some magnitudes faster. And also takes less memory for the variables and much less code.

     (avg_adc/sampleSize) results in a truncated value, because both are integers. So you lose the first decimal.
    Using avg_adc*(0.00458984375/SampleSize) would give a way more precise result. Making SampleSize a constant would allow the compiler to calculate the division at compile time, resulting in smaller and faster code.

    Making local variables volatile is futile. Volatile is only useful (and required) for global vars that are using in both, main code and ISRs.

     

    OUTA_UART takes an unsigned char. But you pass it a float. If you Power is below 1W, this will be rounded down to 0 while being cast to an unsigned char.

    If you want to ‘print’ a float value, you’ll have to convert it into something usable first – either a chain of ASCII digits (using sprintf) that are sent one by one through OUTA_UART, or separate it into byte values by splitting its binary representation. Or whatever.

**Attention** This is a public forum