Jump to content
43oh

GPS + MSP430G2452 UART Problem


Recommended Posts

Hello,

 

I am using the example code from TI for UART at 9600baud.

 

I have connected a GPS receiver and I'm trying to get the NMEA data from the receiver on a serial monitor.

 

However the received NMEA messages are degraded (and I can't use any GPS Software), for example:

 

Degraded:

$GPRMC,V,,,,,,,,,N*3

$GPTG,,,,,,,,N*0

$GPGS,A,1,,,,,,,,,,,99.9,99.9,99.9930

$GGSV,1,,02,17,,26,3,,,33*A

$GPLL,,,,,V,N*6

 

Correct:

$GPRMC,,V,,,,,,,,,,N*53

$GPVTG,,,,,,,,,N*30

$GPGGA,,,,,,0,00,99.99,,,,,,*48

$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30

$GPGSV,1,1,00*79

$GPGLL,,,,,,V,N*64

 

The only correct message i'm receiving is the $GPRMC one (witch is pretty neat; I can read the coordinates :D).

 

Do you know why am I having this problem? Could you please, please help me?

 

Thank you very much,

Octav

 

Here's the code:

//******************************************************************************
//  MSP430G2xx2 Demo - Timer_A, Ultra-Low Pwr UART 9600 Echo, 32kHz ACLK
//
//  Description: Use Timer_A CCR0 hardware output modes and SCCI data latch
//  to implement UART function @ 9600 baud. Software does not directly read and
//  write to RX and TX pins, instead proper use of output modes and SCCI data
//  latch are demonstrated. Use of these hardware features eliminates ISR
//  latency effects as hardware insures that output and input bit latching and
//  timing are perfectly synchronised with Timer_A regardless of other
//  software activity. In the Mainloop the UART function readies the UART to
//  receive one character and waits in LPM3 with all activity interrupt driven.
//  After a character has been received, the UART receive function forces exit
//  from LPM3 in the Mainloop which configures the port pins (P1 & P2) based
//  on the value of the received byte (i.e., if BIT0 is set, turn on P1.0).

//  ACLK = TACLK = LFXT1 = 32768Hz, MCLK = SMCLK = default DCO
//  //* An external watch crystal is required on XIN XOUT for ACLK *//  
//
//               MSP430G2xx2
//            -----------------
//        /|\|              XIN|-
//         | |                 | 32kHz
//         --|RST          XOUT|-
//           |                 |
//           |   CCI0B/TXD/P1.1|-------->
//           |                 | 9600 8N1
//           |   CCI0A/RXD/P1.2|<--------
//
//  D. Dang
//  Texas Instruments Inc.
//  December 2010
//  Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10
//******************************************************************************

#include "msp430g2452.h"

//------------------------------------------------------------------------------
// Hardware-related definitions
//------------------------------------------------------------------------------
#define UART_TXD   0x02                     // TXD on P1.1 (Timer0_A.OUT0)
#define UART_RXD   0x04                     // RXD on P1.2 (Timer0_A.CCI1A)

//------------------------------------------------------------------------------
// Conditions for 9600 Baud SW UART, SMCLK = 1MHz
//------------------------------------------------------------------------------
#define UART_TBIT_DIV_2     (1000000 / (9600 * 2))
#define UART_TBIT           (1000000 / 9600)

//------------------------------------------------------------------------------
// Global variables used for full-duplex UART communication
//------------------------------------------------------------------------------
unsigned int txData;                        // UART internal variable for TX
unsigned char rxBuffer;                     // Received UART character

//------------------------------------------------------------------------------
// Function prototypes
//------------------------------------------------------------------------------
void TimerA_UART_init(void);
void TimerA_UART_tx(unsigned char byte);
void TimerA_UART_print(char *string);

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

   DCOCTL = 0x00;                          // Set DCOCLK to 1MHz
   BCSCTL1 = CALBC1_1MHZ;
   DCOCTL = CALDCO_1MHZ;

   P1OUT = 0x00;                           // Initialize all GPIO
   P1SEL = UART_TXD + UART_RXD;            // Timer function for TXD/RXD pins
   P1DIR = 0xFF & ~UART_RXD;               // Set all pins but RXD to output
   P2OUT = 0x00;
   P2SEL = 0x00;
   P2DIR = 0xFF;

   __enable_interrupt();

   TimerA_UART_init();                     // Start Timer_A UART
   TimerA_UART_print("G2xx2 TimerA UART\r\n");
   TimerA_UART_print("READY.\r\n");

   for (;
   {
       // Wait for incoming character
       __bis_SR_register(LPM0_bits);

       // Update board outputs according to received byte
       /*
       if (rxBuffer & 0x01) P1OUT |= 0x01; else P1OUT &= ~0x01;    // P1.0
       if (rxBuffer & 0x02) P1OUT |= 0x08; else P1OUT &= ~0x08;    // P1.3
       if (rxBuffer & 0x04) P1OUT |= 0x10; else P1OUT &= ~0x10;    // P1.4
       if (rxBuffer & 0x08) P1OUT |= 0x20; else P1OUT &= ~0x20;    // P1.5
       if (rxBuffer & 0x10) P1OUT |= 0x40; else P1OUT &= ~0x40;    // P1.6
       if (rxBuffer & 0x20) P1OUT |= 0x80; else P1OUT &= ~0x80;    // P1.7
       if (rxBuffer & 0x40) P2OUT |= 0x40; else P2OUT &= ~0x40;    // P2.6
       if (rxBuffer & 0x80) P2OUT |= 0x80; else P2OUT &= ~0x80;    // P2.7
       */        


       // Echo received character
       TimerA_UART_tx(rxBuffer);
   }
}
//------------------------------------------------------------------------------
// Function configures Timer_A for full-duplex UART operation
//------------------------------------------------------------------------------
void TimerA_UART_init(void)
{
   TACCTL0 = OUT;                          // Set TXD Idle as Mark = '1'
   TACCTL1 = SCS + CM1 + CAP + CCIE;       // Sync, Neg Edge, Capture, Int
   TACTL = TASSEL_2 + MC_2;                // SMCLK, start in continuous mode
}
//------------------------------------------------------------------------------
// Outputs one byte using the Timer_A UART
//------------------------------------------------------------------------------
void TimerA_UART_tx(unsigned char byte)
{
   while (TACCTL0 & CCIE);                 // Ensure last char got TX'd
   TACCR0 = TAR;                           // Current state of TA counter
   TACCR0 += UART_TBIT;                    // One bit time till first bit
   TACCTL0 = OUTMOD0 + CCIE;               // Set TXD on EQU0, Int
   txData = byte;                          // Load global variable
   txData |= 0x100;                        // Add mark stop bit to TXData
   txData <<= 1;                           // Add space start bit
}

//------------------------------------------------------------------------------
// Prints a string over using the Timer_A UART
//------------------------------------------------------------------------------
void TimerA_UART_print(char *string)
{
   while (*string) {
       TimerA_UART_tx(*string++);
   }
}
//------------------------------------------------------------------------------
// Timer_A UART - Transmit Interrupt Handler
//------------------------------------------------------------------------------
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A0_ISR(void)
{
   static unsigned char txBitCnt = 10;

   TACCR0 += UART_TBIT;                    // Add Offset to CCRx
   if (txBitCnt == 0) {                    // All bits TXed?
       TACCTL0 &= ~CCIE;                   // All bits TXed, disable interrupt
       txBitCnt = 10;                      // Re-load bit counter
   }
   else {
       if (txData & 0x01) {
         TACCTL0 &= ~OUTMOD2;              // TX Mark '1'
       }
       else {
         TACCTL0 |= OUTMOD2;               // TX Space '0'
       }
       txData >>= 1;
       txBitCnt--;
   }
}      
//------------------------------------------------------------------------------
// Timer_A UART - Receive Interrupt Handler
//------------------------------------------------------------------------------
#pragma vector = TIMER0_A1_VECTOR
__interrupt void Timer_A1_ISR(void)
{
   static unsigned char rxBitCnt = 8;
   static unsigned char rxData = 0;

   switch (__even_in_range(TA0IV, TA0IV_TAIFG)) { // Use calculated branching
       case TA0IV_TACCR1:                        // TACCR1 CCIFG - UART RX
           TACCR1 += UART_TBIT;                 // Add Offset to CCRx
           if (TACCTL1 & CAP) {                 // Capture mode = start bit edge
               TACCTL1 &= ~CAP;                 // Switch capture to compare mode
               TACCR1 += UART_TBIT_DIV_2;       // Point CCRx to middle of D0
           }
           else {
               rxData >>= 1;
               if (TACCTL1 & SCCI) {            // Get bit waiting in receive latch
                   rxData |= 0x80;
               }
               rxBitCnt--;
               if (rxBitCnt == 0) {             // All bits RXed?
                   rxBuffer = rxData;           // Store in global variable
                   rxBitCnt = 8;                // Re-load bit counter
                   TACCTL1 |= CAP;              // Switch compare to capture mode
                   __bic_SR_register_on_exit(LPM0_bits);  // Clear LPM0 bits from 0(SR)
               }
           }
           break;
   }
}
//------------------------------------------------------------------------------

Link to post
Share on other sites

Looks like you are missing out some characters. I think that its possible too much might be going on since you are receiving, lighting an led, and transmitting every time. I assume the unit doesn't have much of a delay between each character.

 

I would recommend trying some of the following:

Changing the clock to 16 Mhz and fixing the UART_TBIT definitions to reflect this.

Store as many characters as you can at receipt in a buffer - as opposed to a single character.

Remove the if logic that sets the pins high on a receipt.

Link to post
Share on other sites

Thanks for the reply!

 

I still can't figure it out. Here's what I did so far:

Changing the clock to 16 Mhz and fixing the UART_TBIT definitions to reflect this.

I had already tried changing the DCO, and I get better messages, but still not correct ones. If they're not exactly right, the GPS software doesn't know how to interpret them. I think I'm losing a character at almost periodical intervals(In bold what I'm losing):

 

