This post will describe how I use the USI as a UART and discuss how I hook the LaunchPad up to a MSP430F2013 on my breadboard which is connected to an FTDI breakout board. Please note that it is impossible to easily set up the USI module to receive UART data, and I will never write code to do so. For those of you who are beginners please do not get caught up in trying to understand the USI code if you are having trouble, I will not be going in depth about the USI here and will save that for another post. I hope to provide more of a mix of advanced and beginner topics over the next few weeks.
For this post I did not use any of the chips that came with the LaunchPad. For those who are curious, it is possible to plug the MSP430F2013 directly into the socket on the LaunchPad even though I have it in a breadboard for this project; it is also possible to use this code on one of the MSP430s that came with the LaunchPad by changing the include file in the code.
I have the schematic above built up on a breadboard and I am using the FTDI breakout board from Spark Fun shown below (image from Sparkfun website). To connect the FTDI board to the 2013 I used two wires; one connecting the RX line on the FTDI board to the TX(P1.6) line on the 2013, and one to connect the GND of each device together. I do not power the 2013 from the FTDI device's power, but it is still necessary to connect the grounds together. The is because voltage is a measure of the difference in electric field between two points, so without a reference point (GND) the voltages from each source could be completely different relative to the actual ground in the earth. Example, if GND on the FTDI device is at 49.2V and the VCC is at 52.5V (relative to the earths ground), it is still providing a 3.3V supply. Sinec we hook each GND together, it forces both circuits to be referenced to the same point. Hope I explained that well enough to understand.
I powered the 2013 from the LaunchPad, but it could be powered from anything (including the FTDI board, or grapes apparently). To hook the breadboard ot the LaunchPad I connected the RST and TEST pins from the chip to the LaunchPad by taking off the jumpers which connect the emulator side of the board to the target side of the board. Make sure your jumpers are removed and you are connected to the side closest to the USB connector. I also used two wires to connect the GND and VCC from the LaunchPad to power the circuit. I used these jumper wires, but it is also fairly easy to use wire-wrap, or headers soldered to wire, or really anything.
Apparently the blogger really doesn't like syntax highlighter. It also happened to delete the rest of my post after the code section, which is now lost forever because of the autosave blogger has. I can't describe how frustrated I am. Here goes my attempt to re-write what I had. It was perfectly written. >.<
I will be using Git to display in the blog, so I hope its shown correctly. The code is also posted on Git in case someone can't see the embedded code. I think it's possible to comment on the code too. Hope the link works for everyone.
How it all Works
I will not be discussing each line in detail like I do for my other posts but I will be discussing how the USI can transmit a UART signal.
To start, it turns out that you do not need to have the SPI clock output going when using the USI. This is good because not outputting a clock saves not only power but also should allow you to have an extra I/O pin (I would assume?). The first thing I do in the code is enable the output pin, set the USI to master mode, set it to sent the lowest significant bit first, and enable the USI interrupt. I am sending the LSB first because that is how UART works, and I am enabling the USI interrupt so we can determine if the USI is busy or not when we attempt to send a byte. Notice how I do not implement a function for the USI interrupt, we only will be looking at the interrupt flag bit. For this post we will be using the SMCLK as our clock signal for the USI which is sourced from the DCO, which by default is set at 1.1MHz.
Note: The baud rate is dependent on the clock signal the USI uses; for this case the baud rate will be 1100000 because we use a 1.1MHz signal. If you want to use a standard baud rate you must set your clock to a multiple of that rate and set the correct clock divider correctly. See below for information on receiving non-standard baud rates on your PC.
In order to make the output be a UART signal we need to add a start bit and stop bit. First we add the start bit by shifting the data being sent to the left by one position. We add the stop bit by setting the last few bits to 1. Now our 8 bit value has turned into a 10 bit value which we need to send on the USI. In order to send more than 8 bits we need to set the USI to 16 bit mode otherwise it will not transmit more than 8 bits. We then start the transmission by telling the USI there are 10 bits that need to be sent.
Note: Even though the transmit function uses an unsigned integer (a 16 bit value) for the data, only the first 8 bits will be sent.
In the transmit function the while loop makes sure the USI is not currently busy before we start sending our byte. At first I had this at the end of the transmit function which caused the function to wait until the USI was done before it returned. The reason I changed the location was so that it only had to wait when it was ready to start sending the data. This means that the CPU will only sit around waiting when it really has nothing to do. We could go even further and create a buffer. I might discuss how buffers work in microcomputers in a future post.
In order to see the data on your PC you need a terminal program. I recommend Realterm (which I mentioned in a previous post) because you can set the baud rate to any value. I used a program which I wrote in C# in order to test this code, so I did not verify that it works with Realterm, but I expect it will work no problem. I will not be distributing my program sine it is a total mess and was written for my specific purpose in mind; I might post it when we go over ADC converters. Below you can see the output waveform which I captured using my logic analyzer.
So, what do you see that is bothersome about this resulting waveform? Why is there such a long delay between the two transmissions?? Everything works, so why do I think something is wrong? Well, we are running at 1100000 baud rate, but we are sending bytes at a rate of 22kHz; since a byte is 8 bits we are transferring data at a rate of 176.6kbps. This is still quite fast, but look at all the dead time between transmissions! We should be able to achieve at least 700kbps with such a simple program as this one.
I looked into the assembly code in the debugger and there seems to be nothing wrong with the code, there is no overhead causing this delay. So what is it? I think it is the USI, it seems to be taking FOREVER to finish and throw and interrupt. Why? Is this normal? I don't know. The 175.6kbps is more than enough for my project which needs to sent 16 bits at a rate of 4.5kHz (72kbps), so I will not be looking into why the USI takes so long. I will leave that up to you. If anyone finds out why there is such a long delay between transmissions, please comment and let me know. It is more than possible (quite probably) that I have a setting wrong in the USI which is causing it to mess up how the interrupt is thrown. I could also change how the USI lets the program know it's busy, but for now I will leave the code the way it is since it does everything I need it to.
Final Thoughts and Updates on the Blog
Sometimes I will write posts which correspond to what I am doing in my own project (like this one) because it is easy for me. Most of my other posts do not really relate to my project (for example, I don't use any LEDs or buttons in my project), I generally write these solely for the community. I just hope that someone out there benefits from posts like this.
If all goes to plan, my next post will present my proposal on a shield standard. Stay tuned if you are interested in seeing this and want to help make a great standard. The post after that will probably go over how to use the ADC on the 2231
As always, if you have any questions feel free to ask; I will do my best to answer every question but sometimes I won't be able to. It is quite time consuming to help people with their code unless they have a specific question or are unsure of only a few lines. If you want help with code, feel free to ask a specific question; if you post your entire program I probably wont be able to help you even if I want to.
I am very happy with the comments you guys have been posting! The back and forth is what I feel makes this blog special. Please don't stop commenting, the more comments, the better (as long as they are not completely off topic :-P). On August 8th a full month will have gone by since I started the blog! By then the blog will have had more than 2000 visits! This is amazing! I hope my blog and the community continue to grow. There is so much potential for the LaunchPad.
As always, best of luck!