Hallo, Ich habe hier ein Projekt, bei welchem ich zu definiertem Zeitpunkt einen 2 ms langen Puls auslösen will. Dazu verwende ich den Timer0 mit Prescaler 1024 und lasse ihn 30 Tics laufen, bis er in den Compare Interrupt läuft. Dort wird der Puls beendet und der Interrupt deaktiviert. Bei Start des nächsten Pulses (getriggert durch die fallende Flanke des FGs) wird der Timer auf 0 gesetzt und der Interrupt wieder aktiviert. Das Lustige ist, dass es nur manchmal funktioniert. In ca 70% der Fälle kommt ein nur ca 7 ns langer Puls durch. In den anderen 30% funktioniert es wie gedacht. Nach einigen Resets des Controllers ändert sich das Verhalten, es springt wenn man oft genug resettet beliebig hin und her. Ich verwenden einen AT90CAN128 auf dem AVR-CAN Board von Olimex, AVRstudio 4.18 mit WinAVR toolchain und den Olimex USB-JTAG ( Wobei das Jtag-Debugging nicht ganzfunktioniert, warum auch immer... ) unter Win10 Im Anhang die Oszi-Screenshots, nichts am Programm oder der Umgebung geändert, nur resettet. Code:
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | |
5 | void PORT_Init() |
6 | {
|
7 | PORTA = 0b00000000; |
8 | DDRA = 0b00000000; |
9 | |
10 | PORTB = 0b00000000; |
11 | DDRB = 0b00000000; |
12 | |
13 | PORTC = 0b00000000; |
14 | DDRC = 0b00000000; |
15 | |
16 | PORTD = 0b00000000; |
17 | DDRD = 0b00000100; // PD0=INT0 Als Input um Hardware-Interrupt zu erzeugen PD2 als ZündOutput |
18 | |
19 | PORTE = 0b00010000; |
20 | DDRE = 0b00010000; //Led set as output (Bit4 = 1) |
21 | |
22 | PORTF = 0b00000000; |
23 | DDRF = 0b00000000; |
24 | }
|
25 | |
26 | |
27 | void Reg_Init(void) |
28 | {
|
29 | |
30 | EIMSK=0b00000001; // External Asynchodous Interupt Pin 0 (PD0) Aktiviert |
31 | EICRA=0b00000010; // ISR 0 loest bei Fallender Flanke aus |
32 | |
33 | |
34 | //Timer 0 für Schließwinkel
|
35 | TCCR0A=0b00000101; // kein PWM,kein Compare Match , prescaler 1024 -> 2ms = 30 Pulse |
36 | TIMSK0=0b00000000; // erstmal kein Compare Match interrupt |
37 | |
38 | OCR0A=30; |
39 | |
40 | |
41 | }
|
42 | |
43 | |
44 | void WDT_off(void) |
45 | {
|
46 | cli(); |
47 | /* Write logical one to WDCE and WDE */
|
48 | WDTCR = (1<<WDCE) | (1<<WDE); |
49 | /* Turn off WDT */
|
50 | WDTCR = 0x00; |
51 | }
|
52 | |
53 | |
54 | int main() |
55 | {
|
56 | WDT_off(); |
57 | PORT_Init(); |
58 | Reg_Init(); |
59 | |
60 | sei(); // Alles Initialisiert, Interupts Freischalten |
61 | |
62 | while (1) |
63 | |
64 | {
|
65 | }
|
66 | }
|
67 | |
68 | ISR(INT0_vect) // Interrupt von Pin |
69 | {
|
70 | TCNT0 =0; |
71 | TIMSK0 |=0b00000010; // Compare Match 0 interrupt an |
72 | PORTD |= 0b00000100; //Öffnen |
73 | }
|
74 | |
75 | |
76 | ISR(TIMER0_COMP_vect) // 2ms-timer interrupt |
77 | {
|
78 | PORTD &=1111111011; //Zünden |
79 | TIMSK0 &=0b11111101; // Compare Match 0 interrupt aus |
80 | }
|