How to control 4-digit 7-segment without using any library with atmega328p?

I am working on a 4 digit 7 segment digital watch project.

For the first time i successfully made a multiplexing display using delay(1) function, and it works correctly.
But i also want to count time too using timer/counter 0. That’s why i can’t use delay(1) function to show time.(timer 0 won’t work with delay() function)

this is the code to count current time:
Code works fine.

#include<avr/io.h>
#include<avr/interrupt.h>

unsigned int Hour = 0;
unsigned int Min = 0;

uint8_t count;
unsigned int _sec_ = 0;
unsigned int _min_ = 0;
unsigned int _hours_ = 0;

void timer0_setup(void)
{
  count = 0;
  TCNT0 = 0;
  TIMSK0 = (1<<TOIE0);
  TCCR0B |= (1<<CS02) | (1<<CS00); // prescaler value = 64.
  sei();
}
ISR(TIMER0_OVF_vect)
{
    if(count == 62)  // 62 count of the timer0 = 1 second.
    {
        _sec_++;
        if(_sec_ == 60)
        {
            _min_++;
            Min = _min_;
            if(_min_ == 60)
            {
                _hours_++;
                Hour = _hours_;
                if(_hours_ == 24)
                {
                    _hours_ = 0;
                }  
            }
            
            if(_min_ == 60)
            {
                _min_ = 0;
            }
        }
        if(_sec_ == 60)
        {
             _sec_ = 0;
        }
        
        count = 0; 
   
    }
    else
      count++;
}

int main(void)
{    
  timer0_setup();
  
  while(1){
   //print("time: "hour, date);
  }
}

Now i want to display the time on the 4 digit 7 segment display.
and i don’t want to use libraries like SevenSeg.h or any other and i also don’t want to use other chip to control the display.
how i can do that?

is their any way to multiplexing led display using timer1 or or timer2 or something else?

Using: kali linux, aruino ide, atmega328p(16mhz external) on breadboard with Ftdi-232 for programming.

yashraj43:
But i also want to count time too using timer/counter 0.

That makes no sense. Using millis() is as accurate as timing gets, there is no point in using another counter (unless you are also using a second 32,768 Hz crystal).

yashraj43:
Now i want to display the time on the 4 digit 7 segment display.
and i don't want to use libraries like SevenSeg.h or any other

Then you are going to have to create a lot of code equivalent to what is already in the library.

...R

i did it :slight_smile: , i used delay() for multiplexing(delay() uses timer0) and count time using timer/counter1.
But now the problem is i don’t know why the CTC mode is not enabled :frowning: .

here is my code:
Works fine but not getting an interrupt on a desired value. i wan’t interrupt at 1 second
but getting interrupt at 4 second. :o
I think the CTC mode is not activated and not comparing the value inside OCR1A(=15640). But why?

#include<avr/io.h>
#include<avr/interrupt.h>

void timer_setup(void);

//Refresh rate
#define refresh_rate 1

//chanels->
int ch_0 = 5;
int ch_1 = 6;
int ch_2 = 7;
int ch_3 = 8;

//led->
int A = 2;
int B = 3;
int C = 4;
int D = 9;
int E = 10;
int F = 11;
int G = 12;
int dec = 13;


unsigned int hour = 10;
unsigned int minuit = 15;


void timer1_setup(void)
{ 
  cli();
  TCNT1 = 0;
  OCR1A = 15640; desired value = to complete 1 second.
  TCCR1A |= (1<<WGM12); // CTC mode activate
  TIMSK1 |= (1<<OCIE1A);
  TCCR1B |= (1<<CS12) | (1<<CS10); // prescaler value = 1024
  sei();
}

ISR(TIMER1_COMPA_vect)
{ 
    minuit++;
    if(minuit == 60)
    {
      hour++;
      minuit = 0;
    }
    if(hour == 12)
    {
      hour = 0;
    }
    count = 0; 
}



void deci(int chn){
  digitalWrite(chn, HIGH);
  digitalWrite(dec, HIGH);
  delay(refresh_rate);
  digitalWrite(chn, LOW);
  digitalWrite(dec, LOW);
}

void zero(int chn){
  digitalWrite(chn, HIGH);
  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, HIGH);
  digitalWrite(E, HIGH);
  digitalWrite(F, HIGH);
  delay(refresh_rate);
  digitalWrite(chn, LOW);
  digitalWrite(A, LOW);
  digitalWrite(B, LOW);
  digitalWrite(C, LOW);
  digitalWrite(D, LOW);
  digitalWrite(E, LOW);
  digitalWrite(F, LOW);
}

