Jump to content
username

G2553 Hardware UART "Hello World" Example

Recommended Posts

A simple well documented hardware uart "Hello World" example.
Updated, thanks for member comments 3/13/13

 

Notes:

This code is for launchpad rev 1.5

This is hardware UART, your launchpad jumpers must be set for hardware UART

The TI TUSB3410 is a TERRIBLE usb-> UART chip and is very buggy on WIN7 64bit. If your still having issues, it could be a driver issue. Try on XP or use a different USB -> serial device.

 

 

//Nate Zimmer UART example
// Press button to print hello to terminal

#include  <msp430g2553.h> // System define for the micro that I am using

#define RXD        BIT1 //Check your launchpad rev to make sure this is the case. Set jumpers to hardware uart.
#define TXD        BIT2 // TXD with respect to what your sending to the computer. Sent data will appear on this line
#define BUTTON    BIT3

void UART_TX(char * tx_data);            // Function Prototype for TX

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;         // Stop Watch dog timer

  BCSCTL1 = CALBC1_1MHZ;            // Set DCO to 1 MHz
  DCOCTL = CALDCO_1MHZ;

  P1DIR &=~BUTTON;                  // Ensure button is input (sets a 0 in P1DIR register at location BIT3)

  P1OUT |=  BUTTON;                 // Enables pullup resistor on button
  P1REN |=  BUTTON;

  P1SEL = RXD + TXD ;                // Select TX and RX functionality for P1.1 & P1.2
  P1SEL2 = RXD + TXD ;              //

  UCA0CTL1 |= UCSSEL_2;             // Have USCI use System Master Clock: AKA core clk 1MHz

  UCA0BR0 = 104;                    // 1MHz 9600, see user manual
  UCA0BR1 = 0;                      //

  UCA0MCTL = UCBRS0;                // Modulation UCBRSx = 1
  UCA0CTL1 &= ~UCSWRST;             // Start USCI state machine

  while(1)                          // While 1 is equal to 1 (forever)
  {
      if(!((P1IN & BUTTON)==BUTTON)) // Was button pressed?
      {
          UART_TX("Hello World! \r\n");  // If yes, Transmit message & drink beer
          __delay_cycles(100000); //Debounce button so signal is not sent multiple times
      }
  }

}

void UART_TX(char * tx_data) // Define a function which accepts a character pointer to an array
{
    unsigned int i=0;
    while(tx_data[i]) // Increment through array, look for null pointer (0) at end of string
    {
        while ((UCA0STAT & UCBUSY)); // Wait if line TX/RX module is busy with data
        UCA0TXBUF = tx_data[i]; // Send out element i of tx_data array on UART bus
        i++; // Increment variable for array address
    }
}

Share this post


Link to post
Share on other sites

Thanks for this. Very useful. I've got it running with my launchpad (but had to switch TX and RX on the jumpers). For some reason my own code that looked very similar didn't work. I also couldn't get the TI example code to work.

 

Is it ok to integrate this code into my projects on github and make it BSD? I'll put your name in the source file.

Share this post


Link to post
Share on other sites

By all means! Hence why it is here!

 

Glad it was of some use to somebody. Now as a few people may point out, this isn't the fastest and most efficient way to do UART but it is certainly enough to get by for most practical applications.

 

Also happy to hear you got it to work on the launchpad. I have yet to try it on there yet because I refuse to spend another moment trying to get that thing to USB-->serial IC to work.

Share this post


Link to post
Share on other sites

I had the same problem with the switched TX/RX pins on the launchpad. It took me a while to figure that one out...

 

I wrote my own library for the G2533, but should also work for the C2553.

The main difference is the addition of a uart_write_escaped function, which is useful while sending data of different lengths (that way you can have start/end bytes, and if your data contains that byte, it escapes it.)

It also supports a callback function so you can have input processing functions when you receive data.

 

It's still a work in progress though...

 

https://github.com/alvarop/msp430-cc250 ... lib/uart.c

Share this post


Link to post
Share on other sites

@alvarop

 

I am an MSP430 newbee, so in layman's terms can you

explain your receive callback function? There are

SPI code in the functions. :?:

 

Also, how do you use the following functions in an application?:

uart_write_escaped()

hex_to_string()

Share this post


Link to post
Share on other sites

Anytime a packet is received, an interrupt happens and an interrupt service routine(ISR) is called. This ISR gets the packet from the CC2500. Since people want to do different things with the packets, I chose not to process packets in the ISR.

The callback function is called after a packet is received and is given the actual packet to process.

What you do is come up with your own packet processing function and tell the cc2500 library about it. That way it knows who tocall when a packet is received.

 

The uart_write_escaped() is more for sending whole packets through the serial peripheral to the computer. Normally you just send a stream of bytes. Unfortunately, there is no way for the computer to know when a stream of data begins or ends. This function uses the 0x7E byte as a start and end of packets. This way, the receiver knows when to begin and end capturing data.

If your data contains a 0x7E, that might confuse the receiver, so you must escape it by preceding it with a 0x7D and modifying it. The receiver must be aware of this to process it accordingly.

 

The hex_to_string function was just for debugging. When you want to display a value, you usually use printf(). Unfortunately, printf takes a lot of cycles to format the data, and if you're doing time-sensitive stuff, you can't afford the delay. In cases where you don't have full debugging capability, you might want to print out the values of some registers or variables. the hex_to_string() function converts a value to a hexadecimal string.

Share this post


