TI - MCU - MSP430 user guide 32 -> SAC intelligent simulation combination

Keywords: Unity

SAC (Smart Analog Combo), i.e. intelligent simulation combination, the IP core does not take a long time to come out. At present, it is only used in two films: MSP430FR2353 and MSP430FR2355. First, let's look at the internal structure of SAC:

As can be seen from the above figure, the internal part is essentially an OPA amplifier. At the same time, there is a selection switch at the + and - input end of the operational amplifier, which can build different circuits according to the needs of customers. At the same time, a 12 bit DAC module is also integrated in the internal part, which is used to provide fixed voltage in some use environments and realize the purpose of voltage offset.

In view of the above internal structure, we make a detailed analysis:

For the + input, there are three channels to choose from:

00: pin in

01:12 bit DAC signal

10: The output of internal Amp, that is, the output of other SAC modules, is used for the combination of multi-level amps.

For - inputs, there are also three alternative channels:

00: pin access (the output of this Amp can also be selected to form a feedback circuit, or it can be directly grounded)

01: programmable gain

10: The output of internal Amp, that is, the output of other SAC modules, is used for the combination of multi-level amps.

So how to use it? What are the main aspects

In a word, as long as the circuit design of Amp is used, the resources of this module can be used. At the focus point, it is the detection of small current, such as blood glucose meter, blood oxygen meter, pulse detector, etc. in biotechnology. It can also be used to drive infrared or led with certain power.

Here are some common ways to connect:

  • General purpose mode

As shown in the general mode above, the positive and negative terminals of OA select external pins as input, and the output terminal does not feed back, so it can be used as an OA directly, and users can build their own peripheral circuits.

  • Buffer mode

The above circuit topology is the connection mode of voltage follower and voltage buffer (there are some differences between follower and buffer, not to elaborate). It can be used when users require high input impedance and low output impedance.

 

  • Reversing mode

 

Reverse mode, as shown above, this kind of circuit structure should be the most used circuit by the user. The negative terminal is the input, and the positive terminal can provide a required bias voltage. The specific formula is not detailed, and the data is much simpler.

For the bias voltage provided by the positive terminal, there are two ways: internal 12 bitDAC and direct external voltage. This is the two structures shown above.

 

  • Noninverting mode

The topology of this circuit is in-phase mode. The input is from the positive side, and the negative side and the output are connected by adjustable gain to form a feedback circuit.

 

SAC is essentially an operational amplifier structure. At the same time, it is equipped with multiple selection switches at the input and output terminals, so that users can avoid external resistance, capacitance and other circuits in the use process, save board space, and also accelerate user design. At the same time, the internal SAC modules can be cascaded for multi-level amplification, which is more convenient to use. So how to set up the internal circuit structure? Operation register, of course! The following details the relevant register settings and gives the reference program.

 

First, take a look at the contents of registers as a whole. The SAC module includes six registers, as follows:

 

  • SACxOA

 

Sacen: enable bit of SAC module, enable all SAC modules when 1, output bit high resistance state when disabled.

Oapm: the mode selection of OA, that is, it can be high-speed or low-speed. Of course, high-speed or low-speed will affect power consumption, bandwidth, speed, etc. for specific parameters, please refer to the chip's datasheet, as shown in the figure below for FR2355 data.

OAEN: internal OA enable, this bit is used to control the enable of OA module inside SAC.

NMUXEN: this bit controls the enabling of the negative input of OA. From the internal structure diagram, we can see that there are two levels before the negative input of OA: MUX in the first level, i.e. selecting the input source, and MUX in the second season. That is to say, even if the input source of MUX is selected, this must be enabled, otherwise MUX and the negative input of OA will be disconnected.

NSEL: negative input selection bit.

PMUXEN: this bit is similar to NMUXEN at the negative end, which controls the connection or disconnection of MUX at the positive end and OA.

PSEL: positive input selection bit.

 

  • SACxPGA

Gain: OA gain selection, that is, the setting bit of adjustable gain in the figure above, has three bits. With NSEL PSEL MSEL, gain selection in multiple modes can be realized.

MSEL: the selection of PGA mode controls the internal circuit structure as shown in the figure below:

To sum up, it can be found that circuit topology, i.e. gain and other parameters are related to MSEL PSEL NSEL GAIN. How to set these parameters? The following figure gives some examples of parameters. During the use, you can set the register according to the following data.

 

  • SACxDAC

 

The SACxDAC register is obviously used to control the 12 bit DAC module inside the SAC. What is the circuit structure of the internal DAC module like?

Then we can easily understand the meaning of each bit in this register by looking at the internal structure diagram of DAC.

DACSREF: this bit determines the reference voltage of DAC. There are two options: primary and secondary. The reference source of each item can be seen in the chip's datasheet, as shown in the figure below is the information of FR2355.

 

