Serin
Syntax
Serin Rpin { \ Fpin }, Baudmode, { Plabel, } { Timeout, Tlabel, } [ InputData ]
Overview
Receive asynchronous serial data (i.e. RS232 data).
Parameters
Rpin is a Port.Bit constant that specifies the I/O pin through which the serial data will be received. This pin will be set to input mode. Fpin is an optional Port.Bit constant that specifies the I/O pin to indicate flow control status on. This pin will be set to output mode. Baudmode may be a variable, constant, or expression (0 - 65535) that specifies serial timing and configuration. Plabel is an optional label indicating where the program should jump to in the event of a parity error. This argument should only be provided if Baudmode indicates that parity is required. Timeout is an optional constant (0 - 65535) that informs Serin how long to wait for incoming data. If data does not arrive in time, the program will jump to the address specified by Tlabel. Tlabel is an optional label that must be provided along with Timeout, indicating where the program jump to in the event that data does not arrive within the period specified by Timeout. It can also be the compiler directives; Break or Continue, if the command is used inside a loop. Break will exit a loop if a timeout occurs, and Continue will re-iterate the loop. InputData is list of variables and modifiers that informs Serin what to do with incoming data. Serin may store data in a variable, array, or an array string using the Str modifier.
Notes
One of the most popular forms of communication between electronic devices is serial communication. There are two major types of serial communication; asynchronous and synchronous. The Rsin, Rsout, Serin and Serout commands are all used to send and receive asynchronous serial data. While the Shin and Shout commands are for use with synchronous communications.
The term asynchronous means ‘no clock.’ More specifically, ‘asynchronous serial communication’ means data is transmitted and received without the use of a separate ‘clock’ line. Data can be sent using as few as two wires; one for data and one for ground. The PC's serial ports (also called COM ports or RS232 ports) use asynchronous serial communication. Note: the other kind of serial communication, synchronous, uses at least three wires; one for clock, one for data and one for ground.
RS232 is the electrical specification for the signals that PC serial ports use. Unlike standard TTL logic, where 5 volts is a logic 1 and 0 volts is logic 0, RS232 uses -12 volts for logic 1 and +12 volts for logic 0. This specification allows communication over longer wire lengths without amplification.
Most circuits that work with RS232 use a line driver / receiver (transceiver). This component does two things: -
Convert the ±12 volts of RS-232 to TTL compatible 0 to 5 volt levels. Invert the voltage levels, so that 5 volts = logic 1 and 0 volts = logic 0.
By far, the most common line driver device is the MAX232 from Maxim semiconductor. With the addition of a few capacitors, a complete 2-way level converter is realised. Figure 1 shows a typical circuit for one of these devices. The MAX232 is not the only device available, there are

Text in this figure or table
www.maxim.com, and download one of their many detailed datasheets.
5 Volts
C3
16 1uF
C5
| C1 | 1 | 2 | |
| 1uF | C1+ | VCC | V+ |
| 1uF | 3 |
C1- 4
C2 C2+
5
| 1uF | C2- MAX232 | ||
| From PIC | V+ | ||
| 11 | 14 | ||
| Serial Output | T1in | T1out | To PC |
| 10 | 7 |
Serial Port
| T2in | T2out | |
| 12 | 13 | |
| To PIC | R1out | R1in |
| 9 | 8 | |
| RX | TX GND | |
| Serial Input | R2out | R2in |
6 V-
| GND | 9-way | |||
| 1 | 2 | 3 | 4 | 5 |
| 6 | 7 | 8 | 9 | |
| 15 | C4 | D-Socket |
1uF 0V
other types that do not require any external capacitors at all. Visit Maxim’s excellent web site at
Typical MAX232 RS232 line-transceiver circuit.
Because of the excellent IO capabilities of the PICmicro™ range of devices, and the adoption of TTL levels on most modern PC serial ports, a line driver is often unnecessary unless long distances are involved between the transmitter and the receiver. Instead a simple current limiting resistor is all that’s required. As shown below: -

Text in this figure or table
R1 1K From PIC To PC's Serial Output Serial Port To PIC
Serial Input RX TX GND
R2
| 1K | 9-way | ||
| 1 | 3 | 4 | 5 |
| 6 2 7 | 8 | 9 |
D-Socket To PIC Circuit's GND
Directly connected RS232 circuit.
You should remember that when using a line transceiver such as the MAX232, the serial mode (polarity) is inverted in the process of converting the signal levels, however, if using the direct connection, the mode is untouched. This is the single most common cause of errors when connecting serial devices, therefore you must make allowances for this within your software.
Asynchronous serial communication relies on precise timing. Both the sender and receiver must be set for identical timing, this is commonly expressed in bits per second (bps) called Baud. Serin requires a value called Baudmode that informs it of the relevant characteristics of the incoming serial data; the bit period, number of data and parity bits, and polarity.
The Baudmode argument for Serin accepts a 16-bit value that determines its characteristics: 1stop bit, 8-data bits/no-parity or 7-data bits/even-parity and most speeds from as low as 300 Baud to 38400 Baud (depending on the crystal frequency used). The following table shows how Baudmode is calculated, while table 1 shows some common Baudmodes for standard serial Baud rates.

