Вы находитесь на странице: 1из 44

Half Duplex Software UART on the LaunchPad Before I get into this post, I want to let you all

know that the very basic oscilloscope project is coming; this post is the first in a series which will lead up to the final project. Before you all get too excited though, the scope will be very limited because of the low sample rate we must have. Be prepared to see some cool mini-projects as we work toward our main goal. This blog and the ones which follow, mirror what I have done with the F5528 for my own personal project.

This post is fairly short; this is due to the fact that I will break down the larger project into smaller posts to keep things bite sized and allow you to follow my design process. I think it is very important to learn how to develop in steps when working with a complex design; there are many benefits to doing things this way.

A Part of the Big Picture

Making a software UART which can receive was a clear first step in making sure we can get an ADC to work. In order to see what we are getting with the ADC we need a computer interface, and in order to control the LaunchPad we needed to be able to receive data. In addition to using this in our oscilloscope project, there has been a lot of interest in the community for a software UART which can receive.

Before we go onto looking at the code, I want to discuss the limitations of this specific software UART. I have not tested the overall throughput to see how fast it can go, as such, there will be a lower limit on the bit times regardless of clock speed. Clock speed can be used though to make the whole system run faster. Before we finish the scope project we will be running at 8 or 16 MHz, and sending data over an FTDI chip much faster than the LaunchPads debugging UART allows. For now though I want to keep the baby steps to something everyone can do (with or without the FTDI chip).

Another major limitation of this code is that it can not receiving while sending, and it can not send while receiving. It IS possible to write a software UART which is full duplex, though I will not be designing one; at least for the

foreseeable future.

The Code

The code is posted on github at http://gist.github.com/532047 for those of you who have trouble seeing the embedded code here. I just love github, I do not know what I would do without it.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123

124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149

150 151 152 153 154 155 / ****************************************************************************** * * * Description: This code provides a simple Bi-Directional Half Duplex * * * * * * * Author: Nicholas J. Conn - http://msp430launchpad.com * Email: webmaster at msp430launchpad.com * Date: 08-17-10 ***************************************************************************** */ Software UART. The timing is dependant on SMCLK, which is set to 1MHz. The transmit function is based off of the example code provided by TI with the LaunchPad. This code was originally created for "NJC's MSP430 LaunchPad Blog". Half Duplex Software UART on the LaunchPad

#include #include

"msp430g2231.h" "stdbool.h"

#define

TXD

BIT1

// TXD on P1.1

#define

RXD

BIT2

// RXD on P1.2

#define Bit_time (1MHz/9600)=104 #define

104 52

// 9600 Baud, SMCLK=1MHz // Time for half a bit.

Bit_time_5

unsigned char BitCnt; unsigned int TXByte; called unsigned int RXByte;

// Bit count, used when transmitting byte // Value sent over UART when Transmit() is // Value recieved once hasRecieved is set

bool isReceiving; bool hasReceived;

// Status for when the device is receiving // Lets the program know when a byte is received

// Function Definitions void Transmit(void);

void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT

BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ;

// Set range // SMCLK = DCO = 1MHz

P1SEL |= TXD; P1DIR |= TXD;

P1IES |= RXD; P1IFG &= ~RXD; enabling interrupt P1IE |= RXD;

// RXD Hi/lo edge interrupt // Clear RXD (flag) before // Enable RXD interrupt

isReceiving = false; hasReceived = false;

// Set initial values

__bis_SR_register(GIE);

// interrupts enabled\

while(1) { if (hasReceived) { hasReceived = false; to be transmitted Transmit(); } if (~hasReceived) received __bis_SR_register(CPUOFF + GIE); // LPM0, the ADC interrupt will wake the processor up. This is so that it does not // } } endlessly loop when no value has been Received. // Loop again if another value has been // Clear the flag // If the device has recieved a value

TXByte = RXByte; // Load the recieved byte into the byte

// Function Transmits Character from TXByte void Transmit() { while(isReceiving); CCTL0 = OUT; TACTL = TASSEL_2 + MC_2; // Wait for RX completion // TXD Idle as Mark // SMCLK, continuous mode

BitCnt = 0xA; ST/SP CCR0 = TAR;

// Load Bit counter, 8 bits + // Initialize compare register

CCR0 += Bit_time; TXByte |= 0x100; logical 1) TXByte = TXByte << 1; 0)

// Set time till first bit // Add stop bit to TXByte (which is // Add start bit (which is logical

