|
Intro to Physical Computing Syllabus code, circuits, & construction
|
Serial Communication on the PIC using PicBasic Pro |
||||||||||||||||||||||
| Asynchronous serial communication on the PIC using PicBasic Pro is done in a variety of ways. If you've already used the debug statement, you've already done some serial communication. Debug is a special instance of serial communication, in which you set the baudrate and other properties at the beginning of your program using DEFINE statements. Once the details of debug have been set, they cannot be changed while the program is running. The commands serin, serin2, serout, and serout2 provide more flexibility in serial communication. There are a few other serial commands that can be used in lieu of these, but serin2 and serout2 offer the best combination of power, flexibility and simplicity. For these notes, we'll use serin2 and serout2. For details on the other serial commands, see the PicBasic Pro manual.
One important fact to keep in mind before getting into the details of serial commands is this: PicBasic Pro has no way of creating serial buffers. Unlike desktop computers, or even some microprocessors like the BX-24, the PIC deals with serial data one byte at a time. This simplifies matters on one level, because you have less to set up, but it complicates matters on another, as we'll see below. All of the serial commands above both assume you're using a 4 mHz clock. If you're using anything else, make sure to define it at the start of your program, for example: DEFINE OSC 10 for a 10 MHz oscillator, or DEFINE OSC 20 for a 20 MHZ oscillator. The capitalization is important when it comes to defines. |
|||||||||||||||||||||||
| Sending Serial out
The serout command allows you to send serial data out on any I/O pin as follows: serout2 dataPin, mode, [data]
The mode is used to set the baudrate, parity, stop bits, and inversion for serout. You can calculate the baud mode using the formulas given in the manual, but many of the more common baud modes are listed below: |
|||||||||||||||||||||||
A simple "hello world" program to send serial out might look like this: main: serout2 portc.6, 16468, ["hello world", 10, 13] goto main Note that you can put more than one item in the square brackets to be sent out, as long as you separate the items with commas. In the example above, the string "Hello World" is followed by a byte of value 10 (ASCII line feed) and a byte of value 13 (ASCII carriage return). The same modifiers that are used with debug can be used with serout, as follows:
So in order to send the value of a variable to be read in a terminal program for debugging, for example, you could send: serout2 portc.6, 16468, ["myvar = ", DEC myvar, 10, 13] You use DEC when you want to see a number as ASCII text, but you generally don't use it when sending a value to another microcontroller or computer. Receiving Serial in The serin command allows you to receive serial data on any pin. It's very similar to serout2: serin2 dataPin, mode, [data]
Because the PIC has no serial buffer to speak of, serin2 stops the program and waits until serial data comes in. If no data comes in, the program does not continue. To get around this, a timeout label can be used. For example, if timeout is set to 10, then the PIC will wait for data to come in for 10 milliseconds, and if none comes in, it will jump to the label specified in the label parameter. Basically, this allows you to tell the PIC to do something else if it gets no data. The example below shows serin2 in action, and uses a timeout and a label to jump to on timeout. In it, we're waiting for a byte value in (0 - 255), and storing it in a variable called inputData. If we get data, we set pulseWidthVar equal to the new value. If we get no data, we skip to nodata, and use the last value we had for pulseWidthVar: |
It's convenient to include these values at the top of your program as constants, so you can refer to them by name instead of remembering the numbers. For example:
inv9600 con 16468 |
||||||||||||||||||||||
inputData var byte ' variable to receive data into pulseWidthVar var byte ' set initial value for pulseWidthVar pulseWidthVar = 255 main: serin2 portc.7, 16468, 10, nodata, [inputData] pulseWidthVar = inputData nodata: pulsout portb.2, pulseWidthVar goto main Without the timeout and the label, the program would stop running at the serout line until it got some data. This could be bad for the timing of other parts of the program. As with serout2, we can receive data in a number of formats using serin2. The simplest is to receive it raw. If we expect a single byte, put a byte variable in the data parameter. However, if we want to get more complex, we can receive as BIN, HEX, or DEC, we can opt to skip a certain number of characters, or we can wait for a particular character or sting of characters to come in. For details on all of these options, see the PicBasic Pro manual. |
n.b. this is a very crude servo example, as there is no calculation of the servo refresh time. It works as is, but probably wouldn't work properly if we added sensor inputs, etc. In that case, we'd need to program it to calculate the servo's necessary refresh period (20 ms), taking into account the timeout of the serial command. | ||||||||||||||||||||||