DACLSEL: as can be seen from the above structure, this bit determines whether the set DAC value enters the DAC CORE. When the set data enters the DAC CORE, it will drive the corresponding voltage output, that is to say, this bit determines the frequency of voltage change of the DAC CORE, which can be real-time or pulse controlled.

Dacmae: DMA request enable in DAC. When DAC data is updated, if this bit is enabled, there will be a DMA request.

Dacie: the enable signal of DAC interrupt. When DAC data is updated, an interrupt signal can be generated to CPU.

Dacen: DAC enable bit.

 

  • SACxDAT

This register is used to set the DAC voltage value. What is the DAC output voltage value? Calculate according to the following formula:

 

  • SACxDACSTS

 

This register is the status flag register of DAC. At present, only 0 bit is used for dacfg, and others are reserved.

Dacfg is the flag bit of DAC data update.

 

  • SACxIV

DAC interrupt vector register, read-only register, is related to the interrupt generated by the internal data update of DAC. When an interrupt is generated, the program at the interrupt vector will be triggered, and then the user's interrupt service program can be executed.

 

Well, after describing all registers of SAC, several routines are provided for your reference (MSP430FR2355):

  • General Purpose Mode:
#include <msp430.h>

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watch dog timer

  P1SEL0 |= BIT1 + BIT2 + BIT3;             // Select P1.1 P1.2 P1.3 OA function
  P1SEL1 |= BIT1 + BIT2 + BIT3;             // Select P1.1 P1.2 P1.3 OA function

  SAC0OA |= NMUXEN + PMUXEN;                // Enable negative and positive input
  SAC0OA |= OAPM;                           // Select low speed and low power mode
  SAC0OA |= SACEN + OAEN;                   // Enable SAC and OA

  __bis_SR_register(LPM3_bits);             // Enter LPM3
}

  • Buffer Mode:
#include <msp430.h>

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watch dog timer

  P1SEL0 |= BIT1 + BIT3;                    // Select P1.1 P1.3 as external OA function
  P1SEL1 |= BIT1 + BIT3;                    // Select P1.1 P1.3 as external OA function

  SAC0OA |= NMUXEN + PMUXEN + NSEL_1 + OAPM;// Enable negative and positive input
                                            // Select PGA source as OA negative input
                                            // Select low speed and low power mode
  SAC0PGA |= MSEL_1;                        // Set as Unity-Gain Buffer Mode
  SAC0OA |= SACEN + OAEN;                   // Enable SAC and OA

  __bis_SR_register(LPM3_bits);             // Enter LPM3
}
  • Inverting  Mode:
#include <msp430.h>

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watch dog timer

  // Disable the GPIO power-on default high-impedance mode
  // to activate previously configured port settings
  PM5CTL0 &= ~LOCKLPM5;

  // Configure reference module
  PMMCTL0_H = PMMPW_H;                    // Unlock the PMM registers
  PMMCTL2 = INTREFEN | REFVSEL_0;         // Enable internal 1.5V reference
  while(!(PMMCTL2 & REFGENRDY));          // Poll till internal reference settles

  P1SEL0 |= BIT1 | BIT2 | BIT3;             // Select P1.1 P1.2 P1.3 OA function
  P1SEL1 |= BIT1 | BIT2 | BIT3;             // Select P1.1 P1.2 P1.3 OA function

  SAC0DAC = DACSREF_1;                       // Select 1.5V int Vref as DAC reference
  SAC0DAT = 0x0FFF;                         // Set SAC DAC data to 1.5V
  SAC0DAC |= DACEN;                         // Enable DAC
  SAC0OA = NMUXEN + PMUXEN + PSEL_1 + NSEL_1;//Select positive and negative pin input
  SAC0OA |= OAPM;                           // Select low speed and low power mode
  SAC0PGA = GAIN2 + MSEL_0;                 // Set inverting PGA mode with Gain=8
  SAC0OA |= SACEN + OAEN;                   // Enable SAC and OA

  __bis_SR_register(LPM3_bits);             // Enter LPM3
}
  • Non-inverting  Mode:
#include <msp430.h>

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watch dog timer

  P1SEL0 |= BIT1 + BIT2 + BIT3;             // Select P1.1 P1.2 P1.3 OA function
  P1SEL1 |= BIT1 + BIT2 + BIT3;             // Select P1.1 P1.2 P1.3 OA function

  SAC0OA = NMUXEN + PMUXEN + PSEL_0 + NSEL_1;//Select positive and negative pin input
  SAC0OA |= OAPM;                           // Select low speed and low power mode
  SAC0PGA = GAIN0 + GAIN2 + MSEL_2;         // Set Non-inverting PGA mode with Gain=17
  SAC0OA |= SACEN + OAEN;                   // Enable SAC and OA

  __bis_SR_register(LPM3_bits);             // Enter LPM3
}

  • DAC Buffer Mode: Output DAC data and use SAC as DAC
