MSP430 Tutorial




MSP430F5529 USB Project

The goal of the project is to develop a simple USB connected temperature sensor device with MSP430F5529IPNR microcontroller development board.

This page is a Project under development and is being constantly updated. I describe al of my faled and success
Have a comment, question, or need a project to develop? Contact me at:
info@cnktechlabs.com.

Measuring temperature with MSP430 and LMT01 Digital Temperature Sensor

The goal of the project is to develop a USB connected temperature sensor to print temperature to a serial terminal.
Temperature measurements can be done with analog or digital sensors. For this project I have selected TI's LMT01 0.5°C Accurate 2-pin Temperature Sensor with a Pulse Train Interface. LMT01LPG The LMT01 is a high-accuracy, 2-pin temperature sensor with an easy-to-use pulse count interface which makes it an ideal digital replacement for PTC or NTC thermistors both on and off board in automotive, industrial, and consumer markets. LMT01 achieves flat +/- 0.5°C accuracy with very fine resolution (0.0625°C) over a wide temperature range of -20°C to 90°C without system calibration.

From LMT01 datasheet

The LMT01 temperature output is transmitted over a single wire using a train of current pulses that typically change from 34 μA to 125 μA. A simple resistor can then be used to convert the current pulses to a voltage. With a 10 k-Ohm the output voltage levels range from 340 mV to 1.25 V, typically. The temperature can be determined by gating a simple counter on for a specific time interval to count the total number of output pulses. After power is first applied to the device the current level will remain below 34 μA for at most 54ms while the LMT01 is determining the temperature. Once the temperature is determined the pulse train will begin. The individual pulse frequency is typically 88 kHz. The LMT01 will continuously convert and transmit data when the power is applied approximately every 104 ms (max).

The LMT01 will output at minimum 1 pulse and a theoretical maximum 4095 pulses. Each pulse has a weight of 0.0625°C. One pulse corresponds to a temperature less than -50°C while a pulse count of 4096 corresponds to a temperature greater than 200°C. Note that the LMT01 is only guaranteed to operate up to 150°C. Exceeding this temperature by more than 5°C may damage the device. The accuracy of the device degrades as well when 150°C in exceeded.

The output transfer function appears to be linear and can be approximated by the following first order equation:

Section 8.2 "Typical Applications" of the LMT01 datasheet has an example of wiring diagram - LMT01 to the MSP430 microcontroller:

Since LMT01 converts temperature into a pulse train, a microcontoller comparator input is used to count pulses. A pulse is counted every time input voltage to the comparator crosses above the reference voltage.

LMT01 initialization steps

  • After power is first applied to the device the current level will remain below 34 μA for at most 54ms while the LMT01 is determining the temperature.
  • Once the temperature is determined the pulse train will begin.

First select the R and determine the maximum logic low voltage and the minimum logic high voltage while ensuring, that when the LMT01 is converting, the minimum (VP - VN) requirement of 2.15 V is met.

  1. Temperature is Determined: Select R using minimum VP-VN during data transmission (2 V from the table above) and maximum output current of the LMT01 (143.75 μA)

    R = (3.0 V - 2 V) / 143.75 μA = 6.993 k

    The closest 1% resistor is 6.980 k 6.993 k is the maximum resistance so if using 1% tolerance resistor the actual resistor value needs to be 1% less than 6.993 k and 6.98 k is 0.2% less than 6.993 k thus 6.81 k should be used.

    VRdrop = 143.75 μA * 6.81 k = 0.14375 mA * 6.81 k = 0.98V

    With regulated supply of 3.3V :

    (VP - VN)MINtransmission = 3.3 - 0.98 = 2.32V > 2.0MINtransmission

  2. Determinig the Temperature: Check to see if the LMT01's 2.15 V minimum voltage during conversion requirement is met with maximum IOL of 39 μA and maximum R of 6.81 k + 1%: VLMT01 = 3 V - (6.81 k x 1.01) * 39 μA = 2.73 V
  3. Determinig the Temperature: Find the maximum low level voltage range using maximum R of 6.81k and maximum IOL 39 μA:
    VRLmax = (6.81 k x 1.01) * 39 μA = 268 mV
  4. Temperature is Determined: Find the minimum high level voltage using the minimum R of 6.81k and minimum IOH of 112.5 uA: VRHmin = (6.81 k x 0.99) * 112.5 μA = 758 mV

Now select the MSP430 comparator threshold voltage that will enable the LMT01 to communicate to the MSP430 properly.

  1. The MSP430 voltage will be selected by selecting the internal VREF and then choosing the appropriate 1 of n/32 settings for n of 1 to 31. Mid level voltage:
    VMID= (VRLmax - VRHmin )/2 + VRHmin = (758 mV - 268 mV) / 2 + 268 mV= 513 mV n = (VMID / VREF ) * 32 = (0.513 / 2.5) * 32 = 7
  2. In order to prevent oscillation of the comparator output hysteresis needs to implemented. The MSP430 allows this by enabling different n for rising edge and falling edge of the comparator output. Thus for a falling comparator output transition N should be set to 6.
  3. Determine the noise margin caused by variation in comparator threshold level. Even though the comparator threshold level theoretically is set to VMID, the actual level will vary from device to device due to VREF tolerance, resistor divider tolerance, and comparator offset. For proper operation the COMP_B worst case input threshold levels must be within the minimum high and maximum low voltage levels presented across R, VRHmin and VRLmax respectively

      To measure the temperature with LMT01 and MSP430 I will need to count the number of pulses from LMT01 with MSP430 MCU. Counting pulses can be done using comparator B on MSP430. When comparator detects rising edge it will generate an interrupt where pulses will be added.
