Implements an 8-bit sample and hold ADC on the MSP430

How to write a C Program to Implements an 8-bit sample and hold ADC on the MSP430 using its onboard comparator and transmission gate in C Programming Language ?


This C Program Implements an 8-bit sample and hold ADC on the MSP430 using its onboard comparator and transmission gate.

I/O Ports:
  P1.0 <-> CA0  (sampling capacitor)
  P1.1 <-  CA1  (Vin)
  P1.2 <-  CA2  (resistor network ramp)
  P1.4 ->  /CS  (DAC)
  P1.5 ->  SCLK (DAC)
  P1.7 ->  SD1  (DAC)
  P2.0 ->  BIT0 (resistor network)
  P2.1 ->  BIT1 (resistor network)
  P2.2 ->  BIT2 (resistor network)
  P2.3 ->  BIT3 (resistor network)
  P2.4 ->  BIT4 (resistor network)
  P2.5 ->  BIT5 (resistor network)
  P2.6 ->  BIT6 (resistor network)
  P2.7 ->  BIT7 (resistor network)


Solution:

  1. #include <msp430.h>
  2. /*
  3.  * main.c
  4.  *
  5.  * Title: Project 3 ADC Fun!
  6.  *
  7.  * Authors: Daniel Hodges & Omar Arriaga
  8.  *
  9.  * Description: Implements an 8-bit sample and hold ADC on the MSP430 using its onboard comparator
  10.  *              and transmission gate.
  11.  *
  12.  * I/O Ports:
  13.  *
  14.  *  P1.0 <-> CA0  (sampling capacitor)
  15.  *  P1.1 <-  CA1  (Vin)
  16.  *  P1.2 <-  CA2  (resistor network ramp)
  17.  *  P1.4 ->  /CS  (DAC)
  18.  *  P1.5 ->  SCLK (DAC)
  19.  *  P1.7 ->  SD1  (DAC)
  20.  *
  21.  *  P2.0 ->  BIT0 (resistor network)
  22.  *  P2.1 ->  BIT1 (resistor network)
  23.  *  P2.2 ->  BIT2 (resistor network)
  24.  *  P2.3 ->  BIT3 (resistor network)
  25.  *  P2.4 ->  BIT4 (resistor network)
  26.  *  P2.5 ->  BIT5 (resistor network)
  27.  *  P2.6 ->  BIT6 (resistor network)
  28.  *  P2.7 ->  BIT7 (resistor network)
  29.  *
  30.  */
  31. void CLK16MHz();
  32. void portsSetup();
  33. void sampleInput();
  34. void compareInput();
  35. void Drive_DAC(unsigned int level);
  36. int ramp_Value = 0;
  37. int DAC_Value = 0;
  38. int main(void) {
  39.     WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
  40.     CLK16MHz();               // set clock to 16MHz
  41.     portsSetup();             // setup and initialize ports
  42.     _enable_interrupts();     // enable interrupts
  43.     // samples input, determines input, sends sample to DAC
  44.     while(1){
  45.         sampleInput();        // sample Vin and hold for cap to charge
  46.         compareInput();       // compare sampled Vin to a 0 to Vcc ramp
  47.                               // interrupt will trigger once CAOUT goes low
  48.         Drive_DAC(DAC_Value); // send new sample to DAC
  49.     }
  50. }
  51. // set SMCLK to 16MHZ
  52. void CLK16MHz(){
  53.     // 16Mhz SMCLK
  54.     if (CALBC1_16MHZ==0xFF)             // If calibration constant erased
  55.     {
  56.       while(1);                         // do not load, trap CPU!!
  57.     }
  58.     DCOCTL = 0;                         // Select lowest DCOx and MODx settings
  59.     BCSCTL1 = CALBC1_16MHZ;             // Set range
  60.     DCOCTL = CALDCO_16MHZ;              // Set DCO step + modulation
  61. }
  62. // initialize and setup ports
  63. void portsSetup(){
  64.     /*****************************
  65.      * Resistor Network Setup    *
  66.      ****************************/
  67.     // Set P2.6,7 as GPIO ports
  68.     P2SEL &= ~(BIT7 + BIT6);
  69.     P2SEL2 &= ~(BIT7 + BIT6);
  70.     P2DIR |= 0xFF;                      // Set Port2.0-7 as outputs for resistor network
  71.     /*****************************
  72.      * Comparator A Setup        *
  73.      ****************************/
  74.     CAPD |= CAPD0 + CAPD1 + CAPD2;      // Disable input buffer for CA0, CA1, CA2
  75.     CACTL1 |= CAIES + CAIE;             // Comparator interrupt enable, falling edge
  76.     // select CA0 for first mux
  77.     CACTL2 |= P2CA0;
  78.     CACTL2 &= ~(P2CA4);
  79.     /*****************************
  80.      * DAC and SPI Setup         *
  81.      ****************************/
  82.     P1SEL  = BIT7 + BIT5;               // These two lines dedicate P1.7 and P1.5
  83.     P1SEL2 = BIT7 + BIT5;               // for UCB0SIMO and UCB0CLK respectively
  84.     P1DIR |= BIT4; // P1.4 used to activate /CE on DAC
  85.     // SPI Setup
  86.     // clock inactive state = low,
  87.     // MSB first, 8-bit SPI master,
  88.     // 4-pin active Low STE, synchronous
  89.     //
  90.     // 4-bit mode disabled for now
  91.     UCB0CTL0 |= UCCKPL + UCMSB + UCMST + /* UCMODE_2 */ + UCSYNC;
  92.     UCB0CTL1 |= UCSSEL_2;               // UCB0 will use SMCLK as the basis for
  93.                                         // the SPI bit clock
  94.     UCB0CTL1 &= ~UCSWRST;               // **Initialize USCI state machine**
  95.                                         // SPI now Waiting for something to
  96.                                         // be placed in TXBUF.
  97. }
  98. // samples Vin on sampling capacitor
  99. void sampleInput(){
  100.     // select CA1 (Vin) for second mux
  101.     CACTL2 |= P2CA1;
  102.     CACTL2 &= ~(P2CA2 + P2CA3);
  103.     CACTL2 |= CASHORT;    // turn on transmission gate to start sampling
  104.     _delay_cycles(1500);  // delay for sampling cap to charge
  105.     CACTL2 &= ~CASHORT;   // turn off transmission gate to end sampling
  106. }
  107. // compares sample on sampling capacitor to 0 to Vcc ramp
  108. void compareInput(){
  109.     // select CA2 (ramp) for second mux
  110.     CACTL2 |= P2CA2;
  111.     CACTL2 &= ~(P2CA1 + P2CA3);
  112.     CACTL1 |= CAON;       // turn comparator on
  113.     // start ramp from 0 to Vcc using resistor network
  114.     for(ramp_Value = 0; ramp_Value < 256; ramp_Value++){
  115.         P2OUT = ramp_Value;
  116.     }
  117.     CACTL1 &= ~CAON;      // turn comparator off
  118.     P2OUT = 0;            // set ramp back to 0
  119. }
  120. // Drives DAC through SPI; takes value from 0 to 4096
  121. void Drive_DAC(unsigned int level){
  122.       unsigned int DAC_Word = 0;
  123.       DAC_Word = (0x3000) | (level & 0x0FFF);   // 0x1000 sets DAC for Write
  124.                                                 // to DAC, Gain = 1, /SHDN = 1
  125.                                                 // and put 12-bit level value
  126.                                                 // in low 12 bits.
  127.       P1OUT &= ~BIT4;                           // Clear P1.4 (drive /CS low on DAC)
  128.                                                 // Using a port output to do this for now
  129.       UCB0TXBUF = (DAC_Word >> 8);              // Shift upper byte of DAC_Word
  130.                                                 // 8-bits to right
  131.       while (!(IFG2 & UCB0TXIFG));              // USCI_A0 TX buffer ready?
  132.       UCB0TXBUF = (unsigned char)
  133.                    (DAC_Word & 0x00FF);         // Transmit lower byte to DAC
  134.       while (!(IFG2 & UCB0TXIFG));              // USCI_A0 TX buffer ready?
  135.       P1OUT |= BIT4;                            // Set P1.4   (drive /CS high on DAC)
  136.       return;
  137. }
  138. // Comparator A interrupt service routine
  139. #pragma vector=COMPARATORA_VECTOR
  140. __interrupt void Comparator_A (void)
  141. {
  142.     DAC_Value = (ramp_Value * 12);              // convert and store current ramp_Value in DAC_Value
  143. }


Learn More :