27 December 2010

Tutorial 12: Making Comparisons

As we've seen, microcontrollers have great usefulness in digital electronics. In the real world, and for scientific applications, however, digital is not always adequate. In this tutorial, we begin working with analog signals using a 1 bit analog to digital converter: the comparator.

Some MSP430 devices have a built-in comparator (called the Comparator_A+ module in the technical documentation, I'll refer to it as CA+ here), including the MSP430G2211 that comes with the LaunchPad kit. (See TI's website for other LaunchPad-compatible devices that include the CA+ module.) Up to this point, all of the tutorials could be used on both the G2211 and the G2231 chips in the LaunchPad kit by changing the #include header appropriately. For this tutorial, you will need to use the G2211.

Overview of the Comparator_A+ Module
Simplified diagram of the Comparator_A+ module.  Taken from the book
MSP430 Microcontroller Basics; I highly recommend getting a copy of this book!

The CA+ module is very flexible, allowing multiple GIO pins to be connected to its inputs and including a variety of useful internal voltage references. As you may recall, a comparator has two inputs, called inverting and non-inverting (often labeled V+ and V- respectively). The V+ input can be connected to three different pins for external signals, or any of three different internal reference signals. The V- input can be connected to seven different pins (two overlap with the V+ inputs) and any of the internal references. CA+ has an output that can be read in software, trigger the CA+ interrupt, and trigger a timer interrupt. All of these options give the CA+ module its flexibility and usefulness to us in developing instrumentation.

Take a look at the datasheet for the G2211, and find the page that shows the pinout diagram for the chip. The pins that can be connected to the CA+ inputs are labeled as CAx. Note that CA0-2 can be connected to V+, while CA1-7 can be connected to V-. Note also that in addition to providing the CA7 input, P1.7 can be configured to provide the output value CAOUT externally.

Configuring the Comparator_A+ module
The CA+ module has three different registers for its configuration: CACTL1, CACTL2, and CAPD. These registers are described on pages 19-10 to 19-13 of the x2xx Family Guide. We'll look at the basic pieces here.


  • The CAREFx and CARSEL bits (4-5 and 6) control the internal references for the comparator. Bits 4 and 5 select the reference value, while bit 6 selects which input is connected to the reference. There are three references provided in the module. Two of them are a fractional value of the voltage powering the MSP430: 1/2 Vcc and 1/4 Vcc. If you are powered from the USB (3.6 V), these references are 1.8 V and 0.9 V respectively. (These are accurate to about 1%.) A third reference is provided by the forward voltage of a transistor. This voltage is typically 0.55 V, but is less accurate and susceptible to temperature changes.
  • The CAIFG, CAIE, and CAIES bits (0-2) control the interrupt for the comparator. Bit 0 is the interrupt flag, which clears automatically when the interrupt is serviced. Bit 1 turns on the interrupt, and bit 2 selects whether an interrupt is triggered on a rising edge (low to high transition) or a falling edge (high to low transition).
  • The CAON bit (3) turns the comparator on when set, and off when cleared.
  • The CAEX bit (7) is used to exchange the two inputs; ie. the pins/references connected to V+ and V- are swapped. (In addition, the output is inverted to compensate for the change.) This ability is useful in examining values close together, but for basic functionality is not necessary.
  • The P2CAx bits (2-6) are used to select the pins connected to the comparator inputs. V+ is selected with P2CA0 and P2CA4. V- is selected with P2CA1-P2CA3. The x2xx Family Guide provides a table on page 19-12 that explains which bit configuration selects the various pins.
  • The CAF bit (1) puts the output through an RC filter to smooth out any rapid oscillations that might occur if the comparator inputs are very close together. It's not always necessary, but is a good idea to enable if you're using slowly-varying signals.
  • The CAOUT bit (0) is the output value only; you cannot write to this bit, but reading it will give you the current value of the comparator output.
  • The CASHORT bit (7) shorts the two comparator inputs together. While this might sound like an odd thing to do, it is useful under certain circumstances. Basic use of CA+ will not use this function.
  • The CAPD register is analogous to the Port registers; each bit corresponds to the input pins CA0-CA7. The purpose of this register is to disconnect the digital circuitry for the GIO ports from the pins that are being used with analog signals. If an analog signal close to the transition voltage for the digital circuit is applied to the pin, the digital portion could oscillate between high and low fairly rapidly. This effect can cause degradation of the circuitry in the chip, and so it's best to disconnect it completely when analog signals are used. In fact, when a pin is connected to the comparator, it is automatically disconnected. The purpose of this register is to manually control the disconnect. Sometimes you may want to use the comparator on multiple signals; only one pin can be connected to the comparator at a time, but you can switch the input connection in the software. While the CAPD method of disconnecting the digital circuit is redundant when only one pin is used, enabling the CAPD bit for a pin connected to an analog signal prevents it from being reconnected to the digital circuit when the software causes the comparator to switch input pins.