#include <msp430.h>

unsigned int DAC_data=0;

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watch dog timer

  P1SEL0 |= BIT1;                           // Select P1.1 as OA0O function
  P1SEL1 |= BIT1;                           // OA is used as buffer for DAC

  PM5CTL0 &= ~LOCKLPM5;          // Disable the GPIO power-on default high-impedance mode
                                 // to activate previously configured port settings

  // Configure reference module
  PMMCTL0_H = PMMPW_H;                      // Unlock the PMM registers
  PMMCTL2 = INTREFEN | REFVSEL_2;           // Enable internal 2.5V reference
  while(!(PMMCTL2 & REFGENRDY));            // Poll till internal reference settles

  SAC0DAC = DACSREF_1 + DACLSEL_2 + DACIE;  // Select int Vref as DAC reference
  SAC0DAT = DAC_data;                       // Initial DAC data
  SAC0DAC |= DACEN;                         // Enable DAC
  SAC0OA = NMUXEN + PMUXEN + PSEL_1 + NSEL_1;//Select positive and negative pin input
  SAC0OA |= OAPM;                            // Select low speed and low power mode
  SAC0PGA = MSEL_1;                          // Set OA as buffer mode
  SAC0OA |= SACEN + OAEN;                    // Enable SAC and OA

  // Use TB2.1 as DAC hardware trigger
  TB2CCR0 = 100-1;                           // PWM Period/2
  TB2CCTL1 = OUTMOD_6;                       // TBCCR1 toggle/set
  TB2CCR1 = 50;                              // TBCCR1 PWM duty cycle
  TB2CTL = TBSSEL__SMCLK | MC_1 | TBCLR;     // SMCLK, up mode, clear TBR

  __bis_SR_register(LPM3_bits + GIE);        // Enter LPM3, Enable Interrupt
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = SAC0_SAC2_VECTOR
__interrupt void SAC0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(SAC0_SAC2_VECTOR))) SAC0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(SAC0IV,SACIV_4))
  {
    case SACIV_0: break;
    case SACIV_2: break;
    case SACIV_4:
        DAC_data++;
        DAC_data &= 0xFFF;
        SAC0DAT = DAC_data;                 // DAC12 output positive ramp
        break;
    default: break;
  }
}
  • SAC0 + SAC2 cascade mode:
#include <msp430.h>

unsigned int adcResult;

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer

  P1DIR |= BIT0;                            // Select P1.0 as output
  P1OUT &= ~BIT0;                           // Set P1.0 output low

  PM5CTL0 &= ~LOCKLPM5;       // Disable the GPIO power-on default high-impedance mode
                              // to activate previously configured port settings

  //Select P1.1 P1.2 P1.3 as SAC0 function
  //Select P3.1 P3.2 P3.3 as SAC2 function
  P1SEL0 |= BIT1 + BIT2 + BIT3;
  P1SEL1 |= BIT1 + BIT2 + BIT3;
  P3SEL0 |= BIT1 + BIT2 + BIT3;
  P3SEL1 |= BIT1 + BIT2 + BIT3;

  SAC2OA = NMUXEN + PMUXEN + PSEL_0 + NSEL_1;//Select positive and negative pin input
  SAC2OA |= OAPM;                           // Select low speed and low power mode
  SAC2PGA = GAIN1 + MSEL_2;                 // Set Non-inverting PGA mode with Gain=3
  SAC2OA |= SACEN + OAEN;                   // Enable SAC2 and OA
  SAC0OA = NMUXEN + PMUXEN + PSEL_2 + NSEL_1;//Select Pair OA source
  SAC0OA |= OAPM;                           // Select low speed and low power mode
  SAC0PGA = GAIN0 + GAIN1 + MSEL_2;         // Set Non-inverting PGA mode with Gain=5
  SAC0OA |= SACEN + OAEN;                   // Enable SAC0 and OA

  // Configure ADC12
  ADCCTL0 &= ~ADCENC;                       // Disable ADC
  ADCCTL0 = ADCSHT_2 | ADCON;               // ADCON, S&H=16 ADC clks
  ADCCTL1 = ADCSHP;                         // ADCCLK = MODOSC; sampling timer
  ADCCTL2 = ADCRES_2;                       // 12-bit conversion results
  ADCIE = ADCIE0;                           // Enable ADC conv complete interrupt
  ADCMCTL0 = ADCINCH_1 | ADCSREF_0;         // A1 ADC input select = OA0 output
                                            // Vref = DVCC

  while(1)
  {
      ADCCTL0 |= ADCENC | ADCSC;          // Sampling and conversion start
      __bis_SR_register(LPM0_bits | GIE); // Enter LPM0, ADC_ISR will force exit
      __no_operation();                   // For debug only

      if (adcResult > 2047)                // OA output > 1/2 VCC
          P1OUT |= BIT0;                  // Set P1.0 LED on
      else
          P1OUT &= ~BIT0;                 // Clear P1.0 LED off
  }
}

