I am using 6 digits in multiplexing of 7 Segment Displays. I edited this code earlier for 3 Digit display which was working fine all thanks to the help from this forum. But I seem to be stuck at 6 digits the one digit keeps on lighting brighter than the others. I have tried to change the values in the startDisplay() function of the program but doesn't seem to have any effect.
Following is the code:`
#define F_CPU 16000000UL
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
/* TIMER0_PRELOAD_VAL=255-((F_CPU/Prescaler)*Time - 1).
For F_CPU 16 MHz, Time 1 msec is 6. */
#define TIMER0_PRELOAD_VAL 6
void startcounter(uint16_t);
volatile float frequency;
volatile float freq;
volatile uint16_t gate_time; // The time in msec that the gate will remain open.
volatile uint16_t timer0_ticks; // The number of Timer0 ticks.
uint8_t counter1_overflows; // The number of Timer / Counter1 overflows.
volatile uint8_t ready_flag; // Flag of completion of the measurement.
volatile uint32_t counter_val; // The total value of the measurement.
uint8_t digit[3] ; // these are the digits to be displayed
int main()
{
DDRD = (1<<2) | (1<<3) | (1<<4) | (1<<6) | (1<<7);
DDRB = (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5);
DDRC = (1<<1) | (1<<2) ||(1<<3) | (1<<4);
sei();
//Serial.begin(9600);
uint16_t gate=1000; // Se milliseconds.
uint8_t i; // A little trick to not "clog"
// the UART when we have a short gate time.
while(1)
{
i++;
startcounter(gate);
while(!ready_flag){};
frequency = counter_val*(1000/gate);
if (i>=1000/gate)
{
freq = frequency;
}
i=0;
}
return 0;
}
ISR (TIMER2_COMP_vect)
{
//Function to run display...
displayNumber();
}
void startDisplay()
{
OCR2 = 125;
TCCR2 |= (1 << WGM21);
TIMSK |= (1 << OCIE2);
TCCR2 |= (1 << CS22); // prescaler /256
TCCR2 |= (1 << CS21); // prescaler /256
}
void startcounter(uint16_t msecs)
{
gate_time=msecs;
counter1_overflows=0;
timer0_ticks=0;
ready_flag=0;
TIMSK |= (1<<TOIE1); // Enable Overflow Interrupt for Timer / Counter1.
TIMSK |= (1<<TOIE0); // Enable Overflow Interrupt for Timer0.
// Initialize Timer0. Causes Interrupt each msec.
TCNT0 = TIMER0_PRELOAD_VAL; // Preload with the price for a time of 1 msec.
TCCR0 |= (1<<CS01)|(1<<CS00); // Activation with Prescaler 64.
// Reset TCNT1?
TCNT1=0;
// Increase TCNT1 by applying pulse to PD5.
TCCR1B |= (1<<CS10)|(1<<CS11)|(1<<CS12);
}
ISR(TIMER1_OVF_vect){
counter1_overflows++;
}
ISR(TIMER0_OVF_vect){
uint16_t counter1_ticks;
// Counter value of Counter1.
counter1_ticks = TCNT1;
TCNT0 += TIMER0_PRELOAD_VAL; // Preload TCNT0 for 1 msec.
timer0_ticks++;
// Check if gate_time has been completed. If not ISR exit?
if (timer0_ticks < gate_time)
{
startDisplay();
return;
}
// If we lost a Timer / Counter1 interrupt increase the meter.
if (bit_is_set(TIFR,TOV1)) counter1_overflows++;
TIMSK &= ~((1<<TOIE1)|(1<<TOIE0)); // Disable Interrupt overflow for Timer0, Timer / counter1.
TCCR1B &= ~((1<<CS10)|(1<<CS11)|(1<<CS12)); // Stop Timer / Counter1.
TCCR0 &= ~( (1<<CS01)|(1<<CS00)); // Stop Timer0.
counter_val = (counter1_overflows*65536)+counter1_ticks;
ready_flag = 1;
}
void displayNumber()
{
// on each call, calculates and displays the number at the next digit position
// call every 4 ms by a timer
static int i = 6 ; // static variables are initialised once only
pickDigit (i) ;
// calculate the number to be displayed at postion 'i' based on the frequency.
// note: the calculations here are quite slow and would be better done once when
// frequency is newly determined and not each time.
switch( i )
{
case 6:
pickNumber((int)freq %10);
break;
case 5:
pickNumber(((int)freq/10)%10);
break;
case 4:
pickNumber(((int)freq / 100)%10);
break;
case 3:
pickNumber(((unsigned long)freq / 1000)%10);
break;
case 2:
pickNumber(((unsigned long)freq / 10000)%10);
break;
case 1:
pickNumber(((unsigned long)freq / 100000)%10);
break;
}
if ( --i<=0 ) i = 7 ; // 3 digit display ?
}
void pickDigit(int x)
{
// Initially turn _all_ lines off to avoid ghosting
clearLEDs();
PORTC = (0<<5) | (0<<4) | (0<<3) | (0<<2) | (0<<1) | (0<<0);
// select digit (still dark)
switch(x)
{
case 1:
PORTC = (1<<5) | (0<<4) | (0<<3) | (0<<2) | (0<<1) | (0<<0);
break;
case 2:
PORTC = (0<<5) | (1<<4) | (0<<3) | (0<<2) | (0<<1) | (0<<0);
break;
case 3:
PORTC = (0<<5) | (0<<4) | (1<<3) | (0<<2) | (0<<1) | (0<<0);
break;
case 4:
PORTC = (0<<5) | (0<<4) | (0<<3) | (1<<2) | (0<<1) | (0<<0);
break;
case 5:
PORTC = (0<<5) | (0<<4) | (0<<3) | (0<<2) | (1<<1) | (0<<0);
break;
default :
PORTC = (0<<5) | (0<<4) | (0<<3) | (0<<2) | (0<<1) | (1<<0);
break;
}
}
//Function to display a integer number:
void pickNumber(int x)
{
switch(x)
{
default:
zero();
break;
case 1:
one();
break;
case 2:
two();
break;
case 3:
three();
break;
case 4:
four();
break;
case 5:
five();
break;
case 6:
six();
break;
case 7:
seven();
break;
case 8:
eight();
break;
case 9:
nine();
break;
}
}
void clearLEDs()
{
PORTD = (1<<2) | (1<<3) | (1<<4) | (1<<6) | (1<<7);
PORTB = (1<<0) | (1<<1) | (1<<2);
}
// Number library for integers
void zero()
{
PORTD = (0<<2) | (0<<3) | (0<<4) | (0<<6) | (0<<7);
PORTB = (0<<0) | (1<<1) | (1<<2);
}
void one()
{
PORTD = (1<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
PORTB = (1<<0) | (1<<1) | (1<<2);
}
void two()
{
PORTD = (0<<2) | (0<<3) | (1<<4) | (0<<6) | (0<<7);
PORTB = (1<<0) | (0<<1) | (1<<2);
}
void three()
{
PORTD = (0<<2) | (0<<3) | (0<<4) | (0<<6) | (1<<7);
PORTB = (1<<0) | (0<<1) | (1<<2);
}
void four()
{
PORTD = (1<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
PORTB = (0<<0) | (0<<1) | (1<<2);
}
void five()
{
PORTD = (0<<2) | (1<<3) | (0<<4) | (0<<6) | (1<<7);
PORTB = (0<<0) | (0<<1) | (1<<2);
}
void six()
{
PORTD = (0<<2) | (1<<3) | (0<<4) | (0<<6) | (0<<7);
PORTB = (0<<0) | (0<<1) | (1<<2);
}
void seven()
{
PORTD = (0<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
PORTB = (1<<0) | (1<<1) | (1<<2);
}
void eight()
{
PORTD = (0<<2) | (0<<3) | (0<<4) | (0<<6) | (0<<7);
PORTB = (0<<0) | (0<<1) | (1<<2);
}
void nine()
{
PORTD = (0<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
PORTB = (0<<0) | (0<<1) | (1<<2);
}