Setting the MSP430 Threshold and Hysteresis:
      The comparator hysteresis will determine the noise level that the signal can support without causing the comparator to trip falsely thus resulting in an inaccurate pulse count. The comparator hysteresis is set by the precision of the MSP430 and what thresholds it is capable of. For this case as the input signal transitions high the comparator threshold is dropped by 77 mV thus if the noise on the signal as it transitions is kept below this level the comparator will not trip falsely. In addition the MSP430 has a digital filter on the COMP_B output that be used to further filter output transitions that occur too quickly.

MSP430 Comparator

MSP430 Comp_B module supports precision slope analog-to-digital conversions, supply voltage supervision, and monitoring of external analog signals. The comparator compares the analog voltages at the + and - input terminals. If the + terminal is more positive than the - terminal, the comparator output CBOUT is high. The comparator can be switched on or off using control bit CBON. The comparator should be switched off when not in use to reduce current consumption. When the comparator is switched off, CBOUT is always low. The bias current of the comparator is programmable.


Analog Input Switches

The analog input switches connect or disconnect the two comparator input terminals to associated port pins using the CBIPSELx and CBIMSELx bits.

The voltage reference generator

The voltage reference generator is used to generate VREF, which can be applied to either comparator input terminal. The CBREF1x (VREF1) and CBREF0x (VREF0) bits control the output of the voltage generator. The CBRSEL bit selects the comparator terminal to which VREF is applied. The voltage reference generator can generate a fraction of the device's VCC or of the voltage reference of the integrated precision voltage reference source. Vref1 is used while CBOUT is 1 and Vref0 is used while CBOUT is 0. This allows the generation of a hysteresis without using external components.

A good place to sart is to download one of the code examples from the TI Resource Explorer.

Comparator B example code list

MSP430F552x_compB_01.c COMPB output Toggle in LPM4;
MSP430F552x_compB_02.c COMPB output Toggle from LPM4; input channel CB1;
MSP430F552x_compB_03.c COMPB interrupt capability;
MSP430F552x_compB_04.c COMPB Toggle from LPM4; Ultra low power mode;
MSP430F552x_compB_05.c COMPB Hysteresis, CBOUT Toggle in LPM4; High speed mode
MSP430F552x_compB_06.c COMPB and TIMERAx interaction (TA0.1, TA1.1)

I am going to start with a TI's code example - "MSP430F55xx_compB_03.c" below is the image of the main.c file.

This example demonstrates how to initialize comparator B to determine if input voltage to the comparator B is above or below the selected reference.

On the hardware side, I have connected D2 and D3 LEDs to P2.0 and P2.2 throught 510 Ohm current limiting resistors. LMT01 is connected to Pin77 CB0 input.

Matching schematics to the pin declarations in the main.c. STANDARD BITS are defined in msp430f5529.h header file and do not have to be redefined. I have listed the definitions for reference only.

/************************************************************
* STANDARD BITS
************************************************************/

#define BIT0                   (0x0001)
#define BIT1                   (0x0002)
#define BIT2                   (0x0004)
#define BIT3                   (0x0008)
#define BIT4                   (0x0010)
#define BIT5                   (0x0020)
#define BIT6                   (0x0040)
#define BIT7                   (0x0080)
#define BIT8                   (0x0100)
#define BIT9                   (0x0200)
#define BITA                   (0x0400)
#define BITB                   (0x0800)
#define BITC                   (0x1000)
#define BITD                   (0x2000)
#define BITE                   (0x4000)
#define BITF                   (0x8000)

int main(void)
{
	WDTCTL = WDTPW + WDTHOLD;     	// Stop WDT
	P2DIR |= BIT0;                	// P2.0/LED set in output direction
	P2DIR |= BIT2;			// P2.2/LED set in output direction	
	P7DIR |= BIT4;
	.....
	
}		
	

D2 and D3 LEDs will be used as indicators


Comparator B MSP430F5529

Image from comp B user guide.

Current Comparator Settings

Taking a closer look at the current comparator settings:

CBCTL0 |= CBIPEN + CBIPSEL_0; //(0x0080) + (0x0000) = (0x0080) - 0b0000 0000 1000 0000
bit 15: CBIMEN - 0b = Negative input of the comparator is disconnected from input terminals
bits: 14 - 12 Reserved
bits: 11 - 8 CBIMSEL - 0h = Channel input selected for the V- terminal of the comparator if CBIMEN is set to 1, from the above CBIMEN is set to 0.
CBIPEN - 1b     // Positive input of the comparator is connected to the input terminals
CBCTL0 |= CBIPEN + CBIPSEL_0


CBCTL1 = 0b0000 0001 0000 0000 CBMRVS - 0b   // Comparator output state selects between VREF0 or VREF1.
CBMRVL - 0b   // VREF0 is selected if CBRS = 00, 01, or 10.
CBRS - 00b   // This bit defines if the comparator output selects between VREF0 or VREF1 if CBRS = 00, 01, or 10
CBON - 0b   // This bit turns the comparator on. When the comparator is turned off the Comp_B consumes no power. At this point 0b = OFF.
CBPWRMD - 01b   // Normal mode operation (optional)
CBFDLY - 00b   // Filter delay - typical filter delay of 450 ns.
CBEX - 0b0   // Exchange. This bit permutes the comparator 0 inputs and inverts the comparator 0 output. Since this bit is set to 0 the inputs and the output of the comparator are in default configuration.
CBSHORT - 0b   // Inputs are not shorted.
CBIES - 0b   // 0b Rising edge for CBIFG, falling edge for CBIIFG
CBF - 0b   // Comp_B output is not filtered.
CBOUTPOL - 0b   // Output polarity is Noninverted.
CBOUT   // Output value. This bit reflects the value of the Comp_B output.
CBCTL1 |= CBPWRMD_1; // normal power mode (0x0100)
CBCTL2 = 0b 0000 0000 0010 0000
CBREFACC - 0b   // Reference accuracy. A reference voltage is requested only if CBREFL > 0. Current - Static mode
CBREFL - 00b   // Reference voltage is disabled. No reference voltage is requested. (01b = 1.5 V, 10b = 2.0 V, 11b = 2.5 V)
CBREF1 - Reference resistor tap 1.   // This register defines the tap of the resistor string while CBOUT = 1.
CBRS - 00b   // No current is drawn by the reference curcuitry. Reference source. This bit define if the reference voltage is derived from VCC or from the precise shared reference
CBRSEL - 1b   // Since CBEX = 0: V(REF) is applied to the – terminal.
CBREF0 - 0b  // Reference resistor tap 0. This register defines the tap of the resistor string while CBOUT = 0
CBCTL2 |= CBRSEL; // VREF is applied to -terminal (0x0020)

