circuitcellar.com
Magazine Support   Digital Library   Products & Services   Suppliers Directory 
 
 





 

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 won’t dwell on Visual Café here. Instead, I’ll 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 what’s going on inside the devices we write apps for. The application I’m 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? That’s 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 2It’s just as easy to only code these, but it’s easier to read this way.

A single bit in the Status register delineates page 0 and page 1. When you’re programming PICs with pages, it can get confusing as to which page you’re on and whether you swapped that page bit or not. Using a macro cuts down on the confusion factor when things just don’t 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 4—Initializing 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 you’re new to PIC and are wondering where all these funny register names come from, they’re defined in an include file that Microchip provides.

The PIC16C73 multiplexes different tasks onto a single pin. So, it’s 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 port—port C. Listing 5 maps out the pin definitions. Note that I included an I2C interface for future use. There’s 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, you’ll 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. You’ll 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 PIC’s internal registers. I provided functions for that purpose that are called directly from widgets on emWare’s 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, I’ve 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é.