Code: Select all
INTCON.GIE = 1; //Enable all unmasked interrupts.
INTCON.T0IE = 1; //enable timer0 interrupt.
OPTION_REG = 0x00; //timer0 prescal 1:2
Code: Select all
void interrupt(){
counter++;
if(counter >= 1953) onesec = 1; // set a 1 second flag
}
Because PIC16F84A does not have enough I/O ports; a 74164 serial-in, parallel-out is needed to expand for display. Each individual segment cathode is connected to separate 330 ohm current limiting resistors while the common anode of each display is connected to Collector pin of a PNP transistor. Data is send from RA1 pin of MCU to A pin of 74164 ; and RA0 pin is connected to CLK pin of 74164 to send shift clock signal. The figure below shown 74164 logic diagram and truth table.
Press SW4 switch to on - off the timer.
Press SW3 switch to increase second from 0 - 59.
Press SW2 switch to increase minute from 0 - 99.
Press and release SW1 switch to recall time from EEPROM. Press and hold SW1 for 2- 3 second for store current time into EEPROM.
Code: Select all
#define sClock PORTA.F0
#define sData PORTA.F1
#define OutPut PORTA.F2
char onesec = 0;
int counter = 0;
char key_press = 0;
char On_status = 0;
char Digit_map[10] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
char current_sec = 0;
char current_min = 0;
char first_digit, second_digit;
char third_digit, forth_digit;
char timeout = 0;
void interrupt(){
if(INTCON.T0IF == 1) {
counter++;
if(counter >= 1953) {
onesec = 1;
counter = 0;
if(PORTB.F4 == 0) {
timeout ++;
onesec = 0;
}
}
if (onesec == 1){
onesec = 0;
if (current_sec == 0) {
if(current_min > 0) {
current_sec = 59;
current_min --;
}
else current_min = 0;
}
else current_sec --;
first_digit = current_sec % 10;
second_digit = current_sec/10;
third_digit = current_min % 10;
forth_digit = current_min / 10;
}
INTCON.T0IF = 0; // clear interrupt flag
}
}
// ----- Shift Out function --------------------------
void Shift_OutMSB (char sd) {
char i;
char mask = 128;
for (i=1; i<=8; i++){
if (!(sd&mask)) sData = 0; else sData = 1;
sClock= 1;
delay_us (1);
sClock = 0;
mask = mask >> 1;
}
}
void delay(){
delay_ms(5);
}
void delay20ms(){
delay_ms(20);
}
void time_display(){
Shift_OutMSB (Digit_map[first_digit]);
PORTB.F0 = 0;
delay();
PORTB.F0 = 1;
Shift_OutMSB (Digit_map[second_digit]);
PORTB.F1 = 0;
delay();
PORTB.F1 = 1;
Shift_OutMSB (Digit_map[third_digit]);
PORTB.F2 = 0;
delay();
PORTB.F2 = 1;
Shift_OutMSB (Digit_map[forth_digit]);
PORTB.F3 = 0;
delay();
PORTB.F3 = 1;
}
void key_check(){
char temp_sec, temp_min;
if(PORTB.F7 == 0) {
//delay_ms(10);
if (On_status == 1) {
On_status = 0;
OutPut = 0;
INTCON.T0IE = 0; // disable interrupt timer
}
else {
On_status = 1;
OutPut = 1;
TMR0 = 0;
INTCON.T0IE =1; // enable interrupt timer
}
while (PORTB.F7 == 0) { time_display(); }
}
if(PORTB.F6 ==0) {
if (On_status == 0){
if (current_sec < 59 ) current_sec++;
else current_sec = 0;
first_digit = current_sec % 10;
second_digit = current_sec/10;
while (PORTB.F6 == 0) { time_display(); }
}
}
if(PORTB.F5 ==0) {
if (On_status == 0){
if (current_min < 99 ) current_min++;
else current_min = 0;
third_digit = current_min % 10;
forth_digit = current_min/10;
while (PORTB.F5 == 0) { time_display(); }
}
}
if(PORTB.F4 == 0) {
On_status = 0;
OutPut = 0;
INTCON.T0IE = 0; // disable interrupt timer
temp_sec = Eeprom_Read(0x00);
delay20ms();
temp_min = Eeprom_Read(0x01);
delay20ms();
TMR0 = 0;
INTCON.T0IE =1; // enable interrupt timer
while (PORTB.F4 == 0) { time_display(); }
INTCON.T0IE = 0; // disable interrupt timer
if(timeout > 1) {
timeout = 0;
EEprom_Write(0x00, current_sec);
delay20ms();
EEprom_Write(0x01, current_min);
delay20ms();
}
else {
current_sec = temp_sec;
current_min = temp_min;
timeout = 0;
}
first_digit = current_sec % 10;
second_digit = current_sec/10;
third_digit = current_min % 10;
forth_digit = current_min / 10;
}
}
void main() {
TMR0 = 0;
INTCON.GIE = 1; //Enable all unmasked interrupts.
INTCON.T0IE = 0; //disable timer0 interrupt.
OPTION_REG = 0x00; //timer0 prescal 1:2
INTCON.RBIF = 0; // clear interrupt onchange flag
PORTB = 0xFF;
TRISB = 0xF0; //PORTB4-7 = inputs, 0-3 = output.
TRISA = 0; // PORTA = output.
PORTA = 0;
first_digit = current_sec % 10;
second_digit = current_sec/10;
third_digit = current_min % 10;
forth_digit = current_min / 10;
while(1){
key_check();
time_display();
if(current_min == 0 & current_sec == 0){
OutPut = 0;
On_status = 0;
INTCON.T0IE = 0; // disable interrupt timer
}
}
}