/*
ATmega8, 48, 88, 168, 328
/Reset PC6|1 28|PC5
seg_A PD0|2 27|PC4
seg_B PD1|3 26|PC3
seg_C PD2|4 25|PC2
seg_D PD3|5 24|PC1
seg_E PD4|6 23|PC0
Vcc|7 22|Gnd
Gnd|8 21|Aref
PB6|9 20|AVcc
PB7|10 19|PB5 SCK Anode_1
seg_F PD5|11 18|PB4 MISO Anode_2
seg_G PD6|12 17|PB3 MOSI Anode_3
dot PD7|13 16|PB2 Anode_4
PB0|14 15|PB1
*/
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
/* _ _
| A |
F B
|- G -|
E C
|_ D _| .H
*/
uint8_t font[] =
{// HGFEDCBA
0b11000000, // 0
0b11111001, // 1
0b10100100, // 2
0b10110000, // 3
0b10011001, // 4
0b10010010, // 5
0b10000010, // 6
0b11111000, // 7
0b10000000, // 8
0b10010000, // 9
};
volatile uint8_t framebuffer[4];
ISR(TIMER0_OVF_vect)
{
static uint8_t digit;
PORTB &= 0b11000011; // clear all digits
PORTB |= (0b00000100 << digit); // set current digit
PORTD = framebuffer[digit]; // update segments
digit++;
digit = digit % 4; // keep digit in [0:3]
}
void init(void)
{
DDRD = 0b?; // segments
DDRB = 0b?; // digits
// we start with
// normal operation
// clk/1024 prescaler (about 1kHz)
// interrupt on Timer 0 overflow
TCCR0A = (0 << COM0A1) | (0 << COM0A0) | (0 << COM0B1) | (0 << COM0B0)
| (? << WGM01) | (? << WGM00);
TCCR0B = (0 << WGM02)
| (? << CS02) | (? << CS01) | (? << CS00);
TIMSK0 = (0 << OCIE0B) | (0 << OCIE0A) | (? << TOIE0);
// allow interrupts globally
sei();
}
int main(void)
{
uint16_t count=0;
uint16_t dummy;
uint8_t i;
init();
while(1)
{
dummy = count;
for (i=0; i<4; i++)
{
framebuffer[i] = font[dummy % 10];
dummy = dummy / 10;
}
count++;
if (count >= 10000)
{
count = 0;
}
_delay_ms(70);
}
}
Comments