I use PortB interrupt on change to adjust minutes and hours. Timer 0 overflow interrupt makes a precise timing ticks. It create a one millisecond counting and schedule the SSD. SSD made up of four digits. Each digit turns on for 10 milli second period. The overall time of SSD takes about 40 milli seconds.
Schematic diagram. PortB create an interrupt on change to adjust minutes and hours. PortC and PortD displays the timing to SSD. The SSD is common anode. We can use common cathode data with inverting. |
Source code is here.
#include "xc.h"
// PIC16F887 Configuration Bit Settings
// CONFIG1
#pragma config FOSC = XT
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = ON
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = ON
#pragma config IESO = ON
#pragma config FCMEN = ON
#pragma config LVP = OFF
// CONFIG2
#pragma config BOR4V = BOR40V
#pragma config WRT = OFF
unsigned int cnt_0=0;
unsigned int cnt_1=0;
unsigned int cnt_minute=0;
unsigned int oneSecond=0;
unsigned int milliCount=0;
unsigned int _minutes=0;
unsigned int _hours=0;
void ssdOut(void){
static unsigned char dot=0;
unsigned char ssd[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,
0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
if(milliCount>=1000){
oneSecond+=1;
milliCount=0;
dot^=0x80;
}
if(oneSecond>=60){
oneSecond=0;
_minutes+=1;
}
if(_minutes>=60){
_minutes=0;
_hours+=1;
if(_hours>=24) _hours=0;
}
switch (cnt_1){
//Digit 4 1000's
case 1:
PORTD=0x00;
PORTC=~ssd[_hours/10]^dot;
PORTD=0x08;
break;
//Digit 3 100's
case 2:
PORTD=0x00;
PORTC=~ssd[_hours%10]^dot;
PORTD=0x04;
break;
//Digit 2 10's
case 3:
PORTD=0x00;
PORTC=~ssd[_minutes/10]^dot;
PORTD=0x02;
break;
//Digit 1 1's
case 4:
PORTD=0x00;
PORTC=~ssd[_minutes%10]^dot;
PORTD=0x01;
break;
case 5:
cnt_1=0;
break;
}
}
void portSetUp(void){
/*SSD display port setup*/
PORTC=0x00;
PORTD=0x00;
TRISC=0x00;
TRISD=0x00;
/*PortB digital I/O and
interrupt setup*/
PORTB=0x00;
TRISB=0x0F;
ANSELH=0x00;
nRBPU=0;
WPUB=0x0F;
IOCB=0x0F;
RBIE=1;
RBIF=0;
}
void timerSetup(void){
T0CS=0;
PSA=0;
OPTION_REGbits.PS=0x01;
T0IE=1;
GIE=1;
T0IF=0;
TMR0=0;
}
void main(){
portSetUp();
timerSetup();
while(1){
ssdOut();
}
}
void interrupt ISR(void){
/*Timer 0 Flag*/
if(T0IF){
cnt_0+=1;
/*one milli second tick*/
milliCount+=1;
T0IF=0;
}
/*IOCB flag*/
if(RBIF){
if(RB0==0){
if(_minutes>0) _minutes-=1;
}
if(RB1==0){
if(_minutes<60) _minutes+=1;
}
if(RB2==0){
if(_hours>0) _hours-=1;
}
if(RB3==0){
if(_hours<24) _hours+=1;
}
RBIF=0;
}
/*SSD timing*/
if(cnt_0>10){
cnt_1+=1;
cnt_0=0;
}
}
Simulation screen shot is here.
A simulation screen shot, displaying an adjusted time while the counter tick is running. |
Back to main tutorials page.
No comments:
Post a Comment