CBCTL2 |= CBRS_2 + CBREFL_2 + CBREF0_7;// (0x0080) + (0x4000) + (0x0007)

The image below shows CBRS = 00, CBMRVS = 0, and since CBMRVL = 0 VREF0 is selected for the negative input of the comparator B. Since CBIPEN is set to 1 and CBIMSEL is set to 0h, the positive input of the comparator is connected to the CB0 pin. As can be seen from above - reference voltage is disabled.

VTHRESH = VREF * 7 /32 = 2.5V * 7 /32 = 0.5468 V



I have connected D2 and D3 LEDs to P2.0 and P2.2 throught 510 Ohm current limiting resistors. LMT01 is connected to Pin77 CB0 input.

To verify that LMT01 works as it suppose to I have measured 100 ms 0.5V pulses with my Multimeter+ across resistor R 6.81k at the input CB0 pin 77 of MSP430F5529IPNR

The spectrum below shows pulses of approximate frequency of 85.22 kHz

The -3dB point of the oscilloscope is approximately 55kHz so pule amplitude shown is smaller. The real amplitude is about 750mV.

Well, the comparator does not want to trigger on LMt01 pulses, but it triggers on 60 Hz noise.

LMT01 is connected to CB0 pin 77 as shown in the image below:

Finally Success

I have downloaded and installed MSP430ware.
If the installation folder is left default there is an example comp_b_ex1_2V.c in the C:\ti\msp430\MSPWare_3_30_00_18\driverlib\examples\MSP430F5xx_6xx\comp_b folder. After a few modifications to the code I have:

#include "driverlib.h"
volatile unsigned int count = 0;
volatile unsigned int i;
void main(void)
{
    //Stop WDT
    WDT_A_hold(WDT_A_BASE);

    P2DIR |= BIT0;                // P2.0/LED output direction
    P2DIR |= BIT2;
    P7DIR |= BIT4;

    //Select CBOUT function on P1.6/CBOUT and set P1.6 to output direction
    GPIO_setAsPeripheralModuleFunctionOutputPin(
        GPIO_PORT_P1,
        GPIO_PIN6
        );

    //Initialize the Comparator B module
    /* Base Address of Comparator B,
     * Pin CB0 to Positive(+) Terminal,
     * Reference Voltage to Negative(-) Terminal,
     * Normal Power Mode,
     * Output Filter On with minimal delay,
     * Non-Inverted Output Polarity
     */
    Comp_B_initParam param = {0};
    param.positiveTerminalInput = COMP_B_INPUT0;
    param.negativeTerminalInput = COMP_B_VREF;
    param.powerModeSelect = COMP_B_POWERMODE_NORMALMODE;
    param.outputFilterEnableAndDelayLevel = COMP_B_FILTEROUTPUT_DLYLVL1;
    param.invertedOutputPolarity = COMP_B_NORMALOUTPUTPOLARITY;
    Comp_B_init(COMP_B_BASE, &param);

    //Set the reference voltage that is being supplied to the (-) terminal
    /* Base Address of Comparator B,
     * Reference Voltage of 2.0 V,
     * Lower Limit of 2.0*(8/32) = 0.5V,
     * Upper Limit of 2.0*(8/32) = 0.5V,
     * Static Mode Accuracy
     */
    Comp_B_configureReferenceVoltageParam refVoltageParam = {0};
    refVoltageParam.supplyVoltageReferenceBase = COMP_B_VREFBASE2_0V;
    refVoltageParam.lowerLimitSupplyVoltageFractionOf32 = 8;
    refVoltageParam.upperLimitSupplyVoltageFractionOf32 = 8;
    refVoltageParam.referenceAccuracy = COMP_B_ACCURACY_STATIC;
    Comp_B_configureReferenceVoltage(COMP_B_BASE, &refVoltageParam);

    CBINT &= ~(CBIFG + CBIIFG);   // Clear any errant interrupts
    CBINT  |= CBIE;               // Enable CompB Interrupt on rising edge of CBIFG (CBIES=0)
    //Allow power to Comparator module
    Comp_B_enable(COMP_B_BASE);

    //delay for the reference to settle
    __delay_cycles(75);

    //Enter LPM4
    //__bis_SR_register(LPM4_bits);

    //For debug
    //__no_operation();

    for (count = 0; count< 10; count++){
    	P2OUT ^= BIT2;
    	for(i=10000;i>0;i--);
    }

    while(1){
    	/*
    	* The main difference between the two constructions is that __bis_SR_register()
    	* allows you to set more than just the GIE bit, while __enable_interrupt() only sets GIE bit.
    	*/
    	//while(1){
    	P2OUT = 0;
    	__bis_SR_register(LPM4_bits + GIE);       // Enter LPM4 with inetrrupts enabled
    	__no_operation();                         // For debug

    	//__bis_SR_register(CPUOFF);
    	//__delay_cycles(75);           // delay for the reference to settle

    }
}