CCTL0 = CCIS0 + OUTMOD0 + CCIE; // Set signal, intial value, enable interrupts while ( CCTL0 & CCIE ); completion } // Wait for previous TX

// Port 1 interrupt service routine #pragma vector=PORT1_VECTOR __interrupt void Port_1(void) { isReceiving = true;

P1IE &= ~RXD; P1IFG &= ~RXD;

// Disable RXD interrupt // Clear RXD IFG (interrupt flag)

TACTL = TASSEL_2 + MC_2; CCR0 = TAR; CCR0 += Bit_time_5; CCTL0 = OUTMOD1 + CCIE; interrupts

// SMCLK, continuous mode

// Initialize compare register // Set time till first bit // Dissable TX and enable

RXByte = 0; BitCnt = 0x9; }

// Initialize RXByte // Load Bit counter, 8 bits + ST

// Timer A0 interrupt service routine #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A (void) { if(!isReceiving) { CCR0 += Bit_time; if ( BitCnt == 0) { TACTL = TASSEL_2; power consumption) CCTL0 &= ~ CCIE ; } // SMCLK, timer off (for // Disable interrupt // Add Offset to CCR0 // If all bits TXed

else { CCTL0 |= OUTMOD2; if (TXByte & 0x01) CCTL0 &= ~ OUTMOD2; // If it should be 1, set it to 1 TXByte = TXByte >> 1; BitCnt --; } } else { CCR0 += Bit_time; if ( BitCnt == 0) { TACTL = TASSEL_2; (for power consumption) CCTL0 &= ~ CCIE ; // SMCLK, timer off // Disable interrupt // Add Offset to CCR0 // Set TX bit to 0

isReceiving = false;

P1IFG &= ~RXD; (interrupt flag) P1IE |= RXD;

// clear RXD IFG // enabled RXD interrupt

if ( (RXByte & 0x201) == 0x200) the start and stop bits are correct {

// Validate

RXByte = RXByte >> 1; RXByte &= 0xFF; hasReceived = true; } __bic_SR_register_on_exit(CPUOFF); the main while loop continues } else { if ( (P1IN & RXD) == RXD) RXByte |= 0x400; RXByte RXByte = RXByte >> 1; down BitCnt --; } } } view rawmain_UART.cThis Gist brought to you by GitHub.

// Remove start bit // Remove stop bit

// Enable CPU so

// If bit is set? // Set the value in the // Shift the bits

A Quick Explanation of the Code

The code is decently documented, and you all should be familiar with the transmit part of the code; if you aren't, please see this past post where I go over the transmit functionality. I will not really go into detail on all the specific lines of code but I will discuss how the receive code works.

For every byte that is sent over UART there is a start bit which always moves the signal from high to low. Our code recognizes this by throwing an interrupt

on the RXD pin when a signal goes from high to low. It is important to disable this once the receive sequence is started, and it is also just as important to re-enable the interrupt once we are done receiving a byte. Once the interrupt is thrown, the timer and other values are initialized.

Next, the timer interrupt cycles through each bit in a very similar way the transmit function does. The major difference between the two is that instead of shifting the bits out, it reads the RXD pin and sets a bit in the RXByte. This is a bit hard to understand if you have not seen this method being used before. The current bit being read will set or leave cleared the 13th bit in RXByte; the entire byte is then immediately shifted once in order to slowly move the bits into the correct location. After an entire sequence is done all the bits will end up in the correct location.

Finally the stop bit is read, and the timer finishes up. It not only stops the timer and re-enable the interrupt on the RXD pin so we can receive another byte, but it also makes sure the start and stop bits are correct values. If an incorrect value has been received for these bits, the received value is ignored.

The final tricky part of this code, is understanding how the main loop knows a value has been received and how the low power modes work. It wouldn't be an MSP430 project if there wasn't some form of power saving going on :-P.

The main loop will go to sleep every iteration unless there is a value which has just been received, in which case the loop will run again. In the timer code, if the received byte is validated and shown to have no errors, it not only sets the hasReceived flag but also forces the CPU to leave the low power mode, which lets the main loop run and react to the received value.

Conclusions

As always, I hope that this code is something that helps with your projects and is peaks your interest in what is to come.

On a separate note, I am very happy to see the community growing. I have had an increase in viewers and I see more activity on the 43oh forums. I check these forums every few days and do my best to answer any questions, so if you have not joined yet I highly recommend doing so. I also plan on taking a more in depth look at the LaunchPad wiki Learning Community that a TI employee started up a bit ago. There seems to be a good amount of information already present on the site, and there also seems to be a huge potential for growth. I really am grateful to TI for providing us all with support and a large number of resources to get the community going.