Programming Example
To demonstrate the CA+ module, look at a basic comparison program in bcompG221.c. The idea in this program is to measure an analog voltage, and flash an LED if the voltage is above a particular reference, in this case 1/2 Vcc (1.8 V when running off the USB power). To do this, the program uses the Timer_A module to flash the LED, while the Comparator_A+ uses an interrupt to turn the flashing on and off.

The portion of the code that configures the CA+ module is as follows:

CACTL1 = CAREF1 + CARSEL + CAIE; // 0.5 Vcc ref on - pin, enable
                                 // interrupts on rising edge.
CACTL2 = P2CA4 + CAF;      // Input CA1 on + pin, filter output.
CAPD = AIN1; // disable digital I/O on P1.1 (technically
// this step is redundant)

The values used here can be found in the header file for the G2211. Setting CAREF1 alone selects 1/2 Vcc as the reference voltage and setting CARSEL connects the reference to the V- input. Setting P2CA4 alone selects CA1 (same pin as P1.1 for the G2211) as the V+ input. AIN1 was defined to be BIT1, so we permanently disable the digital circuit on P1.1 for this program. This step wasn't essential, since we don't change the inputs on the comparator in this program.

After all the peripherals are configured, the comparator is turned on with CACTL1 |= CAON (the |= operator is used to prevent changing any of the other configurations we put in at first) and the chip enters LPM0.

TimerA periodically triggers an interrupt and toggles the P1.0 output with the value stored in flash. When CAOUT is 0, flash is 0 and so the LED never turns on. When CAOUT is 1, however, flash is set to LED1 (defined to be BIT0) and the LED toggles on and off.

