PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Timer/Interrupt Problem. LED soll jede Minute blinken



dg
16.05.2007, 21:20
Hallo Zusammen,

irgendwie komme ich mit einem simplem Programmteil für einen Tiny25 nicht weiter.
Ich habe mal das Problem auf so wenig Code wie möglich reduziert.

Die LED soll einfach nur jede Minute kurz aufblinken. Leider blinkt sie viel zu schnell und mein Zähler i wird trotz volatile ignoriert.

Hier der Code:



#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

// Flags f�r IRQs
volatile uint8_t EveryMinuteFlag;

// Z�hler f�r IRQs
volatile uint8_t i=0;

int main(void) {

// Ausg�nge setzen
DDRB |= ((1 << PB2) | (1 << PB3) | (1 << PB1));

//Action-Flags
EveryMinuteFlag = 1;

// Timer0 Prescaler 1024
TCCR0B |= ((1<<CS02) | (0<<CS01) | (1<<CS00));

OCR0A = 0x00;
// OCR0B = 0x00;

// Interrupts f�r Timer0
TIMSK |= (1<<OCIE0A); //Interrupt bei Compare
TIMSK |= (1<<TOIE0); //Interrupt bei Overflow

// Interrupts aktivieren
sei();

while (1) {

if (EveryMinuteFlag) {

// LED bliken lassen
PORTB |= ( 1 << PB2 );
_delay_ms(5);
PORTB &= ~( 1 << PB2 );

EveryMinuteFlag = 0;
}

}
}

SIGNAL(SIG_OVERFLOW0)
{
i++;
if (i==250) {
EveryMinuteFlag=1;
i=0;
}
}


Egal welchen vergleichswert ich für i nehme die LED blinkt immer genauso schnell.

Ich mach daran seit Tagen rum und es will einfach nicht. Hat jemand noch ne Idee?

Vielen Dank
daniel

linux_80
16.05.2007, 21:30
Hallo,

als erstes würde ich die Zeile rauswerfen, die den Compare Interrupt (OCIE0A) aktiviert, denn dazu gibts ja hier keine ISR, und der AVR macht dann einen Reset falls der IRQ mal auftritt.

Mit Wieviel MHz läuft der Tiny ?

dg
18.05.2007, 20:21
ich hab jetzt mal die Interrupts für den Timer0-Compare rausgeschmissen, verändert hat das leider nix. Der Tiyn25 läuft mit 8MHz.
meine Vermutung ist das der compiler das wegoptimiert. Leider sind meine letzten Kontakte mit Assembler zu lange her.

Hier mal der ASM Output:



test-timer.o: file format elf32-avr

Disassembly of section .text:

00000000 <main>:

// Zähler für IRQs
volatile uint8_t i=0;

int main(void) {
0: c0 e0 ldi r28, 0x00 ; 0
2: d0 e0 ldi r29, 0x00 ; 0
4: de bf out 0x3e, r29 ; 62
6: cd bf out 0x3d, r28 ; 61

// Ausgänge setzen
DDRB |= ((1 << PB2) | (1 << PB3) | (1 << PB1));
8: 87 b3 in r24, 0x17 ; 23
a: 8e 60 ori r24, 0x0E ; 14
c: 87 bb out 0x17, r24 ; 23

//Action-Flags
EveryMinuteFlag = 1;
e: 81 e0 ldi r24, 0x01 ; 1
10: 80 93 00 00 sts 0x0000, r24

// Timer0 Prescaler 1024
TCCR0B |= ((1<<CS02) | (0<<CS01) | (1<<CS00));
14: 83 b7 in r24, 0x33 ; 51
16: 85 60 ori r24, 0x05 ; 5
18: 83 bf out 0x33, r24 ; 51


// Interrupts für Timer0 bei Overflow
TIMSK |= (1<<TOIE0);

// Interrupts aktivieren
sei();
1a: 89 b7 in r24, 0x39 ; 57
1c: 82 60 ori r24, 0x02 ; 2
1e: 89 bf out 0x39, r24 ; 57

while (1) {

20: 78 94 sei
22: a8 ee ldi r26, 0xE8 ; 232
24: b3 e0 ldi r27, 0x03 ; 3
26: c0 e0 ldi r28, 0x00 ; 0
28: d0 e0 ldi r29, 0x00 ; 0
if (EveryMinuteFlag) {

// LED blinken lassen
PORTB |= ( 1 << PB2 );
2a: 80 91 00 00 lds r24, 0x0000
2e: 88 23 and r24, r24
30: e1 f3 breq .-8 ; 0x2a <main+0x2a>
_delay_ms(5);
PORTB &= ~( 1 << PB2 );

32: c2 9a sbi 0x18, 2 ; 24
*/
void
_delay_loop_2(uint16_t __count)
{
__asm__ volatile (
34: 8a 2f mov r24, r26
36: 9b 2f mov r25, r27
38: 01 97 sbiw r24, 0x01 ; 1
3a: f1 f7 brne .-4 ; 0x38 <main+0x38>
EveryMinuteFlag = 0;
}
3c: c2 98 cbi 0x18, 2 ; 24

}
3e: 10 92 00 00 sts 0x0000, r1
42: f3 cf rjmp .-26 ; 0x2a <main+0x2a>

00000044 <__vector_5>:
}

SIGNAL (SIG_OVERFLOW0)
{
i++;
if (i==250) {
EveryMinuteFlag=1;
44: 1f 92 push r1
46: 0f 92 push r0
48: 0f b6 in r0, 0x3f ; 63
4a: 0f 92 push r0
4c: 11 24 eor r1, r1
4e: 8f 93 push r24
i=0;
50: 80 91 00 00 lds r24, 0x0000
54: 8f 5f subi r24, 0xFF ; 255
56: 80 93 00 00 sts 0x0000, r24
}
5a: 80 91 00 00 lds r24, 0x0000
5e: 81 30 cpi r24, 0x01 ; 1
60: 21 f4 brne .+8 ; 0x6a <__vector_5+0x26>
}
62: 80 93 00 00 sts 0x0000, r24
66: 10 92 00 00 sts 0x0000, r1
6a: 8f 91 pop r24
6c: 0f 90 pop r0
6e: 0f be out 0x3f, r0 ; 63
70: 0f 90 pop r0
72: 1f 90 pop r1
74: 18 95 reti

dg
18.05.2007, 20:52
habs hinbekommen. war tatsächlich so, daß es mit -Os wegoptimiert wurde.

ein -O2 hats gebracht, allerdings nur unter linux mit gcc-Version 3.4.5 AVR-Ada-0.4.1 (CDK4AVR 3.0 3.4.5-20060708) der aktuelle WinAVR optimiert es trotz -O2 weg :(

Vielen Dank

linux_80
18.05.2007, 21:04
Hab auch grad mit den Optimierungen rumprobiert, wenn man garnicht optimiert wird der Code so gross, da er nicht mehr in den Tiny passt !
:-k