So, comment away. Your comments are the fuel which my creative juices run on :-P

IMPORTANT EDIT: There is a small error in the code I presented above. The transmit function is problematic because if you send two bytes in a row the TXByte value would be changed before it is done being transmitted. For now I will write in a quick fix, in the next post I will provide a slightly more efficient solution. The code is updated above. at 5:06 PM Email This BlogThis! Share to Twitter Share to Facebook

Reactions: 56 comments:

justinAugust 18, 2010 at 3:56 AM I may have missed it, but why does the oscilloscope need to be able to receive data?

my idea of the oscilloscope was just to send data to the PC and use a

program to sort the values, and use buttons, with interrupts to change certain values, settings.

Reply

NJCAugust 18, 2010 at 5:28 AM Justin,

Your idea is completely valid and probably easier to implement than using a PC to control the oscilloscope, in addition to displaying the values it reads. The reason I chose to do it this way is so that we have more flexibility and so that no external components are needed.

It really just comes down to personal preference. I would rather control the device with a button click on a computer program, instead of going back and forth between a computer program and hardware buttons. Also this allows us to have more control in the long term; we can have much more complex parameters than a few push buttons would allow.

I do plan on providing an executable with the project for those who do not want to write their own computer applications.

Reply

Gareth WilliamsAugust 18, 2010 at 6:28 AM I'm watching this series with interest. Only since getting my LaunchPad do I now understand the benefit of an oscilloscope to the hobbyist market!

Ultimately, I'd love a completely standalone unit, with it's own LCD rather than a PC driven device. But I have no idea what limitations this would impose aside from the limited flash storage which would have to include

graphical functions.

Reply

justinAugust 19, 2010 at 2:10 AM I see, Your right about the settings, as for the LCD you driven O-scope, I was thinking of picking up one of these http://www.sparkfun.com/commerce/product_info.php?products_id=9484 or it can give some good ideas about how to use an LCD with the O-scope

keep up the good work.

Reply

Juan_CAugust 20, 2010 at 9:11 AM Great code!! I was kind of waiting something like this...I'm busy right now with school but I will try to use this code and to see if i can understand it as soon as I have some time.

Reply

Tabish ChasmawalaAugust 22, 2010 at 8:12 PM Please follow my and spread the word of my new blog:

http://practical-embedded-hacks.blogspot.com/

Reply

NJCAugust 23, 2010 at 3:03 AM First, Tabish, this it not the place to be advertising your blog, I'm sorry. I will not delete the post, but please go to all the forums and post there instead. I am happy to support a fellow blog in the community, but I would like to keep my comment section free of advertisements.

@Gareth Building a standalone oscilloscope can be quite daunting. There is so much that needs to go into it in order to make it useful; precisely controlling a graphic screen is hard to do with a microcomputer. To do this with a microcomputer you would need to seriously reduce your sampling rate to the point where it is not useful. If you are really interested though in making a standalone unit, look into FPGA's. I can help you get started if you want; but be warned, FPGA's are really intense.

@Justin and Gareth I have heard good things about that LCD, but never used one. It could be great for a small project. Both of you, feel free to build a scope with it! Don't let me previous comment hold you back; just know that it will be very hard and very limited in functionality.

@Everyone Thank you for all the comments.

Reply

MegachipAugust 26, 2010 at 7:26 AM Nice work on the Half Duplex Uart NJC. Works perfect, I tried pushing it higher using standard baud rates but no go yet, I did not trace the code to see where it was hanging up.

Thanks for the code, keep it up

Reply

NJCAugust 26, 2010 at 7:44 AM Megachip,

Thank you. You reminded me, there is a problem with the code I should fix in this post. I was going to mention it in the next post, but I should update this one too. In the transmit function we need to either put the while loop at the end, so we do not modify TXByte as it is sending, or put TXByte into a temporary variable. The latter would allow for faster data throughput.

Hope that works for you.

Reply

MegachipAugust 29, 2010 at 8:47 AM Hey NJC, I wanted to note that with the update to the code you can set your terminal to any Baud above 9600 and it works fine. (you can not change the virtual port speed). The speed does not change as far as I can tell but it syncs just fine. I would like to hear your comments on that because I do not know the answer. Thanks my C++ Guru !!!

