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.

MSP432P401R: MSP432P401R Potentiometer with ADC

Part Number: MSP432P401R

Hi all, the idea of this little program is to be able to read the value of a potentiometer using the ADC of the MSP432P401R. To get a more accurate measurement I calculate 4 values and average them and assign them to the variable 'result_ChannelA6'. I have a couple of doubts actually: I have made two versions of the program where I have changed the function 'configuracionADC' (one setting the registers I am interested in and another where the exact same registers are set, but putting it in another way and by debugging with CCS I see that only the FIRST version works, since the first one I see that 'average_value_A6' is always zero and it is because no value is loaded in ADC14->MEM[5]. What could be happening so that one works and the other does not?

And the other question is, how could the program be improved to make the ADC readings more accurate? I say this because when I rotate the potentiometer and the value I read in the ADC sometimes does not even change and other times it gives a value far from what I think it should give. Thanks in advance!

/* ---------------------------------------------------------- VERSION 1 ------------------------------------------- */

  1. #include "msp.h"
  2. #include <stdint.h>
  3. #include <stdio.h>
  4.  
  5. volatile uint8_t buffer_lleno = 0; // Variable indicating whether we have the 4 measures taken or not yet 
  6. volatile uint16_t valor_promedio_A6 = 0; // Variable that stores the average value of A6
  7.  
  8. // Variable created to avoid taking wrong ADC values due to possible race condition in the ISR:
  9. volatile uint16_t result_ChannelA6 = 0;
  10.  
  11. void configuracionADC(void){
  12.     ADC14->CTL0 |=  0x00000010;      /*  ADC14ON: enable ADC */
  13.     ADC14->CTL0 |= 0x04120380;      
  14.     ADC14->CTL1 =  0x00000020;      /* 12-bit resolution */
  15.     ADC14->MCTL[5] |= 6;            /* select A6 input, single-ended, Vref=AVCC */
  16.     P4SEL1 |= BIT7; // We configure P4.7 as ADC channel A6.
  17.     P4SEL0 |= BIT7;
  18.     ADC14->CTL1 |=  0x00050000; /* convert for mem reg 5 */
  19.     ADC14->CTL0 |= 2; 
  20.     ADC14->IER0 |= 0x00000020; // ADC_IFG upon conv result-ADCMEM0
  21. }
  22.  
  23. void init_interrupciones(void){
  24.     NVIC_EnableIRQ(ADC14_IRQn);
  25.     __enable_irq(); // Enable global interrupt
  26. }
  27.  
  28. void main(void)
  29. {
  30.     WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;     // stop watchdog timer
  31.     configuracionADC();
  32.     init_interrupciones();
  33.  
  34.     ADC14->CTL0 |= 1; /* ADC14SC: Start conversion */
  35.     while(1){
  36.         if(buffer_lleno){
  37.             buffer_lleno = 0;
  38.             ADC14->CTL0 |= 3; /* ADC14SC | ADC14ENC: Enable conversions and start conversions */
  39.         }
  40.     }
  41. }
  42.  
  43. // ADC14 interrupt service routine:
  44. void ADC14_IRQHandler(void) {
  45.     static uint16_t index = 0; // Static type so that each time it enters the ISR the previous value is maintained.
  46.     if (ADC14->IFGR0 & ADC14_IFGR0_IFG5){
  47.         valor_promedio_A6 += ADC14->MEM[5]; /* read conversion result */
  48.         index++;
  49.         if(index == 4){
  50.             ADC14->CTL0 &= ~2; // stop ADC
  51.             buffer_lleno = 1; // We indicate that we already have the 4 measures taken
  52.             result_ChannelA6 = (valor_promedio_A6 >> 2); // To divide by 4 and obtain the average value
  53.             valor_promedio_A6 = 0;
  54.             index = 0;
  55.         }
  56.     }
  57. }

/* ------------------------------------------------ VERSION 2 -------------------------------------------------- */

  1. #include "msp.h"
  2. #include <stdint.h>
  3. #include <stdio.h>
  4.  
  5. volatile uint8_t buffer_lleno = 0; 
  6. volatile uint16_t valor_promedio_A6 = 0; 
  7.  
  8. volatile uint16_t result_ChannelA6 = 0;
  9.  
  10. void configuracionADC(void){
  11.     ADC14->CTL0 |= ADC14_CTL0_ON;     
  12.     ADC14->CTL0 |= ADC14_CTL0_MSC | ADC14_CTL0_CONSEQ_2 | ADC14_CTL0_SSEL_4 | ADC14_CTL0_SHT0_3 | ADC14_CTL0_SHP;  
  13.     ADC14->CTL1 =  ADC14_CTL1_RES_2;     /* 12-bit resolution */
  14.     ADC14->MCTL[0] |= ADC14_MCTLN_INCH_6; 
  15.     P4SEL1 |= BIT7; 
  16.     P4SEL0 |= BIT7;
  17.     ADC14->CTL1 |=  0x00050000; /* convert for mem reg 5 */
  18.     ADC14->CTL0 |= ADC14_CTL0_ENC;  
  19.     ADC14->IER0 |= ADC14_IER0_IE5; // ADC_IFG upon conv result-ADCMEM0
  20. }
  21.  
  22. void init_interrupciones(void){
  23.     NVIC_EnableIRQ(ADC14_IRQn);
  24.     __enable_irq(); // Enable global interrupt
  25. }
  26.  
  27. void main(void)
  28. {
  29.     WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;     // stop watchdog timer
  30.     configuracionADC();
  31.     init_interrupciones();
  32.  
  33.     ADC14->CTL0 |= ADC14_CTL0_SC; /* ADC14SC: Start conversion */
  34.     while(1){
  35.         if(buffer_lleno){
  36.             buffer_lleno = 0;
  37.             ADC14->CTL0 |= ADC14_CTL0_ENC | ADC14_CTL0_SC; 
  38.         }
  39.     }
  40. }
  41.  
  42. // ADC14 interrupt service routine:
  43. void ADC14_IRQHandler(void) {
  44.     static uint16_t index = 0;
  45.     if (ADC14->IFGR0 & ADC14_IFGR0_IFG5){
  46.         valor_promedio_A6 += ADC14->MEM[5]; 
  47.         index++;
  48.         if(index == 4){
  49.             ADC14->CTL0 &= ~ADC14_CTL0_ENC; 
  50.             buffer_lleno = 1; 
  51.             result_ChannelA6 = (valor_promedio_A6 >> 2); 
  52.             valor_promedio_A6 = 0;
  53.             index = 0;
  54.         }
  55.     }
  56. }