Text in this figure or table
| Step 1. | Determine the bit period. (bits 0 – 11) | (1,000,000 / Baud rate) – 20 |
| Step 2. | 8-bit/no-parity = step 1 + 0 |
data bits and parity. (bit 13) 7-bit/even-parity = step 1 + 8192
Step 3. True (non-inverted) = step 2 + 0
Select polarity. (bit 14) Inverted = step 2 + 16384 Baudmode calculation.
Add the results of steps 1, 2 3, and 3 to determine the correct value for the Baudmode parameter.

Text in this figure or table
8-bit no-parity 8-bit no-parity 7-bit even-parity 7-bit even-parity
BaudRate
| inverted | true | inverted | true | |
| 300 | 19697 | 3313 | 27889 | 11505 |
| 600 | 18030 | 1646 | 26222 | 9838 |
| 1200 | 17197 | 813 | 25389 | 9005 |
| 2400 | 16780 | 396 | 24972 | 8588 |
| 4800 | 16572 | 188 | 24764 | 8380 |
| 9600 | 16468 | 84 | 24660 | 8276 |
Table 1. Common Baud rates and corresponding Baudmodes.
If communications are with existing software or hardware, its speed and mode will determine the choice of Baud rate and mode. In general, 7-bit/even-parity (7E) mode is used for text, and 8-bit/no-parity (8N) for byte-oriented data. Note: the most common mode is 8-bit/no-parity, even when the data transmitted is just text. Most devices that use a 7-bit data mode do so in order to take advantage of the parity feature. Parity can detect some communication errors, but to use it you lose one data bit. This means that incoming data bytes transferred in 7E (even-parity) mode can only represent values from 0 to 127, rather than the 0 to 255 of 8N (no-parity) mode.
The compiler’s serial commands Serin and Serout, have the option of still using a parity bit with 4 to 8 data bits. This is through the use of a Declare: -
With parity disabled (the default setting): -
Declare Serial_Data 4 ' Set Serin and Serout data bits to 4
Declare Serial_Data 5 ' Set Serin and Serout data bits to 5
Declare Serial_Data 6 ' Set Serin and Serout data bits to 6
Declare Serial_Data 7 ' Set Serin and Serout data bits to 7
Declare Serial_Data 8 ' Set Serin and Serout data bits to 8 (default)
With parity enabled: -
Declare Serial_Data 5 ' Set Serin and Serout data bits to 4
Declare Serial_Data 6 ' Set Serin and Serout data bits to 5
Declare Serial_Data 7 ' Set Serin and Serout data bits to 6
Declare Serial_Data 8 ' Set Serin and Serout data bits to 7 (default)
Declare Serial_Data 9 ' Set Serin and Serout data bits to 8
Serial_Data data bits may range from 4 bits to 8 (the default if no Declare is issued). Enabling parity uses one of the number of bits specified.
Declaring Serial_Data as 9 allows 8 bits to be read and written along with a 9th parity bit.
Parity is a simple error-checking feature. When a serial sender is set for even parity (the mode the compiler supports) it counts the number of 1s in an outgoing byte and uses the parity bit to make that number even. For example, if it is sending the 7-bit value: 0b0011010, it sets the parity bit to 1 in order to make an even number of 1s (four).
The receiver also counts the data bits to calculate what the parity bit should be. If it matches the parity bit received, the serial receiver assumes that the data was received correctly. Of course, this is not necessarily true, since two incorrectly received bits could make parity seem correct when the data was wrong, or the parity bit itself could be bad when the rest of the data was correct.
Many systems that work exclusively with text use 7-bit/ even-parity mode. For example, to receive one data byte from bit-0 of PORTA at 9600 Baud, 7E, inverted:
Serin PORTA.0, 24660, [SerData]
The above example will work correctly, however it doesn’t inform the program what to do in the event of a parity error.
Below, is an improved version that uses the optional Plabel argument:
Serin PORTA.0, 24660, ParityError, [SerData]
Print Dec SerData
Stop
ParityError:
Print "Parity Error"
Stop
If the parity matches, the program continues at the Print instruction after Serin. If the parity doesn’t match, the program jumps to the label P_ERROR. Note that a parity error takes precedence over other InputData specifications (as soon as an error is detected, Serin aborts and jumps to the Plabel routine).
In the examples above, the only way to end the Serin instruction (other than reset or power-off) is to give Serin the serial data it needs. If no serial data arrives, the program is stuck in an endless loop. However, you can force Serin to abort if it doesn’t receive data within a specified number of milliseconds.
For example, to receive a value through bit-0 of PORTA at 9600 Baud, 8N, inverted and abort Serin after 2 seconds (2000 ms) if no data arrives: -
Serin PORTA.0, 16468, 2000, TimeoutError, [SerData]
Print Cls, Dec MyResult
Stop
TimeoutError:
Print Cls, "Timed Out"
Stop
If no serial data arrives within 2 seconds, Serin aborts and continues at the label TimeoutError.
Both Parity and Serial Timeouts may be combined. Below is an example to receive a value through bit-0 of PORTA at 2400 Baud, 7E, inverted with a 10-second timeout: -
Dim SerData as Byte
Again:
Serin PORTA.0, 24660, ParityError, 10000, TimeoutError, [SerData]
Print Cls, Dec SerData
GoTo Again
TimeoutError:
Print Cls, "Timed Out"
GoTo Again
ParityError:
Print Cls, "Parity Error"
GoTo Again
When designing an application that requires serial communication between microcontrollers, you should remember to work within these limitations: -
When the PICmicro™ is sending or receiving data, it cannot execute other instructions. When the PICmicro™ is executing other instructions, it cannot send or receive data.
The compiler does not offer a serial buffer as there is in PCs. At lower crystal frequencies, and higher serial rates, the PICmicro™ cannot receive data via Serin, process it, and execute another Serin in time to catch the next chunk of data, unless there are significant pauses between data transmissions.
These limitations can sometimes be addressed by using flow control; the Fpin option for Serin and Serout. Through Fpin, Serin can inform another PICmicro™ sender when it is ready to receive data. (Fpin flow control follows the rules of other serial handshaking schemes, however most computers other than the PICmicro™ cannot start and stop serial transmission on a byteby-byte basis. That is why this discussion is limited to communication between PICmicros.)
Below is an example using flow control with data through bit-0 of PORTA, and flow control through bit-1 of PORTA, 9600 Baud, N8, non-inverted: -
Serin PORTA.0\PORTA.1, 84, [SerData]
When Serin executes, bit-0 of PORTA (Rpin) is made an input in preparation for incoming data, and bit-1 of PORTA (Fpin) is made an output low, to signal “go” to the sender. After Serin finishes receiving data, bit-1 of PORTA is brought high to notify the sender to stop. If an inverted BaudMode had been specified, the Fpin’s responses would have been reversed. The table below illustrates the relationship of serial polarity to Fpin states.

