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