void one(int chn){
  digitalWrite(chn, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  delay(refresh_rate);
  digitalWrite(chn, LOW);
  digitalWrite(B, LOW);
  digitalWrite(C, LOW);
}

void two(int chn){
  digitalWrite(chn, HIGH);
  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(G, HIGH);
  digitalWrite(E, HIGH);
  digitalWrite(D, HIGH);
  delay(refresh_rate);
  digitalWrite(chn, LOW);
  digitalWrite(A, LOW);
  digitalWrite(B, LOW);
  digitalWrite(G, LOW);
  digitalWrite(E, LOW);
  digitalWrite(D, LOW);
}

void three(int chn){
  digitalWrite(chn, HIGH);
  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(G, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, HIGH);
  delay(refresh_rate);
  digitalWrite(chn, LOW);
  digitalWrite(A, LOW);
  digitalWrite(B, LOW);
  digitalWrite(G, LOW);
  digitalWrite(C, LOW);
  digitalWrite(D, LOW);
}

void four(int chn){
  digitalWrite(chn, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(G, HIGH);
  digitalWrite(F, HIGH);
  digitalWrite(C, HIGH);
  delay(refresh_rate);
  digitalWrite(chn, LOW);
  digitalWrite(B, LOW);
  digitalWrite(G, LOW);
  digitalWrite(F, LOW);
  digitalWrite(C, LOW);
}

void five(int chn){
  digitalWrite(chn, HIGH);
  digitalWrite(A, HIGH);
  digitalWrite(F, HIGH);
  digitalWrite(G, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, HIGH);
  delay(refresh_rate);
  digitalWrite(chn, LOW);
  digitalWrite(A, LOW);
  digitalWrite(F, LOW);
  digitalWrite(G, LOW);
  digitalWrite(C, LOW);
  digitalWrite(D, LOW);
}

void six(int chn){
  digitalWrite(chn, HIGH);
  digitalWrite(A, HIGH);
  digitalWrite(F, HIGH);
  digitalWrite(G, HIGH);
  digitalWrite(E, HIGH);
  digitalWrite(D, HIGH);
  digitalWrite(C, HIGH);
  delay(refresh_rate);
  digitalWrite(chn, LOW);
  digitalWrite(A, LOW);
  digitalWrite(F, LOW);
  digitalWrite(G, LOW);
  digitalWrite(E, LOW);
  digitalWrite(D, LOW);
  digitalWrite(C, LOW);
}

void seven(int chn){
  digitalWrite(chn, HIGH);
  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  delay(refresh_rate);
  digitalWrite(chn, LOW);
  digitalWrite(A, LOW);
  digitalWrite(B, LOW);
  digitalWrite(C, LOW);
}

void eight(int chn){
  digitalWrite(chn, HIGH);
  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, HIGH);
  digitalWrite(E, HIGH);
  digitalWrite(F, HIGH);
  digitalWrite(G, HIGH);
  delay(refresh_rate);
  digitalWrite(chn, LOW);
  digitalWrite(A, LOW);
  digitalWrite(B, LOW);
  digitalWrite(C, LOW);
  digitalWrite(D, LOW);
  digitalWrite(E, LOW);
  digitalWrite(F, LOW);
  digitalWrite(G, LOW);
}

void nine(int chn){
  digitalWrite(chn, HIGH);
  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, HIGH);
  digitalWrite(F, HIGH);
  digitalWrite(G, HIGH);
  delay(refresh_rate);
  digitalWrite(chn, LOW);
  digitalWrite(A, LOW);
  digitalWrite(B, LOW);
  digitalWrite(C, LOW);
  digitalWrite(D, LOW);
  digitalWrite(F, LOW);
  digitalWrite(G, LOW);
}


void setup(){
  // initialize the digital pin as an output.
  pinMode(ch_0, OUTPUT);
  pinMode(ch_1, OUTPUT);
  pinMode(ch_2, OUTPUT);
  pinMode(ch_3, OUTPUT);
  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);
  pinMode(D, OUTPUT);
  pinMode(E, OUTPUT);
  pinMode(F, OUTPUT);
  pinMode(G, OUTPUT);
  pinMode(dec, OUTPUT);
  timer1_setup();
}

// the loop routine runs over and over again forever:
void loop() {
  
    deci(ch_2);
    Time(hour, minuit);
    
}


void Time(int hrs, int minut)
{ removed some code, the lines are limited for Forums}

In addition to setting WGM12 high, you may also need to clear WGM10, WGM11 and WGM13 to zero to get CTC. The previous mode may have left one or more of those bits high, and your current code doesn't clear them.

Also, it's not clear where the 15640 comes from. 16000000/1024 is 15625, and you would actually use 15624 in OCR1A.

And finally, unless your compiler does it for you automatically, you may have to write the OCR1A value one byte at a time, most significant byte first. I don't really know about this, but it's an 8-bit processor.

ShermanP:
And finally, unless your compiler does it for you automatically, you may have to write the OCR1A value one byte at a time, most significant byte first. I don’t really know about this, but it’s an 8-bit processor.

The compiler does it correctly so you can read and write 16-bit registers as 16-bit integers.

:slight_smile: Hey it works…

that’s were the mistake happened :
Wrong setup for timer1:

void timer1_setup(void)
{
  cli();
  TCNT1 = 0;
  OCR1A = 15640; 
  TCCR1A |= (1<<WGM12); // CTC mode activate  
  TIMSK1 |= (1<<OCIE1A);
  TCCR1B |= (1<<CS12) | (1<<CS10); // prescaler value = 1024
  sei();
}

To enable the CTC mode for timer/counter1 we have to write the value WGM12 in TCCR1B not in TCCR1A.

correct setup for timer1:

void timer1_setup(void)
{
  cli();
  TCNT1 = 0;
  OCR1A = 15640; 
  TCCR1B  |= (1<<WGM12); // CTC mode activate   
  TIMSK1 |= (1<<OCIE1A);
  TCCR1B |= (1<<CS12) | (1<<CS10); // prescaler value = 1024
  sei();
}

You are still assuming that all bits of TCCR1A and TCCR1B are cleared before you start. That is not true since Timer1 is set up for PWM output as part of initializing the Arduino runtime. It's best to start your Timer1 setup with:

TCCR1A = 0;
TCCR1B = 0;