username 198 Posted January 8, 2012 Share Posted January 8, 2012 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 } } soapbox, bluehash, turd and 7 others 10 Quote Link to post Share on other sites
larsie 121 Posted January 13, 2012 Share Posted January 13, 2012 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. Quote Link to post Share on other sites
username 198 Posted January 14, 2012 Author Share Posted January 14, 2012 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. Quote Link to post Share on other sites
larsie 121 Posted January 14, 2012 Share Posted January 14, 2012 Thanks. Works for me, so I'm happy... Quote Link to post Share on other sites
alvarop 14 Posted January 17, 2012 Share Posted January 17, 2012 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 gwdeveloper and GeekDoc 2 Quote Link to post Share on other sites
MSP430Andy 16 Posted January 23, 2012 Share Posted January 23, 2012 @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() Quote Link to post Share on other sites
alvarop 14 Posted January 23, 2012 Share Posted January 23, 2012 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. MSP430Andy 1 Quote Link to post Share on other sites
sashagn 0 Posted January 23, 2013 Share Posted January 23, 2013 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 Quote Link to post Share on other sites
cde 334 Posted January 23, 2013 Share Posted January 23, 2013 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. Quote Link to post Share on other sites
pine 140 Posted January 23, 2013 Share Posted January 23, 2013 Thank you for the code. For this line: if( (BIT3 & P1IN)==0) Does it mean capturing button press? Quote Link to post Share on other sites
roadrunner84 466 Posted January 23, 2013 Share Posted January 23, 2013 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. Quote Link to post Share on other sites
PeterD 1 Posted February 8, 2013 Share Posted February 8, 2013 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 variableUCA0TXBUF = 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 Quote Link to post Share on other sites
roadrunner84 466 Posted February 8, 2013 Share Posted February 8, 2013 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); } Quote Link to post Share on other sites
Fred 453 Posted March 13, 2013 Share Posted March 13, 2013 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/ Quote Link to post Share on other sites
gwdeveloper 275 Posted March 14, 2013 Share Posted March 14, 2013 (edited) 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 March 14, 2013 by gwdeveloper Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.