$GPRMC,10212.00,V,,,,,,31051,,,N*70

$GPVTG,,,,,,,,N*30

$GPGGA,12912.00,,,,0,00,9.99,,,,,,*6F

$GPGS,A,1,,,,,,,,,,,,9.99,99.9999.99*30new line$GPGSV,2,,08,05,,31,12,,,2,14,,,22,6,,,23*72

$GPGSV,,2,08,17,,21,24,,,7,27,,,2632,,,24*7something in the check-sum; it should be 2 characters long

$GPGLL,,,,10291.00,V,N*4something in the check-sum; it should be 2 characters long

 

 

Store as many characters as you can at receipt in a buffer - as opposed to a single character.

 

I can only store about 200 characters into a string, and that's not enough for all of the messages. (I want to mention that I'm a beginner with MSP430) I don't understand why I can't declare a bigger string in the main function? I don't get any error when doing that, nor warnings, but the program won't print anything.

 

Remove the if logic that sets the pins high on a receipt.

 

Already did that, but I don't think it has any effect.

 

 

Do you have any other suggestions?

 

Thank you very much,

Octav

Link to post
Share on other sites

I can only store about 200 characters into a string, and that's not enough for all of the messages. (I want to mention that I'm a beginner with MSP430) I don't understand why I can't declare a bigger string in the main function? I don't get any error when doing that, nor warnings, but the program won't print anything.

 

