You are on page 1of 3

ECE 376 - JSG

March 7, 2005

CHESS CLOCK
ECE 376 - Lab #4
Purpose: The purpose of this lab is to
Write a program which has several interrupts going at the same time
Timer2 interrupts to keep track of time, and
INT interrupts to record when one button was pressed, and
a Timer1 interrupt when a second button is pressed.

Use an LCD display to convey information from a PIC processor.


Requirements:
The device built in this lab should have the following features::
Operate off the PIC Evaluation Boards.
Two times are to be displayed as M:SS.SSMinutes, Seconds) for times up to 5 minutes.
Internal times should be accurate to 0.01 second.
When Reset (or on power on), both times are set to 5 minutes with neither time decrementing.
When RB0 is pressed (Player #1 button), the time for Player #2 will decrement every 0.01 second (and Player #1s time is
held)
When RB1 / RC0 is pressed (Player #2 button), the time for Player #1 will decrement every 0.01 second
When Player #1's time reaches zero, PC7=1 (signifying that Player #1 has lost on time) and the clock should stop
When Player #2's time reches zero, PC6=1 (signifying that Player #2 has lost on time)
Circuit Diagrams: (PIC Evaluation Board)

+5

LCD

PIC16F876

MCLR

Reset

RB7
RB6
RB5
RB4
RB3
RB2
RB1
RB0

28
27
26
25
24
23
22
21

20

Vdd

OSC1

20MHz

22pF

RC7
RC6
RC5
RC4
RC3
RC2
RC1
RC0

18
17
16
15
14
13
12
11

RA4
RA3
RA2
RA1
RA0

6
5
4
3
2

100
+5

Push Button
(ditto RB1)

+5

22pF

100

D7
D6
D5
D3
E
R/S

1k

10k
10

8
19

OSC2

Vss
Vss

LED

Jumper

ECE 376 - JSG


March 7, 2005

Procedure:
1) Start MPLAB. Copy the file C:/MPLAB/ECE376/LAB4/CHESS.ASM to something else under the same directory (such as
Group0.ASM). Create a new project with the same name
Project New (Group0.pjt)
Node Properties (decimal default, error level = errors only, PIC16F873)
Add Node: Group0.asm
2) Compile your project and download it to the PIC processor.
When you run the program, the LCD display should have a message similar to the one shown below. This tells you
that both players have 5 minutes remaining (0x7530 x 10ms). The time is initially displayed in hexadecimal format (i.e.
programmer friendly format) rather them minutes - seconds (user friendly format)

Chess Clock
Player #1: 0x7530

Player #2: 0x3F2C


3) Modify the Timer2 interrupt service routine so that when a player's timer decrements to zero, it stops decrementing.
Note how large your code is.
4) Modify the Display routine so that you display time as minutes : seconds : hundredths of seconds
mm:ss.hh
Note how large your code is and how much space is taken up by the user interface routine (i.e. conversion from
computer0friendly hexadecimal to user-friendly decimal.)
5) Modify the main routine so that
Time2 interrupts are turned on every 1ms (should be 10ms, byt it runs 10x faster this way)
INT interrupts are turned on for rising edge interrupts, and
Timer1 External Events Interrupts are turned on for every 1 event.
Modify the interrupt service routine so that
When an INT interrupt happens (RB0 goes high) it becomes player #2's turn
When a Time1 interrupt happens (RC0 goes high) it becomes player #1's turn
6) Modify the main routine so that on reset it is neither player's turn.
Check to see that when the time gets to zero, it stops decrementing and turns on a light indicating time's up.
Check that this program still works and measure the 5 minute timer. (or 1/10th of 5 minutes).
Write-Up:
(Analysis & Data Sections)
Include computations for setting up the Timer2 interrupt and the actual interrupt time measured in this lab
(Requirements & Results)
How well does a PIC16F876 chip work for building a chess clock? Include comments on
- The size of your code (is 8k big enough?)
- The number of I/O lines (22 lines are available, how many are used?)
- How difficult it is to build the hardware (How many components are required to build a chess clock?)
- How difficult it is to write the assembler code (starting from a bare-bones model of course)
(Purpose & Conclusions)
Describe what an interupt is
Describe how / why a timer interrupt is uuseful
Describe the procedure for using top-down programmingWhat is an interrupt?
Describe how an LCD compares to a set of LED's in terms of displaying information.

ECE 376 - JSG


March 17, 2003
// --- Lab 4 ------------------// Chess Clock
//
// This program creates a chess clock on the PIC
// evaluation boards. Timer2 interrupts are used
// to keep track of time accurate to 10ms while
// RB0 and RC0 are used as the inputs for the
// two players.
//
//-------------------------------// Revision History
//
3/24/03: Starting program (jsg)
//
//-----------------------------// Global Variables
unsigned int Time1;
unsigned int Time2;
unsigned char Turn;

// time left for player #1 (x 10ms)


// time left for player #2
// whose turn it is (1 or 2)

}
// Main Routine
void main(void)
{
TRISC = 0;
TRISB = 0;
lcd_init();
Wait_ms(100);
lcd_msg();

//

Timer2_Init();

// initialize Timer2 for 10ms

Turn = 0;
Turn = 1;

// Start out with no-one's turn.


// for debugging, start as player #1

Time1 = 30000;
Time2 = 30000;
// Subroutine Declarations
#include
<pic.h>
#include
<string.h>
#include
"lcd_20x4.h"
#include
"function.h"
#include
<math.h>
// Subroutines
#include
#include
#include
#include

// initialize the LCD

GIE

// start at 5 minutes (30,000 x 10ms)

= 1;

do {
if (!RB0) Turn = 1;
if (!RB1) Turn = 2;

"lcd_20x4.c"
"lcd_msg.c"
"function.c"
"bootlaoder.c"

void interrupt IntServe(void) @ 0x10


{
if (TMR2IF) {
// check if it was a Timer2 interrupt
RC7
= !RC7;
if (Turn == 1) Time1 -= 1;
if (Turn == 2) Time2 -= 1;
TMR2IF = 0;
}
if (INTF) {
// if button #0 was pressed
INTF = 0;
}
if (TMR1IF) {
// if button #1 was pressed
TMR1IF = 0;
}
}

void Timer2_Init(void)
{
T2CON
= 0x47;
PR2
= 100;
TMR2IE = 1;
PEIE
= 1;
TMR2ON = 1;
}

// 10ms interrupt rate

// Display the time left as


//
mm:ss.hh
// Initially, this routine displays the raw data in hex format.
void Display_Time(unsigned
{
lcd_write('0');
lcd_write('x');
lcd_write(ascii(Time >>
lcd_write(ascii(Time >>
lcd_write(ascii(Time >>
lcd_write(ascii(Time));

int Time)

12));
8));
4));

RC1 = !RC1;
lcd_move(1,11);
Display_Time(Time1);
lcd_move(2,11);
Display_Time(Time2);

} while (1>0);
}

// Watch the main loop on RC1