Reply

NJCAugust 29, 2010 at 10:54 AM Megachip,

I am not sure I understand your question. I am confused since you mention that you verified the software UART at faster speeds than 9600 baud? It seems as if you are still using the LaunchPad's UART interface to test this? It is not possible for the LaunchPad to work faster than 9600 (at least, thats what the documentation says).

I am in no way an expert in VCPs, but I do know that when using the 5528, one does not need to set a baud rate on the VCP at all. If one does set the baud rate it does not matter since it has no effect on the speed at which the device communicates. This is different though for the FTDI chips, which use the baud rate set in the VCP.

What hardware are you using to test this? To be honest I have not tested the upper limits of this code yet, and might not get around to checking it anytime soon. Thanks though for testing the code! Maybe your findings can help me make a better version. Once I know more about your setup I might be able to provide a better answer to your question.

Looking forward to your response. :-) Thanks for the comments

Reply

MegachipAugust 30, 2010 at 7:37 AM I am using the LaunchPads UART, Your Half Duplex software ,RealTerm and Hyperterm. I did not find any magic here, I was just asking a question about terminals and BAUD rate settings. I was confused because we set a baud rate and I expected the terminal to only work at that baud.

Both the Uart programs act the same and I did not realize it till now.

It is ONLY THE SOFTWARE UART , NOT THE VCP.

You can run your terminal baud at any rate above 9600 and it will work but the speed does not change. We are still only going as fast as the VCP can go.

What I do not understand is how the VCP is set to 9600 and our program is set to 9600 yet the terminal works at any given speed 9600 and above. Maybe this is the nature of a Software UART and I have only worked with Hardware UARTS.

I hope that answers your questions.

Reply

GeekDocSeptember 5, 2010 at 4:20 PM @Megachip: It sounds like the terminal programs are just compensating somehow.

@NJC: I really like the new header. Did you take the photos, or find them on TI's site?

-Doc

Reply

NJCSeptember 6, 2010 at 2:58 AM @Megachip

From my experience I think doc is right. I think that the weird behavior is related to what I said in my last post. The LaunchPad might not use the baud rate set in the terminal and determine the baud rate automatically. USB communication does not need a baud rate because of how it works. Sorry I can't provide a better answer, I am no expert on the USB protocol.

@Doc Thank you. :-) I took the photo myself, with my phone. I was going to re-do it with a nicer camera, but never got around to it. I should probably fix the image up a bit. I spent an hour or so making it last weekend since I've been without internet (except at work). That is why it has taken me a while to write up my next post, still no internet at home.

Reply

Joby TaffeySeptember 10, 2010 at 7:20 PM Thanks for the UART code. I've used it in my RPN Calculator and my SPI Explorer programs for Launchpad.

I made changes so that I have getc() and putc(). The code is at:

http://blog.hodgepig.org/articles/000047-rpn/index.html

http://blog.hodgepig.org/articles/000048-spi/index.html

Reply

EfcisOctober 1, 2010 at 10:47 AM Hi NJC et al. !

I got inspiration from your great code, but I'm facing the following issue :

My current launchpad app has to reply to some commands sent by a C++ client application. But when several chars are sent "in a row" by my client app, the Launchpad hasn't time enough to check the command (basically with strcmp) and reply if required.

I guess I can increase the master clock to allow more instructions to be executed once a char has been received (and modify Bit_time and Bit_time_5 accordingly), but how to do that, while keeping the 9600 baud timing with accuracy ?

Reply

NJCOctober 2, 2010 at 8:59 AM Efcis,

If your commands have a known maximum character length which is not too large, you could make a buffer for the incoming values which would allow you to have more time to analyse them, unless you are constantly sending commands. Another option is to change the C++ app if you can, and make the commands smaller.

Changing the clock might do the trick, depending on how large the string commands are. See the comment below to make sure the baud rate is set correctly.

// 9600 Baud, SMCLK=1MHz (1MHz/9600)=104

Also note that this code can not transmit anything while it is receiving. Hope that answers your questions.

Reply

EfcisOctober 2, 2010 at 8:59 PM NCJ,

Thanks for your reply. I already buffer the received characters, but it looks like this process (buffering and checking if the last received char is a CR) take too much time to allow the next char to be received. The only way is to add a delay between two consecutive sent chars (1 ms) in the client, that doesn't satisfy me.