Text in this figure or table
| Serial Polar- | Ready to Receive | Not Ready to Receive |
| ity | ("Go") | ("Stop") |
| Inverted | Fpin is High (1) | Fpin is Low (0) |
| Fpin is Low (0) | Fpin is High (1) |
Non-inverted
See the following circuit for a flow control example using two 16F84 devices. In the demonstration program example, the sender transmits the whole word “HELLO!” in approx 6 ms. The receiver catches the first byte at most; by the time it got back from the first 1-second delay (DelayMs 1000), the rest of the data would be long gone. With flow control, communication is flawless since the sender waits for the receiver to catch up.
In the circuit below, the flow control pin (PORTA.1) is pulled to ground through a 10kΩ resistor.

Text in this figure or table
receiver is first powered up.
| 5 Volts | 5 Volts | |||||
| R1 | R3 | |||||
| 4.7k | 14 | 14 | 4.7k | |||
| 13 | 13 | |||||
| SENDER | VDD | RECEIVER | ||||
| RB7 | RB7 VDD | |||||
| 4 | 12 | 12 | 4 | |||
| MCLR | RB6 | RB6 | MCLR | |||
| 11 | 11 | |||||
| RB5 | RB5 | |||||
| 10 | 10 | |||||
| 4MHz | RB4 | RB4 | 4MHz | |||
| 9 | 9 | |||||
| RB3 | TO | RB3 | ||||
| Crystal | Crystal | |||||
| 16 | 8 | 8 | 16 | |||
| OSC1 | RB2 | RB2 | OSC1 | |||
| 7 | 7 | |||||
| RB1 | RB1 | |||||
| 6 | LCD MODULE | 6 | ||||
| RB0 | RB0 | |||||
| PIC16F84 | PIC16F84 | |||||
| 3 | 3 | |||||
| RA4 | RA4 | |||||
| C1 | C5 | |||||
| 15 | 2 | 2 | 15 | |||
| OSC2 | RA3 | RA3 | OSC2 | |||
| 10uF | 1 | 1 | 10uF | |||
| RA2 | RA2 | |||||
| 18 | 18 | |||||
| RA1 | RA1 | |||||
| C2 | C6 | |||||
| 17 | 17 | |||||
| RA0 | RA0 | |||||
| C3 | C4 | VSS | R2 | VSS | C8 | C7 |
| 0.1uF | 0.1uF | |||||
| 22pF | 22pF | 5 | 10k | 5 | 22pF | 22pF |
| 0V | 0V |
Communicating Communication between two microcontrollers using flow control.
This is to ensure that the sender sees a stop signal (0 for inverted communications) when the
' Sender Code. Program into the Sender device.
Do
Serout PORTA.0\PORTA.1, 16468, ["HELLO!"] ' Send the message.
DelayMs 2500 ' Delay for 2.5 seconds
Loop ' Repeat the message forever
' Receiver Code. Program into the Receiver device.
Dim bMessage as Byte
Do
Serin PORTA.0\PORTA.1, 16468, [bMessage] ' Get 1 byte.
Print bMessage ' Display the byte on LCD.
DelayMs 1000 ' Delay for 1 second.
Loop ' Repeat forever
Serin Modifiers.
The Serin command can be configured to wait for a specified sequence of characters before it retrieves any additional input. For example, suppose a device attached to the PICmicro™ is known to send many different sequences of data, but the only data you wish to observe happens to appear right after the unique characters, “XYZ”. A modifier named Wait can be used for this purpose: -
Serin PORTA.0, 16468, [Wait("XYZ"), SerData]
The above code waits for the characters “X”, “Y” and “Z” to be received, in that order, then it receives the next data byte and p[laces it into variable SerData.
The compiler also has a modifier for handling a string of characters, named Str.
The Str modifier is used for receiving a string of characters into a Byte array variable.
A string is a set of characters that are arranged or accessed in a certain order. The characters "ABC" would be stored in a string with the "A" first, followed by the "B" then followed by the "C".
A Byte array is a similar concept to a string; it contains data that is arranged in a certain order. Each of the elements in an array is the same size. The string "ABC" would be stored in a Byte array containing three bytes (elements).
Below is an example that receives ten bytes through bit-0 of PORTA at 9600 bps, N81/inverted, and stores them in the 10 element Byte array, bSerString: -
Dim bSerString[10] as Byte ' Create a 10 element byte array.
Serin PORTA.0, 16468, [Str bSerString] ' Fill the array with data.
Print Str bSerString ' Display the string.
If the amount of received characters is not enough to fill the entire array, then a formatter may be placed after the array’s name, which will only receive characters until the specified length is reached. For example: -
Dim bSerString[10] as Byte ' Create a 10 element byte array.
Serin PORTA.0, 16468, [Str bSerString\5] ' Fill first 5-bytes of array
Print Str bSerString\5 ' Display the 5-character string.
The example above illustrates how to fill only the first n bytes of an array, and then how to display only the first n bytes of the array. n refers to the value placed after the backslash.
Because of its complexity, serial communication can be rather difficult to work with at times. Using the guidelines below when developing a project using the Serin and Serout commands may help to eliminate some obvious errors: -
Always build your project in steps. Start with small, manageable pieces of code, (that deal with serial communication) and test them, one individually. Add more and more small pieces, testing them each time, as you go. Never write a large portion of code that works with serial communication without testing its smallest workable pieces first. Pay attention to timing. Be careful to calculate and overestimate the amount of time, operations should take within the microcontroller for a given oscillator frequency. Misunderstanding the timing constraints is the source of most problems with code that communicate serially. If the serial communication in your project is bi-directional, the above statement is even more critical. Pay attention to wiring. Take extra time to study and verify serial communication wiring diagrams. A mistake in wiring can cause strange problems in communication, or no communication at all. Make sure to connect the ground pins (Vss) between the devices that are communicating serially. Verify port setting on the PC and in the Serin / Serout commands. Unmatched settings on the sender and receiver side will cause garbled data transfers or no data transfers. This is never more critical than when a line transceiver is used(i.e. MAX232). Always remember that a line transceiver inverts the serial polarity.
If the serial data received is unreadable, it is most likely caused by a Baud rate setting error, or a polarity error. If receiving data from another device that is not a PICmicro™, try to use Baud rates of 9600 and below, or alternatively, use a higher frequency crystal.
Because of additional overheads in the microcontroller, and the fact that the Serin command offers no hardware receive buffer for serial communication, received data may sometimes be missed or garbled. If this occurs, try lowering the Baud rate, or increasing the crystal frequency. Using simple variables (not arrays) will also increase the chance that the device will receive the data properly.







