-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathblinky_millis.c
95 lines (72 loc) · 1.82 KB
/
blinky_millis.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
// prescaler is set so timer0 ticks every 64 clock cycles, and the overflow handler
// is called every 256 ticks.
#define MICROSECONDS_PER_TIMER0_OVERFLOW \
(64UL * 256UL * 100000UL / ((F_CPU + 5UL) / 10UL))
// the whole number of milliseconds per timer0 overflow
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000U)
// the fractional number of milliseconds per timer0 overflow
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000U) >> 3)
// shift right to fit in a byte
#define FRACT_MAX (1000U >> 3)
volatile unsigned long timer0_millis = 0;
volatile unsigned char timer0_fract = 0;
#if defined(__AVR_ATtiny13__) || defined(__AVR_ATtiny13A__) || defined(__AVR_ATtiny85__)
ISR(TIM0_OVF_vect)
#else
ISR(TIMER0_OVF_vect)
#endif
{
// Copy to local vars so they can go in registers
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += MILLIS_INC + 1;
}
else {
m += MILLIS_INC;
}
timer0_millis = m;
timer0_fract = f;
}
void init_timer()
{
sei();
// Set timer0 prescaler to 64
TCCR0B |= _BV(CS01) | _BV(CS00);
// Set timer0 interrupt mask - TimerOverflowInterruptEnable
TIMSK0 |= _BV(TOIE0);
}
unsigned long millis()
{
unsigned long m;
uint8_t oldSREG = SREG;
// copy millis into m atomically by disabling interrupts
cli();
m = timer0_millis;
SREG = oldSREG;
return m;
}
#define LEDPIN PB3
#define LEDDDR DDB3
int main(void)
{
OSCCAL += 0;
init_timer();
DDRB |= _BV(LEDDDR);
PORTB = 0x00;
unsigned long lastTime = 0;
for (;;) {
unsigned long currentTime = millis();
if (currentTime > lastTime + 1000) {
PORTB ^= _BV(LEDPIN);
lastTime = currentTime;
}
// Do other stuff
}
return 0;
}