I want to make a coil winder decremental counter after setting the number on a four digit seven segment display. Use of an ISR is made to refresh the SSDs.
I have from the various searches on google collected code for two sketches that display the number on the SSDs.
One uses a switch case of 9, the second sketch uses an array for the masks for the segments A to G. decimal point is not used.
In the second sketch the ISR has for delays without which the display does not work. How to modify this ISR in the scond sketch so that there are no delays in it.
First sketch:
//Atmega8 @16MHZ
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay_basic.h>
#define SEVEN_SEGMENT_PORT PORTD
#define SEVEN_SEGMENT_DDR DDRD
volatile uint8_t digits[4];
void sevenSegment(uint8_t n)
{
/*
This function writes a digits given by n to the display
the decimal point is displayed if dp=1
Note:
n must be less than 9
*/
if (n < 10)
{
switch (n)
{
case 0:
//.gfedcba
SEVEN_SEGMENT_PORT = 0b10111111;
break;
case 1:
//.gfedcba
SEVEN_SEGMENT_PORT = 0b10000110;
break;
case 2:
//.gfedcba
SEVEN_SEGMENT_PORT = 0b11011011;
break;
case 3:
//.gfedcba
SEVEN_SEGMENT_PORT = 0b11001111;
break;
case 4:
//.gfedcba
SEVEN_SEGMENT_PORT = 0b11100110;
break;
case 5:
//.gfedcba
SEVEN_SEGMENT_PORT = 0b11101101;
break;
case 6:
//.gfedcba
SEVEN_SEGMENT_PORT = 0b11111101;
break;
case 7:
//.gfedcba
SEVEN_SEGMENT_PORT = 0b10000111;
break;
case 8:
//.gfedcba
SEVEN_SEGMENT_PORT = 0b11111111;
break;
case 9:
//.gfedcba
SEVEN_SEGMENT_PORT = 0b11101111;
break;
}
}
}
void Wait()
{
uint8_t i;
for (i = 0; i < 10; i++)
{
_delay_loop_2(0);
}
}
void Print(uint16_t num)
{
/*
This function separates a given integer into digits
and writes them to the four SSDs.
*/
uint8_t i = 0;
uint8_t j;
if (num > 9999) return; // display all zeroes for number that is >9999
while (num)
{
digits[i] = num % 10;
i++;
num = num / 10;
}
for (j = i; j < 4; j++) digits[j] = 0; // show 0 on SSD that is 0
}
int main(void)
{
uint16_t i;
// Prescaler = FCPU/256
TCCR0 |= (1 << CS02);
//Enable Overflow Interrupt Enable
TIMSK |= (1 << TOIE0);
//Initialize Counter
TCNT0 = 0;
//Port B[3,2,1,0] as out put
DDRB |= ((1 << PB3) | (1 << PB2) | (1 << PB1) | (1 << PB0));
PORTB = 0b00000000;
//Port D
SEVEN_SEGMENT_DDR = 0XFF;
//Turn off all segments
SEVEN_SEGMENT_PORT = 0X00;
//Enable Global Interrupts
sei();
while (1)
{
Print(9045);
Wait();
}
}
ISR(TIMER0_OVF_vect)
{
/*
This interrupt service routine (ISR)
Updates the SSDs
*/
static uint8_t i = 0;
if (i == 3)
{
//If on 1st SSD go to 4th SSD
i = 0;
}
else
{
//Goto Next SSD
i++;
}
//Activate the SSD display according to i
PORTB &= (0b11110000);
PORTB |= (1 << i);
//Write the digit[i] in the ith SSD.
sevenSegment(digits[i]);
}
Second Sketch:
// ATmega8@16MHz_7seg_4digit
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>
#define LED_Directions DDRD /* define LED Direction */
#define LED_Direction DDRB /* define LED Direction */
#define LED_PORT1 PORTD /* define LED port */
#define LED_PORT2 PORTB /* define LED port */
volatile uint8_t digits[4];
volatile uint8_t segments[] = {0b10111111, 0b10000110, 0b11011011, 0b11001111, 0b11100110, 0b11101101, 0b11111101, 0b10000111, 0b11111111, 0b11101111};
int k, j, i, h;
int brightvalue = 0;
void set_brightness()
{
int brightness = brightvalue;
while (0 < brightness)
{
_delay_us(1);
--brightness;
}
}
ISR(TIMER0_OVF_vect)
{
PORTB = (1 << PB0);
PORTD = segments[k];
set_brightness();
PORTB = (1 << PB1);
PORTD = segments[j];
set_brightness();
PORTB = (1 << PB2);
PORTD = segments[i];
set_brightness();
PORTB = (1 << PB3);
PORTD = segments[h];
set_brightness();
}
void SevenSeg_SetNumber(int num)
{
k = num % 10;
num = num / 10;
j = num % 10;
num = num / 10;
i = num % 10;
num = num / 10;
h = num % 10;
num = num / 10;
}
int main(void)
{
sei();
DDRD = 0xff; /* define port direction is output */
DDRB = 0xff; /* define port direction is output */
PORTD = 0x00;
PORTB = 0x00;
TIMSK = (1 << TOIE0); /* Enable Timer0 overflow interrupts */
TCNT0 = 0; /* load TCNT0, count for 10ms*/
TCCR0 = (1 << CS02); /* start timer0 with /256 prescaler*/
brightvalue = 1000; /* set brightness level of 7 segment display */
while (1)
{
SevenSeg_SetNumber(9045);/* set value to display */
}
}
I am using an Atmega *@16MHz as target using MCUDUDES minicore with arduino ide 1.8.11