// ADC interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC_VECTOR
__interrupt void ADC_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(ADCIV, ADCIV_ADCIFG))
  {
      case ADCIV_NONE:
          break;
      case ADCIV_ADCOVIFG:
          break;
      case ADCIV_ADCTOVIFG:
          break;
      case ADCIV_ADCHIIFG:
          break;
      case ADCIV_ADCLOIFG:
          break;
      case ADCIV_ADCINIFG:
          break;
      case ADCIV_ADCIFG:
          adcResult = ADCMEM0;            // Read ADC memory
          __bic_SR_register_on_exit(LPM0_bits);// Exit from LPM
          break;
      default:
          break;
  }
}
  • SAC0 + SAC2 + eCOMP0 cascade + comparator mode (SAC can be directly connected to internal comparator)

Please refer to other posts I wrote for the tutorial of using comparator module.

#include <msp430.h>

unsigned int adcResult;

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer

  P1DIR |= BIT5;                            // Select P1.5 as output
  P1OUT &= ~BIT5;                           // Set P1.5 output low
  PM5CTL0 &= ~LOCKLPM5;          // Disable the GPIO power-on default high-impedance mode
                                 // to activate previously configured port settings

  // Configure reference module
  PMMCTL0_H = PMMPW_H;                    // Unlock the PMM registers
  PMMCTL2 = INTREFEN | REFVSEL_0;         // Enable internal 1.5V reference
  while(!(PMMCTL2 & REFGENRDY));          // Poll till internal reference settles

  //Select P1.1 P1.2 P1.3 as SAC0 function
  //Select P3.1 P3.2 P3.3 as SAC2 function
  P1SEL0 |= BIT1 + BIT2 + BIT3;
  P1SEL1 |= BIT1 + BIT2 + BIT3;
  P3SEL0 |= BIT1 + BIT2 + BIT3;
  P3SEL1 |= BIT1 + BIT2 + BIT3;

  SAC0OA = NMUXEN + PMUXEN + PSEL_0 + NSEL_1;//Select positive and negative pin input
  SAC0OA |= OAPM;                           // Select low speed and low power mode
  SAC0PGA = GAIN0 + GAIN1 + MSEL_2;         // Set Non-inverting PGA mode with Gain=5
  SAC0OA |= SACEN + OAEN;                   // Enable SAC0 and OA0

  SAC2DAC = DACSREF_1;                 // Select 1.5V internal Vref as SAC2 DAC reference
  SAC2DAT = 0xAAA;                          // Set SAC2 DAC output = 1V
  SAC2DAC |= DACEN;                         // Enable SAC2 DAC
  SAC2OA = NMUXEN + PMUXEN + PSEL_1 + NSEL_1;//Select positive and negative pin input
  SAC2OA |= OAPM;                           // Select low speed and low power mode
  SAC2PGA = MSEL_1;                         // Set OA as buffer mode
  SAC2OA |= SACEN + OAEN;                   // Enable SAC2 and OA2

  // Setup eCOMP
  CP0CTL0 = CPPSEL_5 | CPNSEL_5;          // Select SAC0 and SAC2 output as eCOMP0 input
  CP0CTL0 |= CPPEN | CPNEN;                  // Enable eCOMP input
  CP0CTL1 |= CPIIE | CPIE;                   // Enable eCOMP dual edge interrupt
  CP0CTL1 |= CPEN | CPMSEL;                  // Turn on eCOMP, in low power mode


  __bis_SR_register(LPM3_bits | GIE);       // Enter LPM3
  __no_operation();                         // For debug
}

// eCOMP interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ECOMP0_ECOMP1_VECTOR
__interrupt void ECOMP0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ECOMP0_ECOMP1_VECTOR))) ECOMP0_ISR (void)
#else
#error Compiler not supported!
#endif
{
    switch(__even_in_range(CP0IV, CPIV__CPIIFG))
    {
        case CPIV__NONE:
            break;
        case CPIV__CPIFG:
            P1OUT |= BIT5;                  // OA0+ input > 200mV
            break;
        case CPIV__CPIIFG:
            P1OUT &= ~BIT5;                 // OA0+ input < 200mV
            break;
        default:
            break;
    }
}

OK, all the contents of SAC have been explained here, and the basic common program routines have been provided. I won't explain the program in detail. In the process of using the program, the program configuration can be easily understood corresponding to the above register description.

Published 9 original articles, won praise 0, visited 127
Private letter follow

Posted by websitesca on Thu, 16 Jan 2020 03:17:28 -0800