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.

MSP430F6776A: ADC trouble getting correct readings from SD24.

Part Number: MSP430F6776A

Tool/software:

New to embedded and am trying to read the raw data from the sd24 channels that have a pressure sensor connected to it (not calibrated yet but that's not important).
I've based my code off of a library demo code that initially outputted the top 16 bits of channels 0, 1 and 2.
I modified the code to use SD24_B_getResults function to get 2 16 bit chunks. The problem with this is the first 8 0's seem to be put at the beginning of the number not the end, putting the number outside of it's 24 bit range.
I even tried bit shifting it and manually taking away the first 8 bits and the numbers still did not seem correct.
From my understanding the conversion from raw data to MV is (results/2^23) * .6 and it should give me a mv of .115 which would make the raw data be ~ 1,607,816.53. Because of the incorrect setup the outputs are around 2708761088 on channel 0 alone.
I tried checking if it might be something setup with the SD24_B_initConverterAdvancedParam settings, but changing that didn't seem to do anything either. Please let me know what I can do to get the correct reading from the sd24 channels.


//*****************************************************************************
//  MSP430F67791A Demo - SD24_B, Continuous Conversion on a Group of 3 Channels
//
//  Description: This program uses the SD24_B module to perform continuous
//  conversions on a group of channels (0, 1 and 2). An SD24_B interrupt occurs
//  whenever the conversions have completed. Test by applying voltages to the
//  3 input channels and setting a breakpoint at the line indicated
//  below. Run program until it reaches the breakpoint, then use
//  the debugger's watch window to view the conversion results. Results
//  (upper 16 bits only) are stored in three arrays, one for each channel.
//  ACLK = n/a, MCLK = SMCLK = DCO =  ~ 1.1MHz
//  //* For minimum Vcc required for SD24_B module - see datasheet          *//
//  //* 100nF cap between Vref and AVss is recommended when using 1.5V REF  *//
//
//               MSP430F67791A
//             -----------------
//         /|\|              XIN|-
//          | |                 |
//          --|RST          XOUT|-
//            |                 |
//   Vin1+ -->|SD0P0            |
//   Vin1- -->|SD0N0            |
//   Vin2+ -->|SD1P0            |
//   Vin2- -->|SD1N0            |
//   Vin3+ -->|SD2P0            |
//   Vin3- -->|SD2N0            |
//            |            VREF |---+
//            |                 |   |
//            |                 |  -+- 100nF
//            |                 |  -+-
//            |                 |   |
//            |            AVss |---+
//            |                 |
//
//   E. Chen
//   Texas Instruments Inc.
//   January 2014
//   Built with CCS Version: 5.5.0 and IAR Embedded Workbench Version: 5.52
//*****************************************************************************
#include <msp430.h>
#include "sd24_b.h"
#include <stdio.h>
/* Number of conversion results to store */
#define Num_of_Results 8

/* Arrays to store SD24_B conversion results */
unsigned int Ch0results[Num_of_Results];
unsigned int Ch1resultsLow[Num_of_Results];
unsigned int Ch1results[Num_of_Results];
unsigned int Ch2results[Num_of_Results];
uint32_t raw24;


volatile uint32_t lastRaw = 0;
volatile uint32_t Ch0Full[Num_of_Results];
volatile uint32_t Ch1FullBeforeConvert[Num_of_Results];
volatile uint32_t Ch1Full[Num_of_Results];
volatile uint32_t Ch2Full[Num_of_Results];
uint8_t Globalconverter = SD24_B_CONVERTER_1;


//#pragma vector=SD24B_VECTOR
__interrupt void SD24B_ISR(void)
{
    lastRaw = SD24_B_getResults(SD24_BASE, Globalconverter);
    SD24_B_clearInterrupt(
        SD24_BASE,
        Globalconverter,
        SD24_B_CONVERTER_INTERRUPT
    );
    __bic_SR_register_on_exit(LPM0_bits);  // wake main loop
}


void AlignmentSetup(void){
    SD24_B_initParam modParam = {
           .clockSourceSelect = SD24_B_CLOCKSOURCE_SMCLK,
           .clockPreDivider   = SD24_B_PRECLOCKDIVIDER_1,
           .clockDivider      = SD24_B_CLOCKDIVIDER_1,
           .referenceSelect   = SD24_B_REF_INTERNAL
       };
       SD24_B_init(SD24_BASE, &modParam);

       // —————————————————————————————
       // 2) Advanced per-converter init
       //    (right-aligned, two’s-complement,
       //     1× PGA, OSR=256, continuous)
       // —————————————————————————————
       SD24_B_initConverterAdvancedParam advParam = {
           .converter       = SD24_B_CONVERTER_0,          // channel 0 (SD0P0/SD0N0)
           .alignment       = SD24_B_ALIGN_RIGHT,          // right-aligned
           .startSelect     = SD24_B_CONVERSION_SELECT_SD24SC,
           .conversionMode  = SD24_B_CONTINUOUS_MODE,
           .dataFormat      = SD24_B_DATA_FORMAT_2COMPLEMENT,
           .sampleDelay     = SD24_B_FOURTH_SAMPLE_INTERRUPT,             // no interrupt delay
           .oversampleRatio = SD24_B_OVERSAMPLE_256,               // 256× OSR
           .gain            = SD24_B_GAIN_1             // unity PGA
       };

       SD24_B_initConverterAdvanced(SD24_BASE, &advParam);

       advParam.converter = SD24_B_CONVERTER_1;           // channel 1
       SD24_B_initConverterAdvanced(SD24_BASE, &advParam);

       advParam.converter = SD24_B_CONVERTER_2;           // channel 2
       SD24_B_initConverterAdvanced(SD24_BASE, &advParam);

       // —————————————————————————————
       // 3) Enable interrupts on channel 2 only
       //    (as in the demo)
       // —————————————————————————————
       SD24_B_enableInterrupt(SD24_BASE,
                              SD24_B_CONVERTER_2,
                              SD24_B_CONVERTER_INTERRUPT);

       // —————————————————————————————
       // 4) Start bucket-brigade / group conversion:
       //    group0 = converters 0–2
       // —————————————————————————————
       // TRGCTL1 holds the group-start bits (grp0 = bit0)
       HWREG16(SD24_BASE + OFS_SD24BCTL1) |= SD24GRP0SC;

       // —————————————————————————————
       // 5) Enter LPM0 w/ interrupts
       // —————————————————————————————
       //__bis_SR_register(LPM0_bits | GIE);
       /* */
}

uint32_t raw;
int32_t signedResult;

int32_t Convert2(int32_t bounds) {
    int32_t raw = (int32_t)(lastRaw >> 8);
    return (raw << 8) >> 8;  // Sign-extend 24-bit into 32-bit by shifting
}

int32_t Convert(uint32_t x)
{
    int32_t t = x & 0xffffff;
    return t - (t >> 23 << 24);
}

void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;               // Stop WDT

    SD24BCTL0 = SD24REFS | SD24SSEL_1;      // Select internal REF
                                            // Select SMCLK as SD24_B clock source


    AlignmentSetup(); // does this update alignments? Moving it stop register interrupts.
    SD24BCCTL0 = SD24ALGN | SD24SCS_4;      // Left-aligned, group 0
    SD24BCCTL1 = SD24ALGN | SD24SCS_4;      // Left-aligned, group 0
    SD24BCCTL2 = SD24ALGN | SD24SCS_4;      // Left-aligned, group 0


    SD24BIE = SD24IE2;                      // Enable channel 2 interrupt

    __delay_cycles(0x3600);                 // Delay for 1.5V REF startup

    SD24BCTL1 |= SD24GRP0SC;                // Set bit to start conversion
    __bis_SR_register(LPM0_bits | GIE);     // Enter LPM0 w/ interrupts
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=SD24B_VECTOR //ties interrupt to below function
__interrupt void SD24BISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(SD24B_VECTOR))) SD24BISR (void)
#else
#error Compiler not supported!
#endif
{
    static unsigned int index = 0;

    switch (SD24BIV)
    {
        case SD24BIV_SD24OVIFG:             // SD24MEM Overflow
            break;
        case SD24BIV_SD24TRGIFG:            // SD24 Trigger IFG
            break;
        case SD24BIV_SD24IFG0:              // SD24MEM0 IFG
            break;
        case SD24BIV_SD24IFG1:              // SD24MEM1 IFG
            break;
        case SD24BIV_SD24IFG2:              // SD24MEM2 IFG
        {
             raw = SD24_B_getResults(SD24_BASE, Globalconverter) & 0x00FFFFFF; // Mask to 24 bits
            if (raw & 0x00800000) {
                raw |= 0xFF000000; // Sign-extend if negative
            }
            signedResult = (int32_t)raw;
            lastRaw = SD24_B_getResults(SD24_BASE, Globalconverter);
            Ch0Full[index] = SD24_B_getResults(SD24_BASE, SD24_B_CONVERTER_0); //gives me ~2708761088
            Ch1Full[index] = SD24_B_getResults(SD24_BASE, SD24_B_CONVERTER_1); //gives me ~2360862464
            //Ch1FullBeforeConvert[index] = Ch1Full[index] ;                     
            //Ch1Full[index] = Convert2(Ch1Full[index]);
            Ch2Full[index] = SD24_B_getResults(SD24_BASE, SD24_B_CONVERTER_2); //gives me ~2148898816



            Ch0results[index] = SD24BMEMH0; // Save CH0 results (clears IFG)

            Ch1resultsLow[index] = SD24BMEML1; // Low CH1 results (clears IFG)
            Ch1results[index] = SD24BMEMH1; // Save CH1 results (clears IFG)
            Ch2results[index] = SD24BMEMH2; // Save CH2 results (clears IFG)
            if (++index == Num_of_Results)
            {
                index = 0;                  // SET BREAKPOINT HERE
            }
            break;
        }
    }
}

  • I didn't find the demo you started with, but this looks odd:

    >AlignmentSetup(); // does this update alignments? Moving it stop register interrupts.
    > SD24BCCTL0 = SD24ALGN | SD24SCS_4; // Left-aligned, group 0
    > SD24BCCTL1 = SD24ALGN | SD24SCS_4; // Left-aligned, group 0
    > SD24BCCTL2 = SD24ALGN | SD24SCS_4; // Left-aligned, group 0

    AlignmentSetup() sets ALIGN_RIGHT (low 24 bits), but then the next three statements set left-alignment (high 24 bits). It looks as though your Convert functions expect right-alignment. Do you get more reasonable results if you remove the SD24ALGN settings?

**Attention** This is a public forum