Programming a New Development Board

When starting a new project on either a development board or a board of my own design, rather than trying to do everything in one huge programming effort, I break the project down into small pieces and work towards the end goal in small sections.  This process really saves on  frustration and makes troubleshooting easier when problems occur.

I'll use the Sure Electronics PICDEM+ board as an example for the following discussion.  It's got a PIC18F4520 and number of devices installed including an LCD display, a 4 digit, seven-segment LED display, an I2C EEPROM (24C02) and temperature chip (LM75), a buzzer and some LEDs and switches.  Some of these devices share port pins, so you can't use everything at once, but it's a good platform for development.  It's also got an ICSP connector (location) and a USB interface via a CP2102 USB - UART bridge.  Sure Electronics sells mainly on ebay, with a very good reputation.

Sure_Dem2PLUS


Determine Board Layout

My first step is to determine the layout of the circuit - which port pins are connected to what.  If this is a board of your own design, you will already know but if this is a commercial development board, it may take some research.  Check the documentation, look at the schematic and even examine the pc card to determine connections.  Fortunately, the Sure board has schematics available and many of the port pin functions are silk-screened on the board.  I make a list of connections, and usually include it as a comment section at the beginning of the code.  Below is from one of my first programs on the Sure Electronics board.  Note that I'd included relevant comments to help remember the details in the future.

{ Port Arrangements
 
Port B0 = LED 1    Note: LED1 and S2 share PORTB.0 - so sharing is difficult
Port B1 = LED 2
Port B2 = LED 3
Port B3 = LED 4
Note: LOW = LED ON
 
Switches
S1 = RA4
S2 = RB0 Note: LED1 and S2 share PORTB.0 - so sharing is difficult
Note: Pressed = LOW
 
Port C2 (CCP1) = speaker
Note: PWM to make a tone
 
I2C Temperature Sensor
LM75A
addr:$90
SCL   C3/C4
SDA   C3/C4
 
EEPROM
24C04
addr:$A0
SCL   C4
SDA   C4
 
USART --> USB Output
CP2102 USB/Series Bridge
Port C6(TX)
Port C7(RX)
 
Seven Segment LED Display (multiplexed digits) = 4 Digits
 
Port D pins --> a - h segment pins of seven segment displays
Port B 4 - 7 --> Digit cathodes 0 - 3
 
HD44780 Character LCD Module
2 Line x 16 character
Port D = Data port
Port A1 = E
Port A2 = RW
Port A3 = RS
R28 = contrast (manual)
Port C1(CCP2) PWM voltage generator for contrast 
 
 
PORT ASSIGNMENTS
 
A0
A1  LCD E
A2  LCD R/W
A3  LCD RS
A4  S1
A5
 
B0  LED1            S2
B1  LED2
B2  LED3
B3  LED4
B4  Seven Segment Display  cathode digit 0
B5  Seven Segment Display  cathode digit 1
B6  Seven Segment Display  cathode digit 2     ICSP
B7  Seven Segment Display  cathode digit 3     ICSP
 
C0
C1  CCP2 ---> LCD Contrast
C2  CCP1 ---> spkr
C3  IIC SCL
C4  IIC SDA
C5
C6  Serial TX
C7  Serial RX
 
D0  LCD DB0     Seven Segment Display  segment a
D1  LCD DB1     Seven Segment Display  segment b
D2  LCD DB2     Seven Segment Display  segment c
D3  LCD DB3     Seven Segment Display  segment d
D4  LCD DB4     Seven Segment Display  segment e
D5  LCD DB5     Seven Segment Display  segment f
D6  LCD DB6     Seven Segment Display  segment g
D7  LCD DB7     Seven Segment Display  segment h
 
E0
E1
E2
 
}

While determining connections from the schematic, it's also useful to determine the sense of LEDs and switches.  LEDs may be connected between V+ and the port pin, in which case, a LOW pin will activate the LED, or may be connected between the port pin and ground, which requires a high port pin to activate.  See the drawing below.  Similarly, a switch might be connected between ground and the port pin and pulled high, so a press results in the pin going low, or may be connected between V+ and the port pin and pulled low, in which case a press results in a high port pin.  Either sense is equally valid, but to make a program work as planned, you need to know what to expect.

LED_and_Switch

Finally, while looking at the schematic, determine the part numbers for any other chips installed.  Consult the data sheet and schematic to determine the address of any I2C chips (EEPROM and a temperature sensor in this case) installed.  Data sheets for I2C chips will get a good workout, so keep them close at hand. Oh yeah, one last thing.  Determine what PIC is installed and the crystal frequency. This is a lot of homework but it will prevent interrupting the flow once the coding does start.

Code Development

The first program you should write for a new project is a program to flash an LED on the board.  Do this every time.

Device = 18F4520
 
Clock = 20
 
Dim LED1 as PORTB.0
 
While 1 = 1
 
HIGH(LED1)
 
Delayms (1000)
 
LOW(LED1)
 
Delayms (1000)
 
wend

Why such a trivial little program when you have far bigger things in mind?  Because if the trivial program won't work, nothing else will!  This checks that the PIC is actually running, that the programmer is working, the power supply is ok, and all the little gotcha's along the way.  If this doesn't work, check for obvious problems, like no power (yes, it happens), the programmer is connected (yes, this happens too), the correct oscillator settings, the port pins really are connected like you think they are, and that any jumpers on a development board are in the right positions. Take a few seconds to congratulate youself on a job well done if you are rewarded with an LED flashing on and off at a one second rate.

Next Steps