// Comp_B ISR - LED Toggle
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=COMP_B_VECTOR
__interrupt void Comp_B_ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(COMP_B_VECTOR))) Comp_B_ISR (void)
#else
#error Compiler not supported!
#endif
{
  //CBCTL1 ^= CBIES;              // Toggles interrupt edge
  CBINT &= ~CBIFG;              // Clear Interrupt flag
  P2OUT ^= BIT0;                // Toggle P2.0
  if (count < 200)
	  count++;
  else{
	  P2OUT ^= BIT2;
	  count = 0;
  }
 // __bic_SR_register_on_exit
  __bis_SR_register_on_exit(LPM4_bits + GIE);
  //__bic_SR_register_on_exit(CPUOFF);
}

Success:

What I am trying to do is to count pulses and display the result on the screen. The following code is a combination of C0_SimpleSend.c and my code that I have posted above.

#include <string.h>
#include "driverlib.h"

#include "USB_config/descriptors.h"
#include "USB_API/USB_Common/device.h"
#include "USB_API/USB_Common/usb.h"                     //USB-specific functions
#include "USB_API/USB_CDC_API/UsbCdc.h"
#include "USB_app/usbConstructs.h"


/*
 * NOTE: Modify hal.h to select a specific evaluation board and customize for
 * your own board.
 */
#include "hal.h"

// Function declarations
void convertTimeBinToASCII(uint8_t* str);
void convertDateBinToASCII(uint8_t* str);

void convertCountBinToASCII(uint8_t* str);
void initRTC(void);

// Application globals
volatile Calendar newTime;
volatile uint8_t hour = 4, min = 30, sec = 00;  // Real-time clock (RTC) values.  4:30:00
volatile uint8_t day, month;
volatile uint8_t Rx_buf[10];

typedef volatile union yeartype{
	uint16_t currentyear;

	struct {
		uint8_t LSB;
		uint8_t MSB;
	};
} yeartype;


yeartype year;

volatile uint8_t bSendTimeToHost = FALSE;	// RTC--> main():  "send the time over USB"
uint8_t timeStr[10];	// Stores the time as an ASCII string
uint8_t dateStr[12];
uint8_t cntrStr[12];	// convertCountBinToASCII(cntrStr);

// Global flags set by events
volatile uint8_t bCDCDataReceived_event = FALSE;  // Flag set by event handler to
                                               // indicate data has been
                                               // received into USB buffer

#define BUFFER_SIZE 256
char dataBuffer[BUFFER_SIZE] = "";

/*
 * ======== main ========
 */
volatile uint32_t PulseCount = 0;
volatile uint8_t SecCount = 0;
volatile unsigned int i;
void main(void)
{
	Calendar currentTime;

	WDT_A_hold(WDT_A_BASE); //Stop watchdog timer

	//Initialize GPIO
    
	//Select CBOUT function on P1.6/CBOUT and set P1.6 to output direction
	GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN6);
	//Set P2.0 to output direction
	GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0);
	P2DIR |= BIT0;		// P2.0 set as output
	P2DIR |= BIT1;		// P2.1 set as output
	P2DIR |= BIT2;		// P2.2 set as output
	P4DIR |= BIT7;		// P4.7 set as output Onboard GREEN LED
	P1DIR |= BIT0;		// P1.0 set as output Onboard RED LED
	//**************************************************************************************
	
	//Real Time Clock: Initialize Calendar Mode of RTC
	// Select XT1
	GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN4 + GPIO_PIN5);

	//Initialize LFXT1
	UCS_turnOnLFXT1(UCS_XT1_DRIVE_3, UCS_XCAP_3);


	//Setup Current Date and Time for Calendar
	currentTime.Seconds = 0x00;
	currentTime.Minutes = 18;
	currentTime.Hours = 10;
	currentTime.DayOfWeek = 0x03;
	currentTime.DayOfMonth = 24;
	currentTime.Month = 10;
	currentTime.Year = 2016;

  /*
   * Base Address of the RTC_A_A
   * Pass in current time, intialized above
   * Use BCD as Calendar Register Format
   */
   //RTC_A_initCalendar(RTC_A_BASE, &currentTime, RTC_A_FORMAT_BCD);
   RTC_A_initCalendar(RTC_A_BASE, &currentTime, RTC_A_FORMAT_BINARY);

   //Setup Calendar Alarm for 5:00pm on the 5th day of the week.
   //Note: Does not specify day of the week.
   RTC_A_configureCalendarAlarmParam param = {0};
   param.minutesAlarm = 0x00;
   param.hoursAlarm = 0x17;
   param.dayOfWeekAlarm = RTC_A_ALARMCONDITION_OFF;
   param.dayOfMonthAlarm = 0x05;
   RTC_A_configureCalendarAlarm(RTC_A_BASE, &param);

   //Specify an interrupt to assert every minute
   RTC_A_setCalendarEvent(RTC_A_BASE, RTC_A_CALENDAREVENT_MINUTECHANGE);

   //Enable interrupt for RTC Ready Status, which asserts when the RTC
   //Calendar registers are ready to read.
   //Also, enable interrupts for the Calendar alarm and Calendar event.
   RTC_A_clearInterrupt(RTC_A_BASE, RTCRDYIFG + RTCTEVIFG + RTCAIFG);
   RTC_A_enableInterrupt(RTC_A_BASE, RTCRDYIE + RTCTEVIE + RTCAIE);

   //Start RTC Clock
   RTC_A_startClock(RTC_A_BASE);

   //Initialize the Comparator B module
   /* Base Address of Comparator B,
    * Pin CB0 to Positive(+) Terminal,
    * Reference Voltage to Negative(-) Terminal,
    * Normal Power Mode,
    * Output Filter On with minimal delay,
    * Non-Inverted Output Polarity
    */

