Let’s make a Digital Clock to display seconds, minute & hour to seven segment displays. Here 6 seven segment display are used. We make it in 3 steps. First initial timer1 interrupt at 1s delay. In this project we use ATmega32 with external crystal with 8MHz at
HFUSE=0x89 LFUSE=0xEF
Timer1 interrupt with 1s counting
TCCR1B|=(1<<WGM12)|(1<<CS12); //MODE4 CTC with prescaler 256
TCNT1=0; //clear Timer
TIMSK|=(1<<OCIE1A); //Timer/Counter1 Output Compare Match Interrupt Enable
sei(); //Globel Interrupt Enable
OCR1A=31249; //F_CPU=8MHz,P=256,Delay=1s
In interrupt service routine we call the seven segment part to display. Now the second display in last 2 seven segments, minute in 3rd and 4th and hour in 5th and 6th. Say the digit is stored in an integer array. Then the control logic is-
digits [0]=second%10;
digits [1]=second/10;
digits [2]=minute%10;
digits [3]=minute/10;
digits [4]=hour%10;
digits [5]=hour%10;
We already learn about global variable. Now we used it. Declear int digits[6] in header file. In interrupt service routine-
uint8_t second,minute,hour;
ISR(TIMER1_COMPA_vect)
{
second++;
if(second==60){
minute++;
digits[2]=minute%10;
digits[3]=minute/10;
second=0;
}
digits[0]=second%10;
digits[1]=second/10;
if(minute==60){
hour++;
digits[4]=hour%10;
digits[5]=hour/10;
minute=0;
if(hour==24) hour=0;
}
}
Now for persistence of vision we previously used _delay_ms() function but in real time calculation we can’t used delay to hold CPU. So we use a timer in this case use Timer0 for 1ms duration. We don’t use interrupt service routine, rather that we use flag register.
void delay_ms_1(void)
{
while(!(TIFR&(1<<OCF0)))
{
//wait for 1ms until the flag is set
}
TIFR|=(1<<OCF0); //clear the flag
}
#include<avr/io.h>
#include<stdio.h>
#include<util/delay.h>
#include<avr/interrupt.h>
#include"count.h"
int main(void)
{
DDRB=0xff; //7 segment port
PORTB=0b11111100; //default value 0 to all the 7 segment;
DDRC=0x3f; //7 segment control port
/*********************************************************************************************
*********** Timer1 for 1s delay F_CPU=8MHz, Prescaler 256 Top value OCR ****************/
/********************************************************************************************/
TCCR1B|=(1<<WGM12)|(1<<CS12); //MODE4 CTC with prescaler 256
TCNT1=0; //clear Timer
TIMSK|=(1<<OCIE1A); //Timer/Counter1 Output Compare Match Interrupt Enable
sei(); //Globel Interrupt Enable
OCR1A=31249; //F_CPU=8MHz,P=256,Delay=1s
/********************************************************************************************/
/*********************************************************************************************
******** Timer0 for 1ms, F_CPU=8MHz, Prescaler 64, Top value=124 ***********/
/*********************************************************************************************/
TCCR0|=(1<<WGM01)|(1<<CS01)|(1<<CS00); //CTC mode2, prescaler 64
TCNT0=0; //Clear Timer
OCR0=124; //delay 1ms
/*********************************************************************************************/
while(1)
{
for(int i=0;i<6;i++)
{
PORTC=0x3f;
delay_ms_1();
PORTB=seven_segment(digits[i]);
PORTC&=~(1<<i);
delay_ms_1();
PORTC=0x3f;
delay_ms_1();
}
}
return 0;
}
The clock we made is much more accurate. But for real time display we have a IC DS1307 for accurate measure of time. We will learn the interface in I2C section.
Sometime it is need to shut down/start any load in desire time. Suppose we want to shut down/start a load after 2 hour. In that case the Timer comes into play. Now in that case we have to count second in reverse direction.
We can make an industrial relay in that-
Enter your desire hour, minute and second in Clock selection switch than increment/decrement in Increment switch/Decrement switch. Finally press the Start switch to start the Timer. If load is on it will closed after counting stop. If load is off it will on after counting stop, during counting period the Pin4 switch will inactive.