I'm also facing something strange : If I use a SMCLOCK / 2 clock for the timer to decrease the rate to 4800 bauds (to allow more CPU time between two chars), it doesn't work.

I'm doing a simple

TACTL = TASSEL_2 + MC_2 + ID_1;

in the Port_1 interrupt (and in transmit), but it looks like the timings are incorrect ! As I don't own any oscilloscope / DSO, it's hard to figure what's happening exactly.

Any idea ?

Reply

NJCOctober 4, 2010 at 10:24 AM

Hey efcis, Would you mind making a post on the 43oh.com/forum forums on this topic? I'll be able to answer you more in depth there, in addition to there being more people there who can help.

Reply

Fbio PedrosaJanuary 18, 2011 at 12:23 PM Hey NJC,

Nice post/code. Thanks a lot for it.

A question. Is there a way to still use the P1.1 and P1.2 for other purposes (push-button for instance)? Can I poll for button changes in the long-pooling while after interrupts are enabled and before transmission occurs?

Reply

GertrudeFebruary 10, 2011 at 6:23 PM I have successfully run the transmit code from http://www.msp430launchpad.com/2010/07/launchpads-example-projectripped-open.html When I try to run this UART code, I expected that after I sent a character from RealTerm it would be echoed back to RealTerm. This did not happen. I inserted code to toggle the green LED after line # 143 hasReceived = true; This worked as expected. I then inserted code to toggle the red LED when the main while(1) loop is entered. The LED lights up when the program is initially run, but never toggles again. I appears that the code never returns to the while(1) loop and therefore never Transmit()'s. Any suggestions? Hardware:Windows Vista Home Premium 64 SP2 4 gig RAM. LaunchPad Rev

1.4 MSP430G2231 all original, all jumpers left as received. Thanks, Gertrude

Reply

NJCMarch 4, 2011 at 6:58 PM @Fbio - You cannot use the pins that are used for the software UART for anything but UART while the software UART is running unless you do some tricky enabling and disabling of the software UART in your program.

@Gertrude - Have you double checked that the code is the same as my example and double checked all of the wires and connectors? If all else fails and you have a logic analyzer, test the signal to ensure that the baud rate is working correctly.

Reply

venuMarch 16, 2011 at 1:51 PM Great post, i have been banging my head against anything i can find to understand the following line of code.

TXByte = TXByte >> 1;

Where do the bits get shifted to? On to the P1.1 pin? ( which is connected to the PC?)

Please save my head

Reply

NJCMarch 18, 2011 at 12:26 AM Venu, good question, I know this can be hard for people new to embedded programming. You can think of the >> operator like any other mathematical operator, such as + or -. So when you do y = x + 1; y is not equal to x + 1. When you do x = x + 1; x is now equal to itself plus one. So when you do y = x >> 1; y is equal to x shifted to the right once. The lowest bit just disappears (there is another shift in assembly that causes it to go to the highest big, but not in this case).

So for the example in my code, the new TXByte is now equal to itself shifted one bit to the right. 0b0010 now equals 0b0001.

Hope that saved your head!

Reply

RobThePyroMarch 27, 2011 at 2:21 PM Awesome post NJC, I received my Launchpads last week and currently working on a PC USB > RGB LED controller with the launchpad, definitely going to be using some of this code if you dont mind :)

For those of you without scopes, I have version 1 of the following: http://www.seeedstudio.com/depot/dso-nano-v2-p-681.html? cPath=174&zenid=a4454af982f08f8739827a0b629323e6 and I must say I highly recommend it as a beginners/hobbyist scope. Its really not that expensive and it will save you alot of headaches to just go ahead and grab one ;) (when they are in stock again...)

Reply

BloodredMarch 28, 2011 at 1:58 PM Hello NJC, first of all I'd like to say thanks for posting this code, it got me on the right track with my own UART.

There's something I wish to point out though on the receiving part, as it has given me quite some headaches because it wasn't working properly and randomly skipping bit 0 or bit 1 (were read as 0 when they should've been 1) from the byte it was supposed to receive.

In the Port1 ISR, instead of CCR0 = TAR; CCR0 += Bit_time_5; I used CCR0 = TAR + Bit_time_5; and the bit skipping problem was solved. I still can't quite figure out why this was happening as the CCR0 interrupt shouldn't trigger, because it's obviously disabled, but something was definitely not working properly.

Reply

NJCMarch 28, 2011 at 3:20 PM @Rob - use the code all you want! Thats what its there for :-) just put a little blurb in somewhere that points back to my blog.