//*************************************************************************************

//Set comparator B

   //Select CBOUT function on P1.6/CBOUT and set P1.6 to output direction
   //CBOUT will be "high" or "low" depending on the state of the comparator and CBEX setting
   GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN6);


    Comp_B_initParam param1 = {0};
    param1.positiveTerminalInput = COMP_B_INPUT0;
    param1.negativeTerminalInput = COMP_B_VREF;
    param1.powerModeSelect = COMP_B_POWERMODE_NORMALMODE;
    param1.outputFilterEnableAndDelayLevel = COMP_B_FILTEROUTPUT_DLYLVL1;
    param1.invertedOutputPolarity = COMP_B_NORMALOUTPUTPOLARITY;
    Comp_B_init(COMP_B_BASE, &param1);

    //Set the reference voltage that is being supplied to the (-) terminal
    /* Base Address of Comparator B,
     * Reference Voltage of 2.0 V,
     * Lower Limit of 2.0*(8/32) = 0.5V,
     * Upper Limit of 2.0*(8/32) = 0.5V,
     * Static Mode Accuracy
     */
     Comp_B_configureReferenceVoltageParam refVoltageParam = {0};
     refVoltageParam.supplyVoltageReferenceBase = COMP_B_VREFBASE2_0V;
     refVoltageParam.lowerLimitSupplyVoltageFractionOf32 = 8;
     refVoltageParam.upperLimitSupplyVoltageFractionOf32 = 8;
     refVoltageParam.referenceAccuracy = COMP_B_ACCURACY_STATIC;
     Comp_B_configureReferenceVoltage(COMP_B_BASE, &refVoltageParam);

     CBINT &= ~(CBIFG + CBIIFG);   // Clear any errant interrupts
     CBINT  |= CBIE;               // Enable CompB Interrupt on rising edge of CBIFG (CBIES=0)
    
     //delay for the reference to settle
     __delay_cycles(75);

//*******************************************************************************************************

//USB initialize
    // Minimum Vcore setting required for the USB API is PMM_CORE_LEVEL_2
    PMM_setVCore(PMM_CORE_LEVEL_2);
    USBHAL_initPorts();           // Config GPIOS for low-power (output low)
    USBHAL_initClocks(8000000);   // Config clocks. MCLK=SMCLK=FLL=8MHz; ACLK=REFO=32kHz
    USB_setup(TRUE,TRUE);  // Init USB & events; if a host is present, connect

    initRTC();             // Start the real-time clock (counter). Used to upload current time from RTClock

    //__bis_SR_register(LPM0_bits + GIE + LPM4_bits);
    //Allow power to Comparator module
    Comp_B_enable(COMP_B_BASE);
    __no_operation();
    __no_operation();
    //Comp_B_disable(COMP_B_BASE);
    //__no_operation();

    //delay for the reference to settle
    __delay_cycles(75);

    __enable_interrupt();  // Enable interrupts globally

    GPIO_setOutputHighOnPin(GPIO_PORT_P4,GPIO_PIN7); // Turn ON green LED P4.7

    while (1)
    {

    	uint8_t ReceiveError = 0, SendError = 0;
    	uint16_t count;

    	// Check the USB state and directly main loop accordingly
    	switch (USB_getConnectionState()) // Returns the state of the USB connection
    	{
    		// This case is executed while your device is enumerated on the USB host
    	    case ST_ENUM_ACTIVE:
    	    	GPIO_setOutputHighOnPin(GPIO_PORT_P1,GPIO_PIN0); // Turn ON red LED P1.0
    	    	// Sleep if there are no bytes to process.
    	    	__disable_interrupt();

    	    	if (!USBCDC_getBytesInUSBBuffer(CDC0_INTFNUM)) { // Returns how many bytes are in the buffer are received and ready to be read.
    	    		// Enter LPM0 until awakened by an event handler
    	    		__bis_SR_register(LPM0_bits + GIE);
    	    	}

    	    	__enable_interrupt();

    	    	// Exit LPM because of a data-receive event, and fetch the received data   !!!!!
    	    	if (bCDCDataReceived_event){

    	    		// Clear flag early -- just in case execution breaks
    	    		// below because of an error
    	    		bCDCDataReceived_event = FALSE;

    	    		count = USBCDC_receiveDataInBuffer((uint8_t*)dataBuffer,
    	    				BUFFER_SIZE,
							CDC0_INTFNUM);

    	    		GPIO_setOutputLowOnPin(GPIO_PORT_P4,GPIO_PIN7); // Turn OFF green LED P4.7

    	    		// Count has the number of bytes received into dataBuffer
    	    		// Echo back to the host.
    	    		if (USBCDC_sendDataInBackground((uint8_t*)dataBuffer,
    	    				count, CDC0_INTFNUM, 1)){
    	    				// Exit if something went wrong.
    	    				SendError = 0x01;
    	    				break;
    	    		}

    	         }

    	    	// If USB is present, sent the time to the host.  Flag is set every sec
    	    	if (bSendTimeToHost)
    	    	{
    	    		bSendTimeToHost = FALSE;    	    	    
    	    		convertTimeBinToASCII(timeStr);			//uint8_t timeStr[9];
    	    	    if (USBCDC_sendDataInBackground(timeStr, 10, CDC0_INTFNUM, 1000))
    	    	    {
    	    	    	_NOP();  	// If it fails, it'll end up here.  Could happen if
    	    	    	    		// the cable was detached after the connectionState()
    	    	    }           	// check, or if somehow the retries failed

    	    	    convertDateBinToASCII(dateStr);
    	    	    //if (USBCDC_sendDataInBackground(dateStr, 9, CDC0_INTFNUM, 1000))
    	    	    if (USBCDC_sendDataInBackground(dateStr, 12, CDC0_INTFNUM, 1000))
    	    	    {
    	    	    	_NOP();  	// If it fails, it'll end up here.  Could happen if
    	    	    	    		// the cable was detached after the connectionState()
    	    	    }
    	    	    if (SecCount == 9){
    	    	    	convertCountBinToASCII(cntrStr);
    	    	    	if (USBCDC_sendDataInBackground(cntrStr, 12, CDC0_INTFNUM, 1000))
    	    	    	{
    	    	    		_NOP();  // If it fails, it'll end up here.  Could happen if
    	    	    	    		            	             // the cable was detached after the connectionState()
    	    	    	}
    	    	    	PulseCount = 0;
    	    	    	SecCount = 0;
    	    	    }

    	    	}
    	       break;

    	       // These cases are executed while your device is disconnected from
    	       // the host (meaning, not enumerated); enumerated but suspended
    	       // by the host, or connected to a powered hub without a USB host
    	       // present.
    	       case ST_PHYS_DISCONNECTED:
    	       case ST_ENUM_SUSPENDED:
    	       case ST_PHYS_CONNECTED_NOENUM_SUSP:
    	    	   __bis_SR_register(LPM3_bits + GIE);
    	           _NOP();
    	       break;

    	            // The default is executed for the momentary state
    	            // ST_ENUM_IN_PROGRESS.  Usually, this state only last a few
    	            // seconds.  Be sure not to enter LPM3 in this state; USB
    	            // communication is taking place here, and therefore the mode must
    	            // be LPM0 or active-CPU.
    	            case ST_ENUM_IN_PROGRESS:
    	            default:;
    	        }

    	        if (ReceiveError || SendError){
    	            // TO DO: User can place code here to handle error
    	        }

    		// Enter LPM0, which keeps the DCO/FLL active but shuts off the
    		// CPU.  For USB, you can't go below LPM0!
    		__bis_SR_register(LPM0_bits + GIE + LPM4_bits);

    }  //while(1)
}  //main()


