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.

UART doesn't work correctly after ADC convertion



I write this code to set up the communication between msp430 launchpad and PC. First  I send two bytes to MSP430 from tera term. If the two byes are 0x31,0x30, start the ADC convertion. After finishing convertion, send ADC convertion result back to PC(tera term).


When I send data from PC to MSP430, the UART works well. However, after sentence " while (!(ADC10IFG & ADC10CTL0));", the UART doesn't work well any more. When msp430 send 3 bytes, PC only receive 2 bytes and the value PC received is not equal to the bytes msp430 send.

Could you please tell me what could be the problem? Thanks a lot!!!

int main(void)
{
  a=x=i=0;
  Log1 = (void *) 0x1000;
  Address = (char) 0x01;
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

  ADC10CTL1 = ADC10DIV_0 + INCH_10 + SHS_1 + CONSEQ_2;  // TA trig., rpt, A10
  ADC10CTL0 = SREF_1 + ADC10SHT_3 + REF2_5V + ADC10IE + REFON + ADC10ON;
  if (CALBC1_1MHZ==0xFF)                    // If calibration constant erased
  {
    while(1);                               // do not load, trap CPU!!
  }
  DCOCTL = 0;                               // Select lowest DCOx and MODx settings
  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO
  DCOCTL = CALDCO_1MHZ;
  P1DIR = BIT0 + BIT6;
  P1SEL = BIT1 + BIT2 ;                     // P1.1 = RXD, P1.2=TXD
  P1SEL2 = BIT1 + BIT2 ;                    // P1.1 = RXD, P1.2=TXD
  UCA0CTL1 |= UCSSEL_2;                     // SMCLK
  UCA0BR0 = 104;                            // 1MHz 9600
  UCA0BR1 = 0;                              // 1MHz 9600
  UCA0MCTL = UCBRS0;                        // Modulation UCBRSx = 1
  UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
  IE2 |= UCA0RXIE;                          // Enable USCI_A0 RX interrupt
  IE2 &= ~UCA0TXIE;


  __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0, interrupts enabled

}

//  Echo back RXed character, confirm TX buffer is ready first
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
  Received[i] = UCA0RXBUF;
  i++;
  if(i==2)
  {
      i = 0;
      if(Received[1] == 0x31 && Received[0] == 0x30)
      {
          flash_eraseWord(Log1);
          Log1++;
          b++;
          flash_eraseWord(Log1);
          Log1 = (void*) 0x1000;
           TACCTL1 = OUTMOD_4;                       // Toggle on EQU1 (TAR = 0)
          TACTL = TASSEL_2 + MC_2;                  // SMCLK, cont-mod
          ADC10CTL0 |= ENC;
           while (!(IFG2 & UCA0TXIFG));
           UCA0TXBUF = Address;
          while (!(ADC10IFG & ADC10CTL0));
          FirstADCVal = ADC10MEM;

          ADC10CTL0 &= ~ENC;
          Byte1 = (char) (FirstADCVal >> 8);
          Byte0 = (char) FirstADCVal;
          flash_writeWord(Log1, Byte0);
          Log1++;
          flash_writeWord(Log1, Byte1);
          Log1 = (void*) 0x1000;

          while (!(IFG2 & UCA0TXIFG));
           UCA0TXBUF = Byte0;
           while (!(IFG2 & UCA0TXIFG));
            UCA0TXBUF = Byte1 ;
        LPM0_EXIT;
      }
  }
  a++;
}


  • ISR is only for related peripheral data processing. ISR processing shall be done as quickly as possible. Don't do ADC and flash erase/write stuff _inside_ usart ISR. Instead signal (currently nonexistant) main loop about RX char and do ADC/flash stuff there.

**Attention** This is a public forum