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.
I am using the MSP4305529's 12 bit ADC to acquire voltage readings. 8 samples are taken then averaged by a SCALE_FACTOR of 3. The result is then stored in sum_adc_data.
sum_adc_data >>= SCALE_FACTOR;
I wanted to output the value as a voltage, so we stored the value in vout. In order to get the correct voltage we multiplied by the appropriate ADC12_RATIO (2500/4095).
vout = sum_adc_data * ADC12_RATIO;
the problem is that when I check the registers in CCS vout does not give me the appropriate value. I decided to just copy the value from the sum_adc_data to vout.
vout = sum_adc_data ;
I still obtained the same result for vout. Below I have provided the code and a screenshot of the registers:
#include <msp430.h> #include <stdint.h> #include "TI_LMP91000.h" #include "TI_LMP91000_register_settings.h" #include "TI_MSP430.h" #include "TI_MSP430_hardware_board.h" #include "TI_MSP430_i2c.h" /*----------------------------------------------------------------------------*/ void ADC12_Init(void); // To init MSP430F5528 ADC12 & Start Conversion /*----------------------------------------------------------------------------*/ #define NUM_OF_RESULTS 8 // Number of temp sensor samples to take #define SCALE_FACTOR 3 // For averaging converted samples #define ADC12_RATIO 0.61035 // 2500/4096 (2.5V reference & 12bit converter) //****************************************************************************** void main(void) { uint8_t status = TI_LMP91000_NOT_READY; uint8_t read_val[2]; // buffer to store register values WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer TI_LMP91000_LED_PxOUT |= TI_LMP91000_LED_PIN; // Set LED ON TI_LMP91000_LED_PxDIR |= TI_LMP91000_LED_PIN; // Set pin direction is output I2CSetup(LMP91000_I2C_Address); // Initialize I2C module TI_LMP91000_MENB_PxOUT &= ~TI_LMP91000_MENB_PIN; // Enable \MENB Pin TI_LMP91000_MENB_PxDIR |= TI_LMP91000_MENB_PIN; // Set pin direction is output while (status == TI_LMP91000_NOT_READY) status = LMP91000_I2CReadReg(TI_LMP91000_STATUS_REG); // Read device ready status LMP91000_I2CWriteReg(TI_LMP91000_LOCK_REG, TI_LMP91000_WRITE_UNLOCK); // unlock the registers for write LMP91000_I2CWriteReg(TI_LMP91000_TIACN_REG, TI_LMP91000_TIACN_REG_VALUE); // Modify TIA control register LMP91000_I2CWriteReg(TI_LMP91000_REFCN_REG, TI_LMP91000_REFCN_REG_VALUE); // Modify REF control register read_val[0] = LMP91000_I2CReadReg(TI_LMP91000_TIACN_REG); // Read to confirm register is modified read_val[1] = LMP91000_I2CReadReg(TI_LMP91000_REFCN_REG); // Read to confirm register is modified if ((read_val[0] != TI_LMP91000_TIACN_REG_VALUE) || (read_val[1] != TI_LMP91000_REFCN_REG_VALUE)) // test values took effect while (1); // otherwise error LMP91000_I2CWriteReg(TI_LMP91000_LOCK_REG, TI_LMP91000_WRITE_LOCK); // lock the registers LMP91000_I2CWriteReg(TI_LMP91000_MODECN_REG, TI_LMP91000_MODECN_REG_VALUE); // 3-lead amperometric cell ADC12_Init(); // Initialize MSP430F5528 ADC12 & Start Conversion __bis_SR_register(LPM0_bits + GIE); // Enter LPM0, Enable interrupts __no_operation(); // For debugger } // Description: Initialization of the ADC12 Module & Start Conversion /*----------------------------------------------------------------------------*/ void ADC12_Init(void) { TI_LMP91000_VOUT_ADC12_PxSEL |= TI_LMP91000_VOUT_ADC12_PIN; // Enable A/D channel A0 REFCTL0 &= ~REFMSTR; // Reset REFMSTR to hand over control to // ADC12_A ref control registers ADC12CTL0 = ADC12ON+ADC12SHT0_8+ADC12MSC; // Turn on ADC12, set sampling time // set multiple sample conversion ADC12CTL0 |= ADC12REFON+ADC12REF2_5V; // Turn on Ref Gen & set to 2.5V ADC12MCTL0 = ADC12SREF_1; // Vr+ = Vref+ and Vr- = AVSS ADC12CTL1 = ADC12SHP+ADC12CONSEQ_2; // Use sampling timer, set mode ADC12IE = ADC12IE0; // Enable ADC12IFG.0 __delay_cycles(500); // delay to allow Ref to settle ADC12CTL0 |= ADC12ENC; // Enable conversions ADC12CTL0 |= ADC12SC; // Start conversion } /*----------------------------------------------------------------------------*/ // Description: // ADC12 Interrupt Service Routine /*----------------------------------------------------------------------------*/ #pragma vector=ADC12_VECTOR __interrupt void ADC12ISR (void) { static uint8_t index = 0; static volatile uint16_t results[NUM_OF_RESULTS]; // To store ADC output static uint32_t sum_adc_data = 0; // accumulate and avg adc results static volatile float vout; // lmp91000 vout switch(__even_in_range(ADC12IV,34)) { case 0: break; // Vector 0: No interrupt case 2: break; // Vector 2: ADC overflow case 4: break; // Vector 4: ADC timing overflow case 6: // Vector 6: ADC12IFG0 results[index] = ADC12MEM0; // Move results sum_adc_data += ADC12MEM0; index++; // Increment results index, modulo; if (index == NUM_OF_RESULTS) { sum_adc_data >>= SCALE_FACTOR; // Divide by NUM_OF_RESULTS vout = sum_adc_data * ADC12_RATIO; // LMP91000 vout sum_adc_data = 0; // Set Breakpoint here & see measured vout index = 0; } break; case 8: break; // Vector 8: ADC12IFG1 case 10: break; // Vector 10: ADC12IFG2 case 12: break; // Vector 12: ADC12IFG3 case 14: break; // Vector 14: ADC12IFG4 case 16: break; // Vector 16: ADC12IFG5 case 18: break; // Vector 18: ADC12IFG6 case 20: break; // Vector 20: ADC12IFG7 case 22: break; // Vector 22: ADC12IFG8 case 24: break; // Vector 24: ADC12IFG9 case 26: break; // Vector 26: ADC12IFG10 case 28: break; // Vector 28: ADC12IFG11 case 30: break; // Vector 30: ADC12IFG12 case 32: break; // Vector 32: ADC12IFG13 case 34: break; // Vector 34: ADC12IFG14 default: break; } }
here are the results when we multiply with the ADC12_RATIO:
here are the results when the ratio is removed
shouldn't my vout have the same value as sum_adc_data since all i did was assign the value to vout? Is there a problem with float types in the msp430? How can I fix this issue?
I'm not sure what is happening within your code but in general I would avoid floating point operations on the MSP430 as they are very expensive. What I would do instead would be to change the math to support fixed point mulitplication and division. You can do so by changing your vout line to:
"vout = (sum_adc_data * 2500) / 4095;"
and declaring vout as an int. You will still lose some accuracy when dividing by the "4095" because it will be truncated but this is a much more efficient implementation given the use of the MSP430 controller.
You can also check out this document for how to best perform multiplicaiton and division operations within the MSP430:
http://www.ti.com/lit/an/slaa329/slaa329.pdf
Matt
Greetings Matt,
First of all thank you for the quick response! The data sheet reads:
vout = sum_adc_data * ADC12_RATIO // ADC12_RATIO is 0.6103
However, I still attempted the method you advised and I obtained the following results
this is still not accurate..I should obtain 1.67 Volts or 1670 mV in the vout register.
If you could assist me with the troubleshooting I would greatly appreciate it; thank you for the help!
Regards,
Jonathan
Jonathan Velez said:this is still not accurate..I should obtain 1.67 Volts or 1670 mV in the vout register.
Try vout as 32bit integer.
I noticed that in all of your screen shots, the address of your variable "vout" is at 0x004400. Isn't that Flash memory?
-OCY
0x004400 is indeed the start of flash in a MSP430F5528. The other thing I notice from the screen shots is that both the vout and results variables are reported at the same address of 0x004400.old_cow_yellow said:I noticed that in all of your screen shots, the address of your variable "vout" is at 0x004400. Isn't that Flash memory?
If the problem occurs using a MSP430 compiler v4.2.x and an output format of "eabi (ELF)" then it might be the same problem I reported in CCS 5.5 debugger shows incorrect address for C++ class given static storage allocation in main. The problem in the referenced thread was that the CCS debugger was unable to correct resolve the address of variables from the debug information generated by the compiler.
The attached project also shows the problem, with the static variables from the ISR function placed in main. 7635.msp430_statics_in_main.zip. It was generated in CCS 5.5 with MSP430 compiler v4.2.3 set to an output format of "eabi(ALF).
In the debugger the following screen shot shows the index and sum_adc_data variables have been correctly resolved to their address in RAM, but the results and vout variables have both been resolved to the incorrect address of 0x004604 in flash (which is the address in flash of main):
When the expression view was used to cast the RAM address where the vout variable really is (from the linker map file) the correct value was displayed. i.e. the floating point calculation has been performed correctly on the target and the problem is that the CCS debugger is not displayed the correct value of the vout (and results) variables.
**Attention** This is a public forum