You can't store much more than 200 characters because 2452 only has 256 bytes of RAM.

 

Although you should be able to do what you want with the 2452 I'd strongly recommend going with a 2553 which will give you a true hardware UART as well as 512 bytes of RAM to play with.

Link to post
Share on other sites
Your factory calibrations could be off. Did you solder the 32khz xtal on the launchpad? Try running the dco flashcal or use the calibration function to set DCO, if so. You could verify your clocks with a scope.

The TI example UART (which he is using) doesn't use the crystal.

 

I can only store about 200 characters into a string, and that's not enough for all of the messages. (I want to mention that I'm a beginner with MSP430) I don't understand why I can't declare a bigger string in the main function? I don't get any error when doing that, nor warnings, but the program won't print anything.

 

If you don't need all of the strings you could attempt to only store the two or three you need? The chip you are using has limited ram - 254 so you will find yourself pushed for space.

Link to post
Share on other sites
Your factory calibrations could be off. Did you solder the 32khz xtal on the launchpad? Try running the dco flashcal or use the calibration function to set DCO, if so. You could verify your clocks with a scope.

The TI example UART ( which he is using) doesn't use the crystal.

 

True, but I used the crystal to calibrate my DCO.

Link to post
Share on other sites
I calibrated the DCO but it still has the same problem.

 

So, as rockets4kids said, the best solution(simplest) for my problem was to change the controllers.

Works beautifully with the G2553 :).

 

Thank you all for your help!

 

I'm just curious about your solution - did you store off the entire output of the GPS unit?

 

Glad to hear it is working now regardless :)

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...