// Starts a real-time clock on TimerA_0.  Earlier we assigned ACLK to be driven
// by the REFO, at 32768Hz.  So below we set the timer to count up to 32768 and
// roll over; and generate an interrupt when it rolls over.
void initRTC(void)
{
    TA0CCR0 = 32768;
    TA0CTL = TASSEL_1+MC_1+TACLR; // ACLK, count to CCR0 then roll, clear TAR
    TA0CCTL0 = CCIE;              // Gen int at rollover (TIMER0_A0 vector)
}

// Convert a number 'bin' of value 0-99 into its ASCII equivalent.  Assumes
// str is a two-byte array.
void convertTwoDigBinToASCII(uint8_t bin, uint8_t* str)
{
    str[0] = '0';
    if (bin >= 10)
    {
        str[0] = (bin / 10) + 48;
    }
    str[1] = (bin % 10) + 48;
}



/*
 * Convert uint32_t hex value to an uint8_t array. Use this function to convert year to character decimal string.
 */
void hexdec_long( uint32_t count )
{
    uint8_t ones;
    uint8_t tens;
    uint8_t hundreds;
    uint8_t thousands;
    uint8_t thousand10s;
    uint8_t thousand100s;
    uint8_t mill;
    uint8_t mill10s;
    uint8_t mill100s;
    uint8_t bills;

	bills			= 0;
	mill100s		= 0;
	mill10s			= 0;
	mill			= 0;
	thousand100s 	= 0;
	thousand10s 	= 0;
	thousands 		= 0;
	hundreds 		= 0;
	tens  			= 0;
	ones 			= 0;

	while ( count >= 1000000000 )
	{
		count -= 1000000000;		// subtract 1000000000, one billion
		bills++;					// increment billions
	}
	while ( count >= 100000000 )
	{
		count -= 100000000;			// subtract 100000000, 100 million
		mill100s++;					// increment 100th millions
	}
	while ( count >= 10000000 )
	{
		count -= 10000000;			// subtract 10000000
		mill10s++;					// increment 10th millions
	}
	while ( count >= 1000000 )
	{
		count -= 1000000;			// subtract 1000000
		mill++;						// increment 1 millions
	}
	while ( count >= 100000 )
	{
		count -= 100000;			// subtract 100000
		thousand100s++;				// increment 100th thousands
	}
	while ( count >= 10000 )
	{
		count -= 10000;             // subtract 10000
		thousand10s++;				// increment 10th thousands
	}
	while ( count >= 1000 )
	{
		count -= 1000;				// subtract 1000
		thousands++;				// increment thousands
	}
	while ( count >= 100 )
	{
		count -= 100;               // subtract 100
		hundreds++;                 // increment hundreds
	}
	while ( count >= 10 )
	{
		count -= 10;				// subtract 10
		tens++;						// increment tens
	}
		ones = count;				// remaining count equals ones

	Rx_buf[0]= bills + 0x30;    //Conver HEX to character
	Rx_buf[1]= mill100s + 0x30;

    Rx_buf[2]= mill10s + 0x30;
    Rx_buf[3]= mill + 0x30;
    Rx_buf[4]= thousand100s + 0x30;
    Rx_buf[5]= thousand10s + 0x30;

    Rx_buf[6]= thousands + 0x30;
    Rx_buf[7]= hundreds + 0x30;

    Rx_buf[8]= tens   + 0x30;
    Rx_buf[9]= ones + 0x30;
    return;
}


