Jump to content
43oh

Full-duplex software UART for launchpad


Recommended Posts

So this code snippet springs forth from my desire to use a terminal emulator ( I like putty best ) with my launchpad via the built-in COM port. Simple I think, someone must have already done this by now, no? Well, trying to find a working example for the launchpad led me down a lot of dead ends with nothing that worked well. I did find examples that were half-duplex and ones that required more Timer features than you find on the msp430g2231. Unfortunately, none of them fit my requirements.

 

My goal was to find something that would allow me to use higher DCO clock speeds such as 16MHZ. I also wanted to be able to run reliably with 115k baud rates, so that I can connect a serial to TCP proxy and make my launchpad web enabled.

 

I've implemented something here that meets both of those goals. Well sort of. I discovered that the COM port on the launchpad will only work up to 9600 baud. However, you can disconnect the jumpers and plug your RX/TX lines into an FT232RL device and get higher speeds. It also works well if your goal is to interface to some other device via TTL level RS232, say a GPS device.

 

You can find the code here:

 

https://github.com/RickKimball/msp430softserial

 

Because everything is better with pictures, I took a snapshot of the RX line receiving the character 'U' at 9600 baud. 'U' is unique in that it forms a perfect clock wave 0 10101010 1 when you add the stop and start bits. The green line is the RX line, the red line is me toggling a debug pin inside of the RX ISR routine. I used a program called Soundcard Oscilloscope that helped me dial in the proper timing so that I was sampling in the center of each data bit. http://www.zeitnitz.de/Christian/scope_en

 

242ah3o.gif

 

In the picture above, you'll notice that the first red crossing takes longer than the other samplings, that is because we just ignore the value of the start bit and start sampling in the center of the first data bit.

 

To use and test the code, download it from github and bring it into CCS. Once it is running figure out which COM port your launchpad is using and connect to it with a terminal emulator like putty or minicom using 9600 baud. The default configuration expects you to have soldered a 32.768k crystal to the launchpad board. It uses the crystal to calibrate the DCO for a higher MHZ speed. Don't worry, I don't write it to flash, I just calibrate it and use it. However, you can edit the config.h to modify the baud rate and MCLK speed. You can even run it at the default MCLK speed. See the config.h file comments for more information.

 

I think I've commented the code fairly well. However, this is actually my first published project with the MSP430 launchpad so comments are welcome. So enjoy!

 

-rick

Link to post
Share on other sites

Very nice. Thanks for taking the time to comment and write it all up. This will certainly open up possibilities.

Looking forward to see your Launchpad web enabled.

 

Looks like this is your post, so welcome to the forums. Add a few replies more and you should be able to enter this into the April POTM contest.

Link to post
Share on other sites

This is great! For some reason, I was under the false impression that Launchpad didn't have serial communications through USB. I feel like a kid with a new toy! Thanks!

 

 

P.S. Just a heads up, I initially plugged the LP into a USB hub and the echo didn't work. Connecting directly to my box fixed the issue.

Link to post
Share on other sites

If you don't have a crystal soldered in, you can use the factory 1MHZ precalibrated values

if you modify config.h to something like this:

 

#undef CALIBRATE_DCO       // don't calibrate
#define F_CPU 1000000      // use factory default 1MHZ calibrated DCO
#define BAUD_RATE 4800

 

In main.c modify the 16MHZ to 1MHZ

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

 

I would start with 4800 baud instead of 9600 using the factory calibration. If that works bump it up to 9600.

Also, You can always hand modify the DCO values to make it faster or slower. The works best if you have

a way to measure the SMCLK (output on P1.4) using a multimeter or oscope.

 

-rick

Link to post
Share on other sites

Hi Rick,

 

Coming accross your code pusched my curiosity. I ran it successfully at 4800 baud through hyperterminal by modifying the code as described above. I have an old garmin gps antenna laying around that I would like to connect to my launchpad and receive nmea data. For now, I'm trying to store the text received from the terminal (or at least the first 16 characters) into a variable and it just doesn't work. This is what I did:

while(1){
            nbr = 0;
    if ( !SoftSerial_empty() ) {
        while( (c=SoftSerial_read()) != -1)&&(nbr < 16)) {
	        InputText[nbr] = (char)c;
                      	nbr++;
	  	SoftSerial_xmit((uint8_t)c);
        }
    }
}

I basically want to store the equivalent character in the string before retransmission to the hyperterminal. I declared InputText and nbr as a volatile variables. What am I doing wrong? what am I forgetting?

Link to post
Share on other sites
For now, I'm trying to store the text received from the terminal (or at least the first 16 characters) into a variable and it just doesn't work.

 

By, "it just doesn't work," I assume you mean the echo is still working, but it's not storing to the array correctly.

 

I think what might be happening is that you send a character from terminal, the program moves into that while loop, stores the character to array index 0, and then the loop is repeats. If there isn't already another character waiting, SoftSerial_read() returns -1, the loop exits, and nbr is reinitialized to 0. Next time you send a char, you just overwrite the character you already have in array index 0, when you wanted to place it into array index 1. I actually have some code for something similar.

 

while(1){
         while(SoftSerial_empty()){  // software wait for serial
               // do something
         }
         // we got a char
         while(dispStr[stringIndex - 1] != 13){  // keep adding characters to the array until we get char 13 (line feed)
	if ( !SoftSerial_empty() ) {
            while((c=SoftSerial_read()) != -1) {
                 SoftSerial_xmit((uint8_t)c);
                 dispStr[stringIndex] = c;
                 stringIndex++;
             }
         }
       }
dispStr[stringIndex - 1] = 0;     // terminate string with null char (replace line feed)
stringIndex = 0;
}

 

You could replace "while(dispStr[stringIndex - 1] != 13)" with "while(stingIndex < 16)". There are some ways to clean this example up, but it was just something I had thrown together for another project. I does work for me.

Link to post
Share on other sites

Thanks NatureTM,

 

I really appreciate the help. I used your snippet and adapted it to my code and it finally stores the string before echoing back to the terminal. Will keep you posted and will ask more questions as I'm going forward.

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