Issue
101 December 1998
em
Ware Top to Bottom
Part
2: Launching the Application
THE
CODE
I
discussed Visual Café in the previous installment. Remember
that before emWare V.2.5, one had to code the HTML-laced
GUI. With Visual Café, that task becomes much easier.
But, I wont dwell on Visual Café here. Instead,
Ill take apart a simple PIC/emWare application
line by line.
Some
time ago, I built a real-time PIC emulator for PIC16C5x
devices. It consisted of lots of latch logic coupled
to memory and a proprietary bondout device.
The
design was simple enough, but the necessary software
was really heavy. I moved quite a few units and found
that most of us like to know whats going on inside
the devices we write apps for. The application Im
about to examine is a simpler version of that old emulator.
Listing
1 is a code snippet that defines and computes the data-rate
generator value versus the crystal frequency. Note that
a crystal frequency of 10 MHz is used to derive a data-rate
value for 9600 bps. This formula is provided in the
datasheet for the PIC16C73.
| Listing
1—The include statement keeps you from having
to remember all those funny register names.
|
You
can compute this data rate outside the program and insert
it manually, but why not use the power of the PIC Macro
assembler? Thats just what I did.
Two
bits are also defined in Listing 1. These bits are used
in the serial communications portion of this application.
Their names tell the story. By the way, the __CONFIG
parameter denotes the use of an HS oscillator with no
watchdog timer and no code protection.
Listing
2 is simply a macro declaration. Some of the more complex
PICs use pages to multiplex register addresses. As you
see in the macro definitions, the PIC16C73 is one of
these devices.
| Listing
2Its
just as easy to only code these, but its easier
to read this way. |
A
single bit in the Status register delineates page 0
and page 1. When youre programming PICs with pages,
it can get confusing as to which page youre on
and whether you swapped that page bit or not. Using
a macro cuts down on the confusion factor when things
just dont act right in the application.
The
beginning of Listing 3 looks like code for a bunch of
other microcontrollers. The first line jumps over the
interrupt vector. The PIC16C73 can be interrupted on
an A/D conversion, serial communications event, timer
event, capture event, or change in I/O-port status.
So, it could be important to keep the interrupt vector
area coded for such possible events if your program
is so inclined.
| Listing
3—Note the inclusion of the two EMIT modules.
These tie the app to emWare code. |
Beginning
at the label loop0, the same sequence of events takes
place as with the 8051 version of EMIT. This observation
is also true for all other devices. All micros need
some type of initialization that prepares them for the
task at hand.
Here,
the first call is to the InitMicroController subroutine.
Listing 4 details the first call in this subroutine.
| Listing
4Initializing
ports on the PIC is important because of the complex
nature of the I/O module. |
The
first job is to transfer the calculated data-rate value
to the data-rate register SPBRG. If youre new
to PIC and are wondering where all these funny register
names come from, theyre defined in an include
file that Microchip provides.
The
PIC16C73 multiplexes different tasks onto a single pin.
So, its necessary to set certain bits to define
the actions of a particular pin. Also, since the PIC16C73
uses a USART and not a UART, you must tell the PIC if
the communications sequence will be asynchronous or
synchronous.
Next,
you need to set up the I/O-port pins. InitPortAB executes
this function. For the purposes of this application,
both ports A and B are defined as outputs.
To
complete this process, a byte of zeros is written to
the corresponding TRIS ports. All I/O ports can be defined
as input or output. In input mode, the port pins are
high impedance.
The
PIC16C73 provides a third I/O portport C. Listing
5 maps out the pin definitions. Note that I included
an I2C interface for future use. Theres no doubt
that it will provide an interface to a Microchip EEPROM
device. For the PIC-challenged out there, Listing 5
is a good example of how to define input and output
functions of I/O-port pins.
| Listing
5—Here’s a good example of how the PIC spins
the pins. |
Following
along under InitMicroController, the next step is to
set up the Option register. This register enables the
programmer to define port B pull-up status, interrupt
edges, timer clock sources, and timer prescaler values.
Weak
pullups on port B are enabled in the application and
the timer is prescaled by a value of 32. Writing a binary
01000100 to the Option register does it all.
The
next logical step is to enable or unmask any interrupt
options you deem necessary for the application. Notice
that the serial communication pin interrupts are unmasked
but not enabled.
emWare
uses a round-robin approach. Each part of the EMIT program
must have equal access to processor resources. Otherwise,
data may be lost and processes may hang. Later on, youll
see that the communications resources are being polled.
About
the only thing left to do now is I/O-port initialization.
Here, simply setting the ports to 0 is sufficient. Listing
6 shows the final three init procedures. The call to
set the ports to 0 is found under loop0.
| Listing
6—The 8051 version of EMIT used a serial interrupt.
The semicolon is all that stops you here.
|
By
convention, emMicro code is included in the source code,
so its routines can be called from within the program.
Any included files are declared at the end of the user-written
application code.
One
such routine, EmInit, is always called at least once
in every EMIT program to initialize emWare. Youll
find the call to EmInit at label loop0. Once all of
the initialization is completed, you can turn on the
interrupts you unmasked.
The
next label, loop3, is the main program loop. It polls
the serial communications pins for incoming bits and
checks if any data is waiting to be transmitted.
My
application enables the user to manipulate (read and
write) the PICs internal registers. I provided
functions for that purpose that are called directly
from widgets on emWares GUI. My application really
does nothing but loop, waiting for commands from the
GUI.
As
Listing 3 shows, a call to MyApplication simply executes
a return from subroutine. If other programmatical operations
are needed, they are performed under the MyApplication
label.
If
any EMIT processes are requested, the next call to EmMicroEntry
processes them. Once this routine is entered, all table
lookups and EMIT-related processes will be completed
before this module is exited.
loop3
is where the round-robin processing occurs. Each call
is designed to give EMIT time to process any requests
it receives. No call in loop3 should wait for any input
or output process to provide a status. Such a wait can
induce a hang condition, causing EMIT to miss data and
commands it needs to process.
Now,
Ive successfully initialized a PIC16C73 to communicate
via RS-232 to an Advantech PCM-4862 equipped with EMIT
and a web browser.
By
including the emWare PIC code in the source, I enabled
the PIC16C73 to pass data to and receive commands from
the EMIT software interface. The results are controlled
and displayed by a web browser using a GUI that I designed
with Visual Café.