@Bloodred - interesting find. It could be that you are missing a bit just because of the time the MCU takes to process the Port1 ISR. If you lowered the bit time and half bit time I'm guessing the problem would go away.

Reply

RobThePyroMarch 31, 2011 at 11:04 AM Will of course give credit where credit is due :)

Question: I'm trying to run at speeds faster than 1MHz, such as 4, 8 or even 16MHz to get smoother software pwm.. but this cause's issues with the UART timing since the 1MHz value is reasonably calibrated on the device but trying to run at expected faster speeds gives unpredictable results... have you found a way around this? or just experiment with the bit_time variable via trial and error? sorry if there is an answer to this but I'm unable to Google as I have 9Mb of internet left until tomorrow... The joys of Africa... lol.

Reply

BloodredApril 2, 2011 at 9:23 AM @NJC I don't think it was a timing issue, the change I made shouldn't make much of a difference if any at all. Quite curious, I still can't figure out the reason. I've been using that code in my project extensively and it has been working perfectly, form what I can tell it never misinterprets a received value.

Wouldn't halving bit time effectively double baud rate? I don't need anything faster, 9600 is plenty as my project only has to receive about 80bps tops.

Reply

NJCApril 13, 2011 at 12:03 PM @Rob - I actually never ran into trouble with that since I do not extensively use the G2231, I would sooner use the F2013 (which had calibration constants for most frequencies). I would recommend using whatever tools

you have to measure the clock frequency of your MSP430 and then recalculate the bit_time based off of that.

@Bloodred - very interesting. Have you tried hooking up a scope or logic analyzer to the pins (if you have one)? I really am not sure what could be causing that weird behavior. And yes, halving the bit time would effectively double the baud rate, but you also have to make sure to half the bit_time_5 also.

Reply

AnonymousApril 27, 2011 at 3:16 PM Three comments about the RX part: 1. It's better to set the compare value immediately when the pin interrupt is run for more consistent timing. 2. It seems that the start bit detection is immanent to the pin interrupt and thus the first timer interrupt is supposed to happen in the middle of bit 0 (first data bit to be received). Which means that the compare value should be greater than half a bit time.. 3. Consecutive bytes are missed regardless of processor speed because the timer interrupt is used once more just to check the received data. The check can happen immediately after shifting in the last bit, so the "if ( BitCnt == 0)" block should come after the shifting part (removed from else block).. I hope my observations are correct and useful to folks wanting to implement a FIFO.. Happy hacking! Thanks for sharing.

Reply

AnonymousApril 28, 2011 at 5:06 AM

RE: April 27, 2011 3:16 PM In addition to the above, timing is much less critical if you boost up to e.g. 8 MHz using the DCO. For the async serial it needs calibration which can be done automatically using the included 32 kHz watch crystal and the example code from slac463a.zip - msp430x20xx_dco_flashcal.c. The timer clock or bit_times need to be adjusted, and the compare value set from the pin interrupt needs to be set to 1.5 bit times.

Reply

AndrewSeptember 27, 2011 at 3:10 PM Excellent post - this code worked perfectly for me, and with only slight modification I've been able to get it to suit my purposes for debugging another tricky project I'm working on with my G2252.

My question, though - you say this is a "Software" UART, and I don't see anything in this code that looks like it's calling upon the MSP430's hardware USCI module (which I understand contains UART support, but I confess that that part of the documentation has mostly lost me).

So am I correct in my understanding that this code is just bit-banging serial communication using GPIOs, or is there some aspect of the MSP's USCI/UART hardware that's being leveraged here?

If the former is the case, are there some advantages or disadvantages to doing it this way vs. implementing the "hardware" UART (whatever this would mean)?

Reply

lolezSeptember 27, 2011 at 11:22 PM