Now let's look at the Interrupt Service Routine for CA+:
#pragma vector = COMPARATORA_VECTOR
__interrupt void COMPA_ISR(void) {
if ((CACTL2 & CAOUT)==0x01) {
CACTL1 |= CAIES;    // value high, so watch for
                    // falling edge
flash = LED1;       // let LED flash
else {
CACTL1 &= ~CAIES;   // value low, so watch for
                    // rising edge
flash = 0;          // turn LED off
P1OUT = 0;

None of the examples that TI provides on their website demonstrate how to use the Comparator_A+ interrupt. To find the proper syntax, I located the vector name in the msp430g221.h header file. (Remember, the vector name must be what the compiler expects (in this case, COMPARATORA_VECTOR). The header file is the safest place to locate the proper name.) The interrupt routine name, of course, can be named anything. Something descriptive is always helpful, though. For this program, I chose COMPA_ISR(). The service routine first examines the value of CAOUT. If it is 1, then the voltage on V+ is higher than the reference on V-. The next interrupt should be when the value drops below the reference again, so it sets the edge select to a falling edge. It then sets flash to a non-zero value so the LED will blink. If CAOUT is 0, then V+ is lower than the reference. The edge select is set to a rising edge, flash is set to zero so the LED won't blink, and the P1OUT is cleared to ensure the LED is off.

To test the program, you can connect a potentiometer (anything above 1 kΩ should work) between Vcc and ground, and connect the wiper to the P1.1 pin on the LaunchPad. Adjust the potentiometer to see the LED start blinking (indicating the voltage on the pin is above 1.8 V) and back again to see it turn off (indicating the voltage is below 1.8 V). If you don't have a potentiometer, you can try two resistors of different values. Connect one resistor between Vcc and P1.1, and the other between P1.1 and ground. If the smaller resistor is between Vcc and P1.1, the voltage should be more than 1/2 Vcc, and the LED blinks. If the larger is in that place, the voltage is less than 1/2 Vcc, and the LED turns off.  (Caution: If you use two resistors to try this, be wary of removing the resistors while the LaunchPad is powered.  You might not do any damage, but it's safer to power off a circuit before pulling pieces out.)

Reader Exercise: Change the program so that the LED doesn't blink, but is set on/off constantly for high/low values of CAOUT. Then use TimerA to periodically change the reference voltage between 1/2 Vcc and 1/4 Vcc. When comparing to 1/2 Vcc, it should turn the red LED on P1.0 on if the analog signal is above the reference. When comparing to 1/4 Vcc, it should turn the green LED on P1.6 on if the signal is above the reference. Turning the knob on the potentiometer, you should see the green LED light when the signal is above 1/4 Vcc, then the red LED light when above 1/2 Vcc.


Anonymous said...

Not sure why but I am getting the following unresolved error when I try to compile.

"unresolved symbol CACTL2, first referenced in ./main.obj MSP-EXP430G2-Launchpad line 0 1294546805046 59"

Kind Regards,

mike.taivalmaa dot yahoo.com

JMoore said...

So by configuring CA1 as V+ and CA2 as V-, and CA7 as output, you can emulate an op-amp with our MSP430, right?

void main(void) { // UNTESTED
CACTL1 = 1<<3 ; //CAON
CACTL2 = 0x20 | 0x08 | 0x01 ; // CA2=V-, CA1=V+, CAOUT
LPM3; // Can we go this low?

And use the $0.50 chip as a $0.05 chip :)


Anonymous said...

hello david! first is you are doing a great job! it is currently helping me in out project.

i have a question. in configuring CACTL1 = CAREF1 + CARSEL + CAIE; is it equivalent to CACTL1=0b01100110?


David said...

Hi Geraldine,

You're on the right track-- if you look in the msp430g2211.h header file, you'll see that CAREF1 is 0x20, CARSEL is 0x40, and CAIE is 0x02, summing up to 0x62, which is 0b01100010. Looking in the Family User's Guide, enabling bit 3 as you've written it changes the interrupt to trigger on a falling edge rather than a rising edge. The shorthand for this is CAIES, which is used in the ISR in this code. So the binary value of CACTL1 is as you have it, but bit 3 toggles during the execution of the code.

Hope that helps!

(PS-- I've started standardizing to the header definitions that specify states for the multiple-bit selections like CAREF, so if I were to rewrite this code, I would use CAREF_2 instead of CAREF1. It's the exact same value, but the advantage of the other set is that if you want to set more than one bit in the register you only have to add one term rather than two or more.)

viper0n said...

Hi David,
I tried this program in my msp430g2553 as it has a comparator similar to g2211. But for some reason the CAOUT is set immediately when the comparator is turned on even when nothing is connected to the V+ terminal. I assumed this to be a floating terminal problem but still it shows the same problem. Do you have any suggestions ?

David Olson said...

It's hard to say without seeing your wiring and setup. Did you remove the jumper that connects the UART to P1.1? I'm assuming you're using the stock code, just changing the appropriate included header? Do you have (or can you get) a G2211 and see if that gives you the same problem? I'll have to dig out a G2553 and try with that. My two LaunchPads are both early generations, so neither came with the chips shipped with modern LaunchPads.