I’ve written a proper serial port driver from scratch that can be downloaded here: http://kevin.org/frc. The main source file, serial_ports.c, consists of just over a thousand lines of code, comments and documentation. The code implements a fully buffered, full duplex, interrupt driven serial port driver for the FRC and EDU robot controllers. I’ve included the readme.txt text below. Have fun.
Edit: This project was built using MPLAB 6.60. If your version of MPLAB complains about the project version, the best thing to do is just create a new project with MPLAB’s project wizard. Include every file except: FRC_alltimers.lib, ifi_alltimers.lib, printf_lib.c and printf_lib.h and you should be able to build the code.
-Kevin
The source code in serial_ports.c/.h contains a software
implementation of a fully buffered, interrupt-driven, full-
duplex serial port driver that can be used with either or both
on-board serial ports. Also included is a modified version of
IFI's original printf() software that supports the use of both
serial ports. Unlike the IFI code, this driver is non-blocking,
which means that you can send a byte of data without having to
wait around to make sure it gets sent before sending another.
This is the same way operating systems, like Linux and Windows,
handle serial data reception and transmission in the background
for application software.
The source code in serial_ports.c/.h and printf.c/.h will work
with the Robovation (A/K/A EDU-RC) robot controller and the
FIRST Robotics robot controller without modification.
Because you can now easily receive data from another computer,
you can interact with your nifty IFI robot controller in real-
time to change operating parameters on-the-fly using common
terminal emulation software, or send real telemetry to custom
applications written with Visual Basic, Visual C++, MATLAB,
etc... Don't want to drag a long serial cable behind your 'bot?
Well, check-out the nifty SMiRF radio modem from SparkFun
Electronics ([http://www.sparkfun.com](http://www.sparkfun.com/)). Would the coolness
factor of your 'bot be elevated if you had a LCD mounted on
board to display diagnostics (yes, this is a rhetorical
question)? How about using one of the serial LCDs that can be
found on the 'net? I've had success using Scott Edward's
Electronics ([http://www.seetron.com](http://www.seetron.com/)) serial LCDs. The TRM-425L
will work with the TTL-level serial port two and also includes
a keypad interface. I've been mostly using the BPP-420L on
serial port one. To use the above devices you'll need to build
a simple three or four conductor cable. Disclaimer: Other than
being a satisfied customer, I have no interest (financially, or
otherwise) in the companies mentioned above.
By default, serial port one will operate at 115200 baud, which
is compatible with InnovationFIRST's terminal program, and
serial port two will operate at 9600 baud, which will work with
the above mentioned peripheral devices. these values can be
easily changed by modifying the serial port initialization
functions mentioned below.
For an example of how to use this software, see the code
in Process_Data_From_Master_uP(), which demonstrates how to
properly use this new functionality.
***************************************************************
Here's a description of the functions in serial_ports.c:
Init_Serial_Port_One()
Init_Serial_Port_Two()
These functions initialize the serial ports. This is where
you will enable or disable the serial port's receive and/or
transmit circuitry and set the baud rate at which it will
operate. One or both of these functions must be called before
any serial port operations can take place.
Serial_Port_One_Byte_Count()
Serial_Port_Two_Byte_Count()
These functions will return the number of bytes present in
their respective received data queues. Because there might
not be any data in the queues, these functions must be called
before you can read any data from a serial port.
Read_Serial_Port_One()
Read_Serial_Port_Two()
These functions will return the next byte from the received
data queue. If no data is present in the queue, the function
will return the number zero, which could cause problems if
your incoming data can also contain a zero. This is why the
Serial_Port_xxx_Byte_Count() functions must be called first.
Write_Serial_Port_One()
Write_Serial_Port_Two()
These functions put a byte of data on the serial port transmit
queue. If the queue is full, the function will make you wait
until a storage slot becomes available before allowing your
code to execute again.
Rx_1_Int_Handler()
Rx_2_Int_Handler()
When a new byte of data is received by the serial port, the
microcontroller will automatically call these functions to
get the new data and place it in the received data queue for
you. You shouldn't have to call these functions yourself.
Tx_1_Int_Handler()
Tx_2_Int_Handler()
When the serial port is ready to start sending a new byte of
data, the microcontroller will automatically call these
functions to get the next byte of data from the transmission
queue and give it to the serial port for transmission. You
shouldn't have to call these functions yourself.
***************************************************************
Five things must be done before the serial port driver will
work correctly:
1) You must add the serial_ports.c/.h source files to your
MPLAB project.
2) The interrupt handlers must be installed in the
InterruptHandlerLow() function located in the
user_routines_fast.c source file. See the accompanying
copy of user_routines_fast.c to see how this is done.
3) Init_Serial_Port_One() and/or Init_Serial_Port_Two()
must be called from the User_Initialization() function
located in the user_routines.c source file.
4) As this software is intended to replace the default
serial port software, the call to Initialize_Serial_Comms()
in User_Initialization() should be removed or commented
out. The User_Initialization() function can be found in
the user_routines.c source file.
5) A #include statement for the serial_ports.h header file
must be included at the beginning of each source file that
uses the serial ports. The statement should look like this:
#include "serial_ports.h"
In addition, these five things must be done before the
modified printf() function will work correctly:
1) You must add the printf.c/.h source files to your MPLAB
project.
2) As this software is intended to replace the default
printf() function, the printf_lib.c/.h files need to be
removed from your MPLAB project.
3) All #include references to printf_lib.h must be commented
out or removed.
4) A #include statement for the printf.h header file must
be included at the beginning of each source file that uses
the printf() function. The statement should look like this:
#include "printf.h"
5) To support terminal emulation software,
should
be used instead of just
in the printf() format string.
As mentioned above, this version of the printf() function can
send it's output to either of the serial ports by altering the
value of the global variable "stdout" before calling the
printf() function. Setting the value to "ONE" will send the
output to serial port one. Likewise, setting the value to
"TWO" will send the output to serial port two (these are
#define'd in printf.h).
As an example,
stdout = ONE;
printf("Hello");
stdout = TWO;
printf("World!");
will send the text "Hello" to the peripheral device attached
to serial port one and the text "World!" to the device
attached to serial port two. By default, output is sent to
serial port one.
Kevin Watson
[email="[email protected]"][email protected][/email]