PIC16F84 and LCD chronograph
Circuit Description
This applet demonstrates a
PIC16-based controller for a digital clock/chronograph
The circuit consists of the microcontroller,
a standard ASCII-mode liquid-crystal display,
and two switches.
Press the input switches to control the stopwatch interactively; open the PIC user-interface to watch the program execution, setting breakpoints, etc. (I recommend to uncheck the 'update display' checkbox and to click the data and program memories to enforce repainting. This saves a lot of CPU cycles and makes the animation of the clock go smoothly).
The LC display show the current time or switch to chronograph mode. In chronograph mode, the user can start/stop or
clean and restart. Click again on mode switch to show the current clock time.
(Note that the simulation might run slower than real-time in the stopwatch
mode, due to the very high number of repaints of the LCD.)
The C source code has been written by the
student Douglas, Edson, Elisangela, Hilario and Fernando during the Computer Organization Undergraduate Course, Universidade Federal de Viçosa, Brazil.
The following C code is used for the watch. Note, a special symbol (on left LC display, like a big I inside a circle) was built by using 4 customized new characteres.
You can also download an
archive file (.tar.gz)
with the source code and header files.
// /usr/hitech/bin/picl -16f84 -C -Zg chronograph.c lcd.c delay.c
// /usr/hitech/bin/picl -16f84 -Ochronograph.hex \
// chronograph.obj lcd.obj delay.obj
#include
#include "lcd.h"
#include "delay.h"
#define FATOR 5
// 500kh / 4 = 125 khz
// 8.0 e-6 * prescalar * (256-131) * factor
// 2 125 5 = 0.01 seconds
static bit LCD_RS @ ((unsigned)&PORTA*8+2); // Register selec
// clock
char h = 23; //Initial Hour
char m = 59; //Initial Minute
char s = 59; //Seconds
// chronograph
char m_cr = 0; // Minute
char s_cr = 0; //Seconds
char c_cr = 0; //Cents
char centesimos = 0; //clock cents
char inicia_cr=0;
char Aux=0;
char ajuste = 0;
char i = 0;
char show = 0; // Control variable print in LCD
char n = 0 ;
char oldrb4 = 0;
// Create a LOGO by using
void CreateAndPrintCharacter(){
lcd_write(0x40);
lcd_putch(0x00); // 00000
lcd_putch(0x01); // 00001
lcd_putch(0x02); // 00010
lcd_putch(0x04); // 00100
lcd_putch(0x08); // 01000
lcd_putch(0x10); // 10000
lcd_putch(0x10); // 10000
lcd_putch(0x10); // 10000
lcd_write(0x48);
lcd_putch(0x1F); // 11111
lcd_putch(0x00); // 00000
lcd_putch(0x00); // 00000
lcd_putch(0x00); // 00000
lcd_putch(0x0E); // 01110
lcd_putch(0x0E); // 01110
lcd_putch(0x00); // 00000
lcd_putch(0x0E); // 01110
lcd_write(0x50);
lcd_putch(0x00); // 00000
lcd_putch(0x10); // 10000
lcd_putch(0x08); // 01000
lcd_putch(0x04); // 00100
lcd_putch(0x02); // 00010
lcd_putch(0x01); // 00001
lcd_putch(0x01); // 00001
lcd_putch(0x01); // 00001
lcd_write(0x58);
lcd_putch(0x10); // 10000
lcd_putch(0x10); // 10000
lcd_putch(0x10); // 10000
lcd_putch(0x08); // 01000
lcd_putch(0x04); // 00100
lcd_putch(0x02); // 00010
lcd_putch(0x01); // 00001
lcd_putch(0x00); // 00000
lcd_write(0x60);
lcd_putch(0x0E); // 01110
lcd_putch(0x0E); // 01110
lcd_putch(0x0E); // 01110
lcd_putch(0x0E); // 01110
lcd_putch(0x0F); // 01111
lcd_putch(0x0F); // 01111
lcd_putch(0x00); // 00000
lcd_putch(0x1F); // 11111
lcd_write(0x68);
lcd_putch(0x01); // 00001
lcd_putch(0x01); // 00001
lcd_putch(0x01); // 00001
lcd_putch(0x02); // 00010
lcd_putch(0x04); // 00100
lcd_putch(0x08); // 01000
lcd_putch(0x10); // 10000
lcd_putch(0x00); // 00000
// imprime a logomarca
lcd_goto(0);
lcd_putch(0);
lcd_goto(1);
lcd_putch(1);
lcd_goto(2);
lcd_putch(2);
lcd_goto(64);
lcd_putch(3);
lcd_goto(65);
lcd_putch(4);
lcd_goto(66);
lcd_putch(5);
}
void SendNumbertoLCD(char n)
{
char c;
c = (char)((n/10)+48); // Dezena
lcd_putch(c);
c = (char)((n%10)+48); // Unidade
lcd_putch(c);
}
main(){
TRISA = 0x00; // Output bits porta, xESRx
TRISB = 0xF0; // Input bits portb 7654xxxx, Output Bits xxxx3210
// ******* INTERRUPÇÕES EM TMR0 *********
T0IE = 1; // 1 - Enable TMR0
// 0 - Disable TMR0
T0IF = 0; // Clean TMR0 flag
T0CS = 0; // clock source
// TMR0 ( 1 -> RA4, 0 -> internal clock )
// prescaler
PSA = 0; // ( 0 - on; 1 - off ) prescaler -> TMR0
PS2=0; // pre-scaler 1:8
PS1=0; // clock 1MHz
PS0=0;
TMR0=130;
lcd_init();
CreateAndPrintCharacter();
lcd_goto(5);
lcd_puts("00:00:00");
GIE = 1; // Global Interruption Enable
lcd_goto(69);
lcd_puts("http://www.dpi.ufv.br");
while(1){
if (show) {
// RB4 = clock/cronograph
// RB5 = start/stop
// RB6 = clean
if(RB4 == 0 ){
if ( (centesimos == 0) || oldrb4 ) {
oldrb4 = 0;
lcd_goto(5);
SendNumbertoLCD(h);
lcd_goto(8);
SendNumbertoLCD(m);
lcd_goto(11);
SendNumbertoLCD(s);
}
if(RB5 == 0 && inicia_cr == 0){
m_cr = 0;
s_cr = 0;
c_cr = 0;
}
if (RB5 == 1){
ajuste++;
if (ajuste >3)
ajuste=1;
}
while (RB5 == 1){
if (RB6 == 0)
n = 0;
if (RB6 == 1 && n == 0){
if (ajuste == 1)
h++;
else if (ajuste ==2)
m++;
else if (ajuste == 3)
s++;
n=1;
}
lcd_goto(5);
SendNumbertoLCD(h);
lcd_goto(8);
SendNumbertoLCD(m);
lcd_goto(11);
SendNumbertoLCD(s);
}
}
else if(RB4 == 1 ){
if(RB5 == 0){
if( Aux == 1){
Aux = 0;
}
}
else{
Aux = 1;
}
lcd_goto(5);
SendNumbertoLCD(m_cr);
lcd_goto(8);
SendNumbertoLCD(s_cr);
lcd_goto(11);
SendNumbertoLCD(c_cr);
if(RB6 == 1){
m_cr = 0;
s_cr = 0;
c_cr = 0;
}
}
show = 0;
}
}
}
static void interrupt isr(void) {
// se interrupção em TMR0
if ( T0IF == 1 ) {
i++;
TMR0=130;
if ( i == FATOR ) {
i = 0;
centesimos++;
if( Aux == 1)
c_cr++;
show = 1;
}
if(centesimos == 100){
s++;
centesimos = 0;
}
// hour
if ( s == 60 ) {
m++;
s = 0;
}
if ( m == 60 ) {
h++;
m = 0;
}
if ( h == 24 ) {
h = 0;
}
// cronograph
if ( c_cr == 100 ) {
s_cr++;
c_cr = 0;
}
if ( s_cr == 60 ) {
m_cr++;
s_cr = 0;
}
if ( m_cr == 60 ) {
m_cr = 0;
}
T0IF = 0; // zera flag de interrupcao em TMR0
}
}
|