// Convert the binary globals hour/min/sec into a string, of format "hr:mn:sc"
// Assumes str is an nine-byte string.
void convertTimeBinToASCII(uint8_t* str)
{
    uint8_t hourStr[2], minStr[2], secStr[2];

    convertTwoDigBinToASCII(hour, hourStr);
    convertTwoDigBinToASCII(min, minStr);
    convertTwoDigBinToASCII(sec, secStr);

    str[0] = '\n';
    str[1] = hourStr[0];
    str[2] = hourStr[1];
    str[3] = ':';
    str[4] = minStr[0];
    str[5] = minStr[1];
    str[6] = ':';
    str[7] = secStr[0];
    str[8] = secStr[1];
    str[9] = '\n';
}



// Convert MONTH DATE YEAR
void convertDateBinToASCII(uint8_t* str)
{
    uint8_t dayStr[2], monthStr[2];


    convertTwoDigBinToASCII(day, dayStr);
    convertTwoDigBinToASCII(month, monthStr);
    //void hexdec_long( uint32_t count )
    hexdec_long((uint32_t) year.currentyear);

    str[0] 	= '\n';
    str[1] 	= dayStr[0];
    str[2] 	= dayStr[1];
    str[3] 	= ':';
    str[4] 	= monthStr[0];
    str[5] 	= monthStr[1];
    str[6] 	= ':';
    str[7] = Rx_buf[6];
    str[8] = Rx_buf[7];
    str[9] = Rx_buf[8];
    str[10] = Rx_buf[9];
    str[11] = '\n';

}


// Timer0 A0 interrupt service routine.  Generated when TimerA_0 (real-time clock)
// rolls over from 32768 to 0, every second.
#if defined(__TI_COMPILER_VERSION__) || (__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR (void)
#elif defined(__GNUC__) && (__MSP430__)
void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) TIMER0_A0_ISR (void)
#else
#error Compiler not found!
#endif
{
   // if (sec++ == 60)
   // {
   //     sec = 0;
   //     if (min++ == 60)
   //     {
   //         min = 0;
   //         if (hour++ == 24)
   //         {
   //             hour = 0;
   //         }
   //     }
   // }

    //bSendTimeToHost = TRUE;                 // Time to update
    //__bic_SR_register_on_exit(LPM3_bits);   // Exit LPM
}

/*
 * ======== UNMI_ISR ========
 */
#if defined(__TI_COMPILER_VERSION__) || (__IAR_SYSTEMS_ICC__)
#pragma vector = UNMI_VECTOR
__interrupt void UNMI_ISR (void)
#elif defined(__GNUC__) && (__MSP430__)
void __attribute__ ((interrupt(UNMI_VECTOR))) UNMI_ISR (void)
#else
#error Compiler not found!
#endif
{
        switch (__even_in_range(SYSUNIV, SYSUNIV_BUSIFG )) {
        case SYSUNIV_NONE:
                __no_operation();
                break;
        case SYSUNIV_NMIIFG:
                __no_operation();
                break;
        case SYSUNIV_OFIFG:

                UCS_clearFaultFlag(UCS_XT2OFFG);
                UCS_clearFaultFlag(UCS_DCOFFG);
                SFR_clearInterrupt(SFR_OSCILLATOR_FAULT_INTERRUPT);
                break;
        case SYSUNIV_ACCVIFG:
                __no_operation();
                break;
        case SYSUNIV_BUSIFG:
                // If the CPU accesses USB memory while the USB module is
                // suspended, a "bus error" can occur.  This generates an NMI.  If
                // USB is automatically disconnecting in your software, set a
                // breakpoint here and see if execution hits it.  See the
                // Programmer's Guide for more information.
                SYSBERRIV = 0;  // Clear bus error flag
                USB_disable();  // Disable
        }
}
// RTC (real time clock) Interrupt interrupt on every second ------------------------------------------------
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=RTC_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(RTC_VECTOR)))
#endif
void RTC_A_ISR(void)
{
	newTime = RTC_A_getCalendarTime(RTC_A_BASE);
    switch(__even_in_range(RTCIV,16))
    {
    case 0: break;      //No interrupts
    case 2:             //RTCRDYIFG
        //Toggle P2.0 every second
        //GPIO_toggleOutputOnPin(GPIO_PORT_P2,GPIO_PIN0);
        sec = newTime.Seconds;
        hour = newTime.Hours;
        min = newTime.Minutes;
        day = newTime.DayOfMonth;
        month = newTime.Month;
        year.currentyear = newTime.Year;
        bSendTimeToHost = TRUE;					// Time to update, enable USB transfer
        __bic_SR_register_on_exit(LPM3_bits);   // Exit LPM
        SecCount++;
        //year.currentyear = currentTime.Year;
        break;
    case 4:             //RTCEVIFG
        //Interrupts every minute
        __no_operation();
        break;
    case 6:             //RTCAIFG
        //Interrupts 5:00pm on 5th day of week
        __no_operation();
        break;
    case 8: break;      //RT0PSIFG
    case 10: break;     //RT1PSIFG
    case 12: break;     //Reserved
    case 14: break;     //Reserved
    case 16: break;     //Reserved
    default: break;
    }
}