Could you please redo this code into SINGLE reusable and standalone function? (so there will be nothing in main() except:

magic_function("uart string to send");

Pleaase

Reply

Joby TaffeySeptember 28, 2011 at 6:07 AM @lolez I did this for my Launchpad SPI Explorer. http://blog.hodgepig.org/2010/09/10/575/

See uart.c in http://blog.hodgepig.org/wp-uploads/articles/000048spi/spi.tar.gz

Reply

Eddy BOctober 6, 2011 at 5:40 PM it's work very good

tks Nicholas

Ed

Reply

Eddy BOctober 6, 2011 at 6:41 PM Nicholas in your code you noted : // 9600 Baud, SMCLK=1MHz (1MHz/9600)=104

But when I try to change the value by 26 this value for 38400 bauds communication it doesn't work.

Why ?

Reply

NJCOctober 19, 2011 at 9:57 PM It might be time for me to update this post and make the functions a bit more reliable. I do admit that the code presented here is not perfect.

If you do need a device with a flawless UART, I recommend using one of the newer value line chips that have a hardware UART built in.

@Eddy B - It should work just fine as long as you are not using the LaunchPad's built in application UART to communicate with the PC. The LaunchPad's UART supports a maximum of 9600 baud. I recommend using an FTDI chip if you are having trouble communicating at higher speeds.

Reply

AndrewOctober 20, 2011 at 10:19 AM "If you do need a device with a flawless UART, I recommend using one of the newer value line chips that have a hardware UART built in."

The documentation is a little confusing in this regard - it seems to indicate that all of the value line devices have an SPI/I2C UART - does this not also mean there's an async serial UART? Which devices do have this feature?

Reply

NJCOctober 20, 2011 at 11:52 AM @Andrew - The MSP430 contains either the USI and/or the USCI. You have to look closely at the documentation to see what each individual chip supports. For example, the MSP430G2231 only has a USI and supports just I2C and SPI. On the other hand, the MSP430G2153 has two USCIs and supports UART, SPI, I2C, and IrDA.

Reply

AndrewOctober 20, 2011 at 8:43 PM @NJC - Thanks, this makes sense to me.

The code in this post, as I understand it, is a way to fake a UART on an MSP that doesn't support it in hardware, rather than a method for interfacing with real UART hardware, correct?

To say it differently, it would be inefficient to implement the above method for serial communication on an MSP430G2153, correct?

Reply

TendollaNovember 10, 2011 at 2:27 PM Amazing Stuff!

Within 45 minutes, I was switching LED's on and off, only when I pressed the spacebar (through the terminal!)

Thank you Nicholas - I have a $5 Donation on it's way -- enough to buy a pint of beer?

Reply

NJCNovember 14, 2011 at 8:25 PM @Andrew - Yes, it is a way to fake a UART that doesn't have a hardware UART. Redundant and inferior would be a better way to describe it than inefficient.

@Tendolla - Thank you so much! It might actually be enough for a pitcher of beer. :-) Glad I could help you get started with the LaunchPad. Thanks again!

Reply

Burak GrenerJanuary 11, 2012 at 4:51 PM hi everybody,

i try to change TDX pin to different fron P 1.1 and P 1.2 but only works on P 1.5 however i also need other pins as TDX. Any one can solve this problem or can give advise to solve the problem???

Thanks. Best Regarts, Burak.

Reply

AndrewJanuary 13, 2012 at 8:43 AM @Burak,

Which other pins are you trying to use? You'll want to make sure you have the jumper pulled off to disable the button for P1.3 - I believe that pin gets pulled high by an onboard resistor when the switch is enabled.

Likewise, the LEDs at 1.0 and 1.6 may be interfering.

Reply

hi dear vishuJanuary 25, 2012 at 4:08 PM This comment has been removed by the author.

Reply

AnonymousJanuary 25, 2012 at 4:12 PM HI

Great post NJC.

I used this code for my project(MCU msp430g2553 having one hard uart) where MCU msp430g2553 is working as a middle buffer between other two device. as shown

Device1---------- MY MCU-------- Device2 Hard uart Hard uart||soft Uart Hard uart

and also n full duplex mode (so i dedicate another timer for transmit)

for single digit transmit and receive is working fine. but on continue communication some char (or say bit) get corrupted or missed some time. i used circular buffer in between to make communication more reliable thing get improved from it but not 100%.

please suggest some solution.

Reply

AnonymousJanuary 26, 2012 at 4:20 PM Hi,

thanks a lot for the code man :)

i use it for led display via Serial and it work like a charm.

i wanted to implement a new functionality but it require the loop in main function to go on without waiting for a Serial transmition.