Once I know the board is somewhat functional, I start creating a program framework to match the board.  In this case, it makes sense to assign variables to each LED and switch and verify operation of each.  You can get a little creative here.  Flash each LED in turn to verify connections.  Light up LEDs according to switch presses.  Exercise each LED and switch to see that they work in the expected way. It was during this phase that one of the pesky shared port pins hit home.  Look at PORTB.0 in the above listing.  It is shared by an LED and a switch.  Pressing the switch turns on the LED with no help from the microprocessor.  But if the LED is set to on by the microprocessor, pressing the switch has no impact on the level seen on the port pin!  Not a huge problem as long as design your application around this detail.


A Word About Programmers

It goes without saying that the code generated by Swordfish has to get into the PIC microprocessor somehow.  There are many programmers available for PIC; the key point to consider is how the PIC is programmed: 1.  The PIC is put into a socket on the programmer:  When a program is to be loaded, the PIC is placed in a socket on the programmer.  This kind of programmer is pretty simple to build, but a pain-in-the-backside to use!  The PIC must be removed from the dev board, plugged into the programmer and then replaced.  This is time-consuming and there's the risk of bent or broken pins.  In the case of the board we're looking at here, this isn't even an option as the PIC is surface mount and soldered to the board. 2.  Bootloader:  A bootloader can be installed on the PIC.  When the PIC is reset, a signal is sent from the serial port, at which time a boot loader program can load a program to the PIC.  If no response is seen on the serial port, the existing program is executed.  Swordfish comes with MCLoader which works well, but bootloader code is required on the PIC to allow this to work.  If you have a socketed PIC, a programmer like the above can be used to load the boot loader code once, and then the bootloader will allow programming without removing the PIC again.  The bootloader code can also be loaded by ICSP (in-circuit serial programmer) - see the following. 3.  ICSP: Two port pins on most PIC chips can be used for in-circuit serial programming.  The most popular ICSP programmer is the PICKit 2.  It's connected via a 6 pin connector to program the PIC.  An ICSP is a must-have when working with surface mount PICs.  It can be used to load boot-loader code so that MCLoader can be used, or it can be used each time the PIC is programmed.

ICSP_Conn


UART/Serial Communications

The next step is to test out the UART/serial communications functions on the board.  This board has a CP1202, which provides a serial link via USB.  Data can be sent to and from the board with a terminal emulation program like Graham's iHyperTerminal.  Swordfish can use either the hardware UART or a software UART.  The hardware UART uses dedicated transmit and receive pins on the PIC while the software UART can use any port pins.  From the above port list, we can see that PORTC.6 is used as the transmit line and PORTC.7 is the receive line to the CP1202 bridge.  Checking the PIC18F4520 data sheet, we can see that these pins correspond to the hardware UART, so using the hardware UART will give us the best performance. The pin diagram is a handy place to get an overview of the multiple functions assigned to each PIC pin.

Pin_Diagram

Swordfish has modules to support either the hardware UART or software UART, so implementing serial communications is pretty easy.

device = 18F4520
 
Clock = 20 'this corresponds to the crystal frequency   include "USART.bas"     USART.setbaudrate(br9600)     While 1 = 1   USART.write ("Digital-DYI gets me going." , 13, 10)   we

Notice the SetBaudRate command in this code. It needs to be set to the same speed in the PIC and in the terminal program on the PC.  If you see gibberish on the terminal screen, chances are that the baud rate is not set correctly.  The baud rate generator depends on knowing the correct clock frequency, so the correct clock frequency must be selected (note: the clock frequency may be different than the crystal frequency depending on the oscillator configuration).  Also note in the USART.write statement the 13 and 10; this corresponds to the ASCII codes for carriage control and line feed so that a new line is printed for each cycle.

Character LCD Display

This board has a built-in LCD display, compatible with the standard HD44780 controller.  Swordfish has an LCD module to help us out.  There is no standard port arrangement to connect an LCD module, so we need to define options prior to loading the LCD module to let Swordfish know what pins to use.

Device = 18F4520
 
Clock = 20
 
// LCD Settings
#option LCD_DATA = PORTD
#option LCD_RS = PORTA.3
#option LCD_EN = PORTA.1
#option LCD_RW = PORTA.2
 
 
// import LCD library...
Include "LCD.bas" 
 
Include "utils.bas"
Include "convert.bas"
 
SetAllDigital
 
LCD.Cls 'clear the LCD   while 1 = 1   LCD.WriteAt (1,1, "Digital-DYI") LCD.WriteAt (2,1, "gets me going.")   wend


The option statements define the interface pins for the LCD and must be specified before including the LCD module.  utils.bas and convert.bas include some common functions that are useful to have, including SetAllDigital, which configures ports (PORTA in this case) that have analog and digital capabilities.

The WriteAt command controls the line and character position where the text will be printed.

Module Best Practices

This would be a good place to mention best practices when using modules.  The command Write is used in a number of modules.  When Swordfish compiles a program, it first checks to see if a command is part of the basic library.  If not, it continues looking through the include files until it finds a matching command.  In the case of write, it might send something to the USART, the LCD, EEPROM or other places, depending on which module was loaded first.  If we extend the command to USART.Write, Swordfish then knows to look in the USART module to find the command.  The simple Write command will work, but as you add to a program, that which was perfect may give you unexpected results.

What Next?

If you assemble these pieces, you're got a good framework to continue code development.  You've got a PIC that functions, outputs via LED, UART or LCD and inputs via switches or UART.  From here, the direction depends on what you're trying to accomplish.  For each new hardware component or function, test how it works in small pieces.  If you're developing a new algorithm or procedure, test to be sure it gives the results it should.  Once you have the pieces working, build the "big stuff" from the tested parts.

Using a development board such as this board from Sure is a good method to check out hardware and software before designing a dedicated pc board, and to make sure the hardware works as conceived.

Forum Activity

Member Access