Link to post
Share on other sites

Hi,

 

First of all, thank you for sharing the code.

I am new to microcontroller, and studying them mostly from the internet online. Could you please post an the schematics as well, it will be very helpful for me.

 

Ssaha

Share this post


Link to post
Share on other sites

Hi,

 

First of all, thank you for sharing the code.

I am new to microcontroller, and studying them mostly from the internet online. Could you please post an the schematics as well, it will be very helpful for me.

 

Ssaha

It's the standard Hardware Uart pinout. P1.1 is RXD, P1.2 is TXD, P1.3 is the button. P1.6 is the green status led.

Share this post


Link to post
Share on other sites

You can concatenate the "hello world" and "\r\n" strings to make it "hello world\r\n". Also, almost all terminal applications do not require '\r', so you could just use "hello world\n" as well.

 

A little background: the character '\n' is short for "newline" which is ascii character 10. '\r' is short for 'carriage return', which is ascii character 13. UNIX machines only use newline, while macs used to use only carriage return, dos/windows uses both.

The backslash means the next character is an escaped character, hence the 'n' in '\n' bears a special meaning. Would you want to output a backslash itself, you'd write '\\'.

Note again, that escape characters are one character, you need just one char to store '\n', as it is translated at compile time to the actual newline character. The length of the string "hello world\r\n" is 14 bytes; 5 for hello, 1 for the space, 5 for world, 1 for '\r', 1 for '\n' and one for the implicit '\0', which indicates that this is the end of the string.

 

if( (BIT3 & P1IN)==0)
if((P1IN & BIT3)==0)
if(!(P1IN&BIT3))

Do all mean the same, which is "do the following if the fourth bit of P1IN is equal to zero". Which is P1.3 on the launchpad and is thus connected to the left switch.

Share this post


Link to post
Share on other sites

Hi Nathan

 

Thanks for posting this code. It worked as advertised.

 

There are however several small comments I would like to add.

 

On launchpad 1.5 the p1.3 switch requires pin pulup to be enabled:

 

    P1OUT |=  Button;
    P1REN |=  Button;                   // enable resistive pullup on switch
 

 

message_num = (int)message[i]; //Cast string char into a int variable
UCA0TXBUF = message_num; // write INT to TX buffer

 
In the above code the 2 lines can be simplified to : UCA0TXBUF = message;   // write string char to TX buffer

 

 

Also your red Error LED is not defined as an output.

 

Peter

Share this post


Link to post
Share on other sites

Thanks for sharing. I do have some questions though.

In your TX, you have an infinite while with a conditional break, why not relace it with a conditional while?

while(1)
{
  if(message[i]==0) // If end of input string is reached, break loop. 
  {
    break;
  }
  ...
}

// Could also be, and is more intuitive and readable
while(message[i] != 0)
{
  ...
}

Second, you have a hard delay to "wait for the byte to be sent", you'd better wait for the transmission to be done.

message_num = (int)message[i]; //Cast string char into a int variable
UCA0TXBUF = message_num; // write INT to TX buffer
i++; // increase string index
__delay_cycles(10000); //transmission delay

// Would better be
UCA0TXBUF = message[i]; // No need to cast to integer; we want to write chars
i++; // increase string index
while(!(IFG2 & UCA0TXIFG)); // Wait until UART is done

Even better to go to LPM0 and let an interrupt wake you when the UCA0TXIFG gets high. But I understand that may be a little to complex for now.

// Add this in USCI setup, __above__ UCA0CTL1 &= ~UCSWRST;
IE2 |= UCA0TXIE; // Enable transmit interrupt

// Replace __delay_cycles(10000); or while(!(IFG2 & UCA0TXIFG)); with
LPM0; // Go to low power mode

// Add this to the bottom of your program
#pragma vector=USCIAB0TX_VECTOR
__interrupt USCIAB0TX_ISR(void)
{
  __bic_status_register_on_exit(LPM0_bits);
}

Share this post


Link to post
Share on other sites

Thanks for this. Just what I needed. My trimmed down version of your TX routine:

void TX(char *tx_message)
{
	unsigned int i=0; //Define end of string loop int

	while(tx_message[i]!=0 && i < 50)
	{
		while(!(IFG2 & UCA0TXIFG)); // Wait until UART is ready
		UCA0TXBUF = (int)tx_message[i++]; // write character to TX buffer
	}
}

 

No copying of the string buffer.

Checking if the UART is ready before sending rather than after.

Combining a few lines (incrementing i, casting and sending).

Combining the length check with the while loop. (I didn't bother with the error output.)

 

This works for me using the Launchpad's USB UART. I'm using a v1.4 Launchpad so had to cross over the RX and TX lines with some F/F jumper wires to get the hardware UART working. (On a v1.5 board you can just turn the existing jumpers 90 degrees.).

This thread explains it all - http://forum.43oh.com/topic/584-msp430g2553-usci-hardware-uart/

Share this post


Link to post
Share on other sites

I've been using this from TI for all the msp430 series. Works pretty well. Just add itoa and ftoa functions and you're set.

 

// tx function borrowed from TI's virtual_com_cmds.c void 
TXString( char* string, int length ) 
{ 
   int pointer; 
   for( pointer = 0; pointer < length; pointer++) 
   { 
      volatile int i; UCA0TXBUF = string[pointer]; 
      while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? 
   } 
}
 

EDIT: fixed code tags. Post was from Tapatalk...

Edited by gwdeveloper

Share this post


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...