I'm presently crushing my head to the wall because each try result in the fact that serial won't work anymore :(

need help on that

Thanks

Reply

AndrewJanuary 27, 2012 at 7:56 AM Anonymous,

Instead of implementing a continuous loop for the new function you're writing, try setting it up as a function that gets called at a periodic basis as an interrupt by the timer (in much the same way that this serial code works). If you're not using the WDT (Watchdog timer), it can be used as an additional periodic timer, calling your function regularly.

Reply

zhenyu XiApril 27, 2012 at 12:10 PM nice code. Thank you!

But i'm still confused. Why do you need two definitions of Bittime(#define Bit_time 104 // 9600 Baud, SMCLK=1MHz (1MHz/9600)=104 #define Bit_time_5 52 // Time for half a bit). And in the #pragma vector=PORT1_VECTOR function you set the timer till first bit with "Bit_time_5". Can you explain this for me? Thanks!

Reply

NJCMay 20, 2012 at 12:20 AM @zhenyu - The reason we have a half bit time, is so that we can start measuring the received signal one half bit time after the initial transition from high to low. Sure, the half bit time could be calculated every time we need it, but I just store it from the beginning to make the function a bit more efficient.

Does that make sense?

Reply

Ben EsserSeptember 3, 2012 at 8:24 PM First off, thanks for the great site! It's helped a lot so far.

I have a problem using your code with my launchpad. My device is a G2553.

When I send characters to it, it sends back a character that you would usually expect when the baud rate is off. But I've tried all the possible baud rates as well as changing the bit-rates in the code. Nothing works.

Any ideas?

Reply

AndrewSeptember 3, 2012 at 10:04 PM What particular character is it sending back? If it's not printable ASCII, could you give us the hex?

Reply

AnonymousOctober 5, 2012 at 3:47 PM Hello,

First thank you for these posts, very helpful. I am writing code in c that needs to send an email after I have sent a particular hex message via UART to the computer. I have everything I need, but I am having trouble setting the necessary flag after the signal is received. Can you offer any advice on how to accomplish this? Is it even possible? If not is there a way to do this with seperate c modules.

PS: I have verified each piece of code, just need help combining them.

Reply Replies

AnonymousOctober 5, 2012 at 3:53 PM Let me clarify, I want the launchpad to send a signal that tells the computer to send an email. I have code for sending emails, and thanks to you the uart. I want an email sent after the uart comm has taken place. Thanks

NJCOctober 5, 2012 at 3:58 PM I would recommend getting everything to work in steps. First make a C program which can receive characters received via the LauchPad's UART and then display them. There are many examples online for serial communication in C. If you run into any additional trouble, try the 43oh.com/forums. Hope that helps!

Reply

Load more... Links to this post Create a Link

Newer Post Older Post Home Subscribe to: Post Comments (Atom) SEARCH POSTS ON THE LAUNCHPAD

HELP ME PAY THE BILLS!

SUBSCRIBE TO

Posts Comments

Nicholas J. Conn nicholasjconn AroundTI Glass half full or half empty? To the engineer it's twice as big as it needs to be. That's #engineeringchange 6 days ago reply retweet favorite YouVersion See the Bible come to life when @bibleseries premiers next Sunday. Watch and share the trailer today: youtu.be/1hThfoBzWxw

12 days ago reply retweet favorite AroundTI Thomas Edison once said that 'Our greatest weakness lies in giving up.' We agree. RT if you do too. We keep pursuing: ow.ly/hUYpv 15 days ago reply retweet favorite nicholasjconn 'Mass Equals Time' Redefines Weight Standards bit.ly/Zi79tP via @IEEESpectrum 16 days ago reply retweet favorite

Join the conversation

POPULAR POSTS

A Simple ADC Example on the LaunchPad I finally have had the time to write up this post. Hopefully in a few more weeks I will have more time and can keep up a steady stream of po...

Timers and Clocks and PWM! Oh My! I am going to try and not be so wordy in this post since there is a lot to cover on this topic. I want to do it all at once too; I would rat...

Adding Bluetooth to your MSP430 Project Most projects which I have seen input and output some sort of data: be it a multimedia stream, sensor data, or user inputs. In this post I w... Half Duplex Software UART on the LaunchPad Before I get into this post, I want to let you all know that the very basic oscilloscope project is coming; this post is the first in a seri...

printf() for the MSP430

"The output function printf translates internal values to characters." This simple definition comes from the book "C Progra...

BLOG ARCHIVE

2013 (1) 2012 (6) 2011 (14) 2010 (22) December (1) September (1) August (5) Half Duplex Software UART on the LaunchPad Yet Another Update Post A Shield Standard Proposal Using the USI as a UART Warning: Non Technical Post, and LaunchPad Shields... July (15) FOLLOWERS

NJC MSP430 LaunchPad Blog. Simple template. Powered by Blogger.

Вам также может понравиться