// Convert MONTH DATE YEAR
void convertCountBinToASCII(uint8_t* str)
{


	PulseCount = PulseCount /99;
    hexdec_long((uint32_t) PulseCount);

    str[0] 	= '\n';
    str[1] 	= Rx_buf[0];
    str[2] 	= Rx_buf[1];
    str[3] 	= Rx_buf[2];
    str[4] 	= Rx_buf[3];
    str[5] 	= Rx_buf[4];
    str[6] 	= Rx_buf[5];
    str[7] 	= Rx_buf[6];
    str[8] 	= Rx_buf[7];
    str[9] 	= Rx_buf[8];
    str[10] = Rx_buf[9];
    str[11] = '\n';

}



// Comp_B ISR - LED Toggle Interrupt --------------------------------------------
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=COMP_B_VECTOR
__interrupt void Comp_B_ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(COMP_B_VECTOR))) Comp_B_ISR (void)
#else
#error Compiler not supported!
#endif
{
  //CBCTL1 ^= CBIES;              // Toggles interrupt edge
  CBINT &= ~CBIFG;              // Clear Interrupt flag
  GPIO_toggleOutputOnPin(GPIO_PORT_P2,GPIO_PIN0);
  //if (PulseCount < 4095)
	  PulseCount++;

  //else{
	  //P2OUT ^= BIT2;
	  //PulseCount = 0;
  //}
 // __bic_SR_register_on_exit
  //__bis_SR_register_on_exit(LPM4_bits + GIE);
  //bSendTimeToHost = TRUE;                 // Time to update
 //__bic_SR_register_on_exit(LPM3_bits);   // Exit LPM
  //__bic_SR_register_on_exit(CPUOFF);
}


The next step is to send the "count" to the serial terminal on a PC. You will need to generate CDC INF file using the MSP Descriptor Tool.
Save the generated file into the "USB_config" folder of your project.
Open "MSP Descriptor Tool" and click on "Add CDC" (Virtual COM Port).

Click on "Generate" and select "USB_config" folder location of your project.

Click OK to jenerate descriptor files.

Install the Virtual COM port driver refer to Section 2.5.2, Installing a CDC Interface on Windows 7, of the MSP430 USB API Stack "Examples_Guide_MSP430_USB.pdf" provided in the Documentation folder of the MSP430USBDEVPACK. 2.5.2 Installing a CDC Interface on Windows 7
When you build and run a CDC example for the first time, per the instructions in Sec. 2.3, Win7 does not display a dialog box for installing the INF file. Instead, a bubble in the system tray may appear, indicating that drivers were not installed. To install the INF file, launch the Device Manager. (See Appendix A for how to do this.) The USB CDC examples appear in the Device Manager as “MSP430-USB Example”. If a driver isn't properly installed, it appears with a yellow "!" on its icon, colloquially referred to as a "yellow bang".
Right click on that item:

From the resulting contextual menu, select 'Update Driver Software'.

Choose "Browse My Computer for Driver Software":

Choose "Browse My Computer for Driver Software":

Navigate to the \USB_config directory for the CDC example in question. Be sure to choose the one for the right example.

Then, click "OK". Windows 7 should display the following Windows Security message:

Click "Install". The Device Manager should now show the device without the "green bang" icon, with an assigned COM port number.

NOTE: If the Device Manager lists the COM port as anything greater than 9, then verify that the general purpose "terminal" application like HyperTerminal being used will support COM ports greater than 9.

2.5.3 Installing a CDC Interface on Windows 8

Unlike Win7, which allows installation of an unsigned driver (or INF file) if the user grants permission, Win8 will not, under normal conditions. However, in implementing this restriction, Microsoft still needed to provide a means of turning it off, to allow driver development. This is because a driver can’t be signed until after it’s completed. Under normal conditions, attaching a device with a CDC interface, for which no signed INF was pre-installed, results in this dialog box.

The solution Microsoft provides is a relatively hidden means of disabling enforcement of driver signage. The disabling is effective until the next reboot. The device/INF can be installed during that boot session, and then during subsequent boot sessions, Win8 will see the installed driver and not generate the dialog box shown above. To enable this mode, press Win+R to bring up the "Run" window. Type "shutdown.exe /r /o /f /t00" (without the ""). Press "OK".

A reboot will occur, and the advanced startup menu displayed

The solution Microsoft provides is a relatively hidden means of disabling enforcement of driver signage. The disabling is effective until the next reboot. The device/INF can be installed during that boot session, and then during subsequent boot sessions, Win8 will see the installed driver and not generate the dialog box shown above. To enable this mode, press Win+R to bring up the "Run" window. Type "shutdown.exe /r /o /f /t00" (without the ""). Press "OK".

A reboot will occur, and the advanced startup menu displayed

The solution Microsoft provides is a relatively hidden means of disabling enforcement of driver signage. The disabling is effective until the next reboot. The device/INF can be installed during that boot session, and then during subsequent boot sessions, Win8 will see the installed driver and not generate the dialog box shown above. To enable this mode, press Win+R to bring up the "Run" window. Type "shutdown.exe /r /o /f /t00" (without the ""). Press "OK".

A reboot will occur, and the advanced startup menu displayed

Click "Troubleshoot", then "Advanced Options", then "Startup Settings".

Finally, click on "Restart" in the bottom right corner, and wait for the reboot.

When the computer restarts, select the option "Disable driver signature enforcement".

When it finally boots into the operating system you can manually install the unsigned driver. You'll see the following message; just select "Install this driver software anyway".

The disabling lasts for one boot session. In the next re-boot, enforcement of driver signage will resume.

Once drivers are installed program the board and the output is:

The 10 digit number, 000000001119, represents the temperature.




Article From an Online Datasheets:

  1. LMT01 0.5°C Accurate 2-Pin Digital Output Temperature Sensor with Pulse Count Interface
  2. TI Designs - Precision: Verified Design; Comparator with Hysteresis Reference Design; Art Kay, Timothy Claycomb