Forum: Mikrocontroller und Digitale Elektronik Pin Interrupt löst Reset aus


von johannes h. (j0hannes)


Angehängte Dateien:

Lesenswert?

Guten Abend alle zusammen

Ich bin neu in dem Forum, so go easy on me =).

Mein Promlem 1 ist mein externer Interrupt löst entweder einen Reset aus 
oder der Rücksprung in die int main() geht immer an den Anfang der main 
und initialisiert alles neu.

Mein Promlem 2 ein externer Interrupt wird manchmal gleich zweimal 
hintereinander aufgerufen (mit einem Tastendruck) obwohl ich große 
Verzögerungszeiten drin hab.

Ich verwende AVR Studio 4 in einer Windows XP VM, da hatte ich die 
Probleme zum ersten mal.
Ich Habe jedoch das unten abgebildete Programm in CodeVisionAVR 
Evaluation V2.05.5a erstellt, weil meine Vermutung war das meine 
Interruptinitialisierung falsch ist und ich die Hoffnung hatte das der 
CodeWizard die Initialisierung richtig macht.
Mein Microkontroller ist ein ATMega644P auf dem Pollin 
funk-avr-evalationboard ver 1.1, das board hab ich schonmal ausgetauscht 
daran kann es nicht liegen nur vielleicht an dem Microcontroller.

Und hätte die frage wie ich mir die Sprungadressen meines externen 
Interrupt ausgeben lassen kann. Ich würd gerne feststellen ob ein Reset 
ausgeführt wird oder der Sprung an eine falsche Adresse gemacht wird.

Ich hoff ich hab mein Problem verständlich gemacht und alles wichtige 
angegeben. Ich würde mich über eine Fehleranalyse freuen.

mit freundlichen Grüßen Joahnnes


1
/*****************************************************
2
This program was produced by the
3
CodeWizardAVR V2.05.5a Evaluation
4
Automatic Program Generator
5
© Copyright 1998-2011 Pavel Haiduc, HP InfoTech s.r.l.
6
http://www.hpinfotech.com
7
8
Project : 
9
Version : 
10
Date    : 09.12.2011
11
Author  : Freeware, for evaluation and
12
non-commercial use only
13
Company : 
14
Comments: 
15
16
17
Chip type               : ATmega644P
18
Program type            : Application
19
AVR Core Clock frequency: 16,000000 MHz
20
Memory model            : Small
21
External RAM size       : 0
22
Data Stack size         : 1024
23
*****************************************************/
24
25
#include <mega644p.h>
26
#include <delay.h>
27
#include <stdio.h>
28
29
volatile unsigned int ein = 0;
30
// Pin change 8-15 interrupt service routine
31
interrupt [PC_INT1] void pin_change_isr1(void)
32
{
33
printf("ISR AN \r");
34
// Place your code here
35
if(!ein)
36
    {
37
        delay_ms(1000);
38
        PORTD.6 = 1;
39
        printf("EIN \r");
40
        ein = 1;
41
    }
42
    else if(ein)
43
    {
44
        delay_ms(1000);
45
        PORTD.6 = 0;
46
        printf("AUS \r");
47
        ein = 0;
48
    }   
49
printf("ISR AUS \r");
50
}
51
52
53
54
// Standard Input/Output functions
55
56
57
// Timer2 output compare interrupt service routine
58
interrupt [TIM2_COMPA] void timer2_compa_isr(void)
59
{
60
// Place your code here
61
62
}
63
64
// Declare your global variables here
65
66
67
void main(void)
68
{
69
// Declare your local variables here
70
71
// Crystal Oscillator division factor: 1
72
#pragma optsize-
73
CLKPR=0x80;
74
CLKPR=0x00;
75
#ifdef _OPTIMIZE_SIZE_
76
#pragma optsize+
77
#endif
78
79
// Input/Output Ports initialization
80
// Port A initialization
81
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
82
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
83
PORTA=0x00;
84
DDRA=0x00;
85
86
// Port B initialization
87
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
88
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
89
PORTB=0x00;
90
DDRB=0x00;
91
92
// Port C initialization
93
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
94
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
95
PORTC=0x00;
96
DDRC=0x00;
97
98
// Port D initialization
99
// Func7=Out Func6=Out Func5=Out Func4=In Func3=In Func2=In Func1=In Func0=In 
100
// State7=0 State6=0 State5=0 State4=T State3=T State2=T State1=T State0=T 
101
PORTD=0x00;
102
DDRD=0xE0;
103
104
// Timer/Counter 0 initialization
105
// Clock source: System Clock
106
// Clock value: Timer 0 Stopped
107
// Mode: Normal top=0xFF
108
// OC0A output: Disconnected
109
// OC0B output: Disconnected
110
TCCR0A=0x00;
111
TCCR0B=0x00;
112
TCNT0=0x00;
113
OCR0A=0x00;
114
OCR0B=0x00;
115
116
// Timer/Counter 1 initialization
117
// Clock source: System Clock
118
// Clock value: Timer1 Stopped
119
// Mode: Normal top=0xFFFF
120
// OC1A output: Discon.
121
// OC1B output: Discon.
122
// Noise Canceler: Off
123
// Input Capture on Falling Edge
124
// Timer1 Overflow Interrupt: Off
125
// Input Capture Interrupt: Off
126
// Compare A Match Interrupt: Off
127
// Compare B Match Interrupt: Off
128
TCCR1A=0x00;
129
TCCR1B=0x00;
130
TCNT1H=0x00;
131
TCNT1L=0x00;
132
ICR1H=0x00;
133
ICR1L=0x00;
134
OCR1AH=0x00;
135
OCR1AL=0x00;
136
OCR1BH=0x00;
137
OCR1BL=0x00;
138
139
// Timer/Counter 2 initialization
140
// Clock source: System Clock
141
// Clock value: 16000,000 kHz
142
// Mode: Normal top=0xFF
143
// OC2A output: Clear on compare match
144
// OC2B output: Disconnected
145
ASSR=0x00;
146
TCCR2A=0x80;
147
TCCR2B=0x01;
148
TCNT2=0x00;
149
OCR2A=0x00;
150
OCR2B=0x00;
151
152
// External Interrupt(s) initialization
153
// INT0: Off
154
// INT1: Off
155
// INT2: Off
156
// Interrupt on any change on pins PCINT0-7: Off
157
// Interrupt on any change on pins PCINT8-15: On
158
// Interrupt on any change on pins PCINT16-23: Off
159
// Interrupt on any change on pins PCINT24-31: Off
160
EICRA=0x00;
161
EIMSK=0x00;
162
PCMSK1=0x02;
163
PCICR=0x02;
164
PCIFR=0x02;
165
166
// Timer/Counter 0 Interrupt(s) initialization
167
TIMSK0=0x00;
168
169
// Timer/Counter 1 Interrupt(s) initialization
170
TIMSK1=0x00;
171
172
// Timer/Counter 2 Interrupt(s) initialization
173
TIMSK2=0x02;
174
175
// USART0 initialization
176
// Communication Parameters: 8 Data, 1 Stop, No Parity
177
// USART0 Receiver: On
178
// USART0 Transmitter: On
179
// USART0 Mode: Asynchronous
180
// USART0 Baud Rate: 9600
181
UCSR0A=0x00;
182
UCSR0B=0x18;
183
UCSR0C=0x06;
184
UBRR0H=0x00;
185
UBRR0L=0x67;
186
187
// USART1 initialization
188
// USART1 disabled
189
UCSR1B=0x00;
190
191
// Analog Comparator initialization
192
// Analog Comparator: Off
193
// Analog Comparator Input Capture by Timer/Counter 1: Off
194
ACSR=0x80;
195
ADCSRB=0x00;
196
DIDR1=0x00;
197
198
// ADC initialization
199
// ADC disabled
200
ADCSRA=0x00;
201
202
// SPI initialization
203
// SPI disabled
204
SPCR=0x00;
205
206
// TWI initialization
207
// TWI disabled
208
TWCR=0x00;
209
210
// Global enable interrupts
211
#asm("sei")
212
printf("START \r");
213
while (1)
214
      {
215
      // Place your code here
216
      delay_ms(4500);
217
      }
218
}

von Peter II (Gast)


Lesenswert?

wo hast du das her?

// Pin change 8-15 interrupt service routine
interrupt [PC_INT1] void pin_change_isr1(void)


ich kenn nur die Version aus dem Tourturiel, und das sieht anders aus. 
Wenn das falsch ist, dann wird nur eine normale funktion angelgt und 
keine ISR.

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#ISR

von Krapao (Gast)


Lesenswert?

Welche Version macht die Probleme - die im Anahng oder die im Beitrag?

> Mein Promlem 2 ein externer Interrupt wird manchmal gleich zweimal
> hintereinander aufgerufen (mit einem Tastendruck) obwohl ich große
> Verzögerungszeiten drin hab.

Die Verzögerungszeiten helfen nicht, wenn vor dem Verzögern bereits der 
nächste Interrupt registriert wird. Das dabei gesetzte Flag bleibt 
bestehen!

Mach es richtig und lies die Artikel Interrupt und Entprellung. 
Und ich empfehle dir der besseren Les- und Debugbarkeit wegen die 
Schreibweise aus Bitmanipulation, statt der Zuweisung absoluter 
Hexwerte an SFRs.

von johannes h. (j0hannes)


Lesenswert?

Peter II schrieb:
> wo hast du das her?

von http://www.hpinfotech.ro/
Codevision verwendet den atmel compiler, müsste eigentlich richtig sein 
wir verwenden sie gleiche software in der Uni

Krapao schrieb:
> Welche Version macht die Probleme - die im Anahng oder die im Beitrag?

Beide Versionen haben das gleiche Problem.

Krapao schrieb:
> Die Verzögerungszeiten helfen nicht, wenn vor dem Verzögern bereits der
> nächste Interrupt registriert wird. Das dabei gesetzte Flag bleibt
> bestehen!

Das stimmt hab ich nicht dran gedacht, Danke

Krapao schrieb:
> Mach es richtig und lies die Artikel Interrupt und Entprellung.
> Und ich empfehle dir der besseren Les- und Debugbarkeit wegen die
> Schreibweise aus Bitmanipulation, statt der Zuweisung absoluter
> Hexwerte an SFRs.

Die Artikel hab ich schon gelesen aber ich hab nichts gefunden was auf 
mein problem hinweist, aber ich les sie nachmal.
Des mit den Bitmanipulationen hab ich in der angehängten datei gemacht, 
die gepostete version hab ich nur gerade getestet ob da das selbe 
auftritt, ich hab vor es wieder mit bitmanipulationen zu machen ;)

von Krapao (Gast)


Lesenswert?

> Des mit den Bitmanipulationen hab ich in der angehängten datei gemacht,

Nö eher nicht...

>>  //Timermodus einstellen CTC mit WGM22 und toggle mit COM2A0
>>  //TCCR2A = Timer/Counter Control Register A
>>  //[COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20]
>>  // übergabe bsp (1 << COM2A0) | (1 << WGM21)
>>  TCCR2A = 0x82;

würde man lesbarer schreiben (und es reicht eine Kommentarzeile)
1
  //Timermodus einstellen CTC mit WGM22 und toggle mit COM2A0
2
  TCCR2A = (1 << COM2A0) | (1 << WGM21);

Btw. kontrolliere Kommentar und Funktion bzgl. des WGM22/WGM21

>>  //interrupt enable für CTC
>>  //TIMSK2 = Timer/Counter2 Interrupt Mask Register
>>  // [- - - - - OCIE2B OCIE2A TOIE2]
>>  TIMSK2 = 0x02;

Wo issn die ISR dafür?
Ohne die schmiert der µC beim Auftreten des OCIE2A ab.

von johannes h. (j0hannes)


Lesenswert?

Krapao schrieb:
> Nö eher nicht...

ok ich dachte du meinst was anderes, ich dacht grad an die makros fürs 
led setzen.
Kann ich machen, hab ich mir keine großen gedanken gemacht :)

Krapao schrieb:
> Wo issn die ISR dafür?
> Ohne die schmiert der µC beim Auftreten des OCIE2A ab.

hab ich grad gelöscht damit es weng übersichtlicher is, ich hab aber net 
alles erwischt wie ich grad seh, danke für den Hinweis

von johannes h. (j0hannes)


Lesenswert?

So ich hab grad mal die Spannung am reset pin gemessen wenn ich den ich 
den Pininterrupt auslöse die bleipt auf 4,1V also kann ich wohl 
ausschliessen das ein Reset ausgelöst wird.

Ich denke das Programm springt aus der Interruptroutine einfach wieder 
an den Anfang der int main.

wodurch kann ein Sprung an eine falsche Adresse ausgelöst werden ?
Bzw. wie kann ich es verhindern?

Das Interrupttutorial hab ich nochmal gelesen aber da steht nichts 
darüber drin.

gruß jo

von Krapao (Gast)


Lesenswert?

> So ich hab grad mal die Spannung am reset pin gemessen wenn ich den ich
> den Pininterrupt auslöse die bleipt auf 4,1V also kann ich wohl
> ausschliessen das ein Reset ausgelöst wird.

Ich wüsste keine Stelle im Datenblatt in der dokumentiert ist, dass der 
Reset-Pin den Pegel wechselt, wenn der Programmcounter eine ISR nicht 
findet und dadurch einfach an der nächsten aufzufindenen Programmstelle, 
d.h. in der Regel am Programmanfang landet.

"Der AVR macht einen RESET bei fehlender ISR" ist eine laxe 
Formulierung. Es ist kein echter Reset im Sinn des Datenblattes. Es ist 
i.d.R. auch kein richtiges Reboot sondern ein wildgewildener 
Programmcounter...

> wodurch kann ein Sprung an eine falsche Adresse ausgelöst werden ?

Fehlende ISR zu einem aktivierten und auftretenden Interrupt.

> Bzw. wie kann ich es verhindern?

Die Situation wieder zusammenfassen und die eine aktuelle Source 
zeigen. Ich habe es schon erlebt, dass im Eifer des Programmiergefechts 
doch die falsche Version im AVR drin hatte... Bevorzugt ist die die 
AVR-GCC Version, weil mehr Leute die lesen können und ggf. simulieren 
können.

von johannes h. (j0hannes)


Lesenswert?

Krapao schrieb:
> Fehlende ISR zu einem aktivierten und auftretenden Interrupt.

Ok, aber ich denke das hab ich nicht.

Ich mach ab jetzt wieder mit der avr gcc version weiter. Ich hab noch 
nichts dran geändert, ich wüsste gran nicht was ich ändern sollte

von Krapao (Gast)


Lesenswert?

Eine andere "RESET" Ursache können beim Pollin-Board die Taster sein, 
wenn deren "Entprellkondensatoren" kurzfristig zu viel Strom ziehen. Ist 
meine ich bei dem Pollinboardartikel im Wiki erklärt. Ein gesetzter 
Brownout besonders der mit hohem Level und die Auswertung der 
Resetursache zum Beginn der main müsste diesen Fall aufklären können.

von Krapao (Gast)


Lesenswert?

> Ich mach ab jetzt wieder mit der avr gcc version weiter. Ich hab noch
> nichts dran geändert, ich wüsste gran nicht was ich ändern sollte

Habe ich doch oben geschrieben, dass du was ändern musst. Bei der 
peter.c im Anhang des ersten Beitrags fehlt eine ISR für den Timer oder 
der Init dafür ist zu viel. Die Version muss abstürzen!

Wenn du dann eine andere Version testest und die immer noch abstürzt, 
würde es IMHO Sinn machen, die aktuelle Version zu zeigen, wenn du Hilfe 
zur aktuellen Version haben willst, oder?

von johannes h. (j0hannes)


Angehängte Dateien:

Lesenswert?

Krapao schrieb:
> fehlt eine ISR für den Timer oder
> der Init dafür ist zu viel.

Ich dacht des macht nix wenn ich die funktion drin lass ich hab sie ja 
nicht aufgerufen. aber ich hab sie jetzt mal raus gemacht

von gaast (Gast)


Lesenswert?

Die Kommentare deiner Initialisierungsfunktion passen nicht zu den 
Werten, die du zuweist. Blöderweise lässt sich das ja schwer nachprüfen, 
da du es nach wie vor verweigerst, die Bits so zu setzen wie das jeder 
andere tut, nämlich lesbar.
Ohne das Datenblatt zu konsultieren tippe ich also einfach mal darauf, 
dass du tatsächlich den PCINT9 statt PCINT1 aktivierst. Dieser findet 
blöderweise keine ISR vor. Du hast wohl in das falsche PCMSK 
geschrieben.
Wobei die Initialisierungsroutine sowieso Mist ist.

von johannes h. (j0hannes)


Lesenswert?

gaast schrieb:
> Die Kommentare deiner Initialisierungsfunktion passen nicht zu den
> Werten, die du zuweist

welcher passt net? und wie soll es net passen sin doch nur die register 
mal angegeben.
1
//initialisiertuns Funktion den Externen Interrupt (Schalter)
2
void ExInt()
3
{
4
  //EICRA = External Interrupt Control Register A  [- - ISC21 ISC20 ISC11 ISC10 ISC01 ISC00]
5
  EICRA = 0x3F;
6
7
  //EIMSK = External Interrupt Mask Register       [- - - - INT2 INT1 INT0]
8
  EIMSK = 0x00;
9
    
10
  //EIFR = External Interrupt Flag Register    [- - - - - INTF2 INTF1 IINTF0]
11
  EIFR = 0x00;
12
13
  //PCICR = Pin Change Interrupt Control Register [- - - - PCIE3 PCIE2 PCIE1 PCIE0]
14
  PCICR  = 0x02;
15
16
  //PCMSK1 = Pin Change Mask Register 1      [PCINT15 PCINT14 PCINT13 PCINT12 PCINT11 PCINT10 PCINT9 PCINT8]
17
  PCMSK1 = 0x02;
18
19
}


PCINT9 ist der gewollte pininterrupt

von johannes h. (j0hannes)


Lesenswert?

Ich habs gelöst ich hab meine DDR gelöscht, sry das ich eure zeit 
verschwendet hab

von johannes h. (j0hannes)


Lesenswert?

Und Danke

von gaast (Gast)


Lesenswert?

johannes häußermann schrieb:
> PCINT9 ist der gewollte pininterrupt

Warum existiert dann keine ISR dafür? Die ISR im angehängten Code gehört 
zu PCINT1.
Das Data Direction Register hat mit diesem Problem nichts zu tun. Wie 
wäre es, wenn du du mal selbst Programmierst, anstatt irgendwelche 
Wizards zu nutzen, was du ja offensichtlich tust?

von Krapao (Gast)


Lesenswert?

Die folgende abgespeckte Version funktioniert im Simulator.

Die Änderungen:

# printf aus der ISR raus wg. Interrupt
# printf/uart komplett aus Programm raus wg. Simulator
# RESET-Anzeige LED2 zu Beginn von main()
# LED2-Blinken in while(1) als Herzschlag/Lebenszeichen
# F_CPU vor #include delay.h

Beim Simulieren vor jedes _delay_ms auskommentieren,
dann ist das Simulieren einfacher.

1
/*
2
 *  Pollin Funk AVR Board 1.1
3
 *  Atmega644P
4
 */
5
#include <stdint.h>
6
#include <avr/io.h>
7
#include <avr/interrupt.h>
8
#include <stdbool.h>
9
#include <stdio.h>
10
11
#ifndef F_CPU
12
#define F_CPU 16000000 // processor clock frequency
13
#warning kein F_CPU definiert
14
#endif
15
#include <util/delay.h>
16
 
17
#define LED1          6
18
#define LED2          5
19
20
#define DDR_Taster    DDRB
21
#define DDR_LED       DDRD
22
23
#define PORT_LED      PORTD
24
#define PORT_Taster   PORTB
25
26
#define LED_AN(LED)   (PORTD |=  (1<<(LED)))  //LED an gehen "funktion"
27
#define LED_AUS(LED)  (PORTD &= ~(1<<(LED)))  //LED aus gehen "funktion"
28
#define TASTER        PB1            // pin des tasters
29
#define TASTER_GEDRUECKT()  (PINB & (1<<TASTER))  //if(TASTER_GEDRUECKT())
30
31
32
void ExInt()
33
{
34
  //PCICR = Pin Change Interrupt Control Register [- - - - PCIE3 PCIE2 PCIE1 PCIE0]
35
  PCICR  = (1<<PCIE1);
36
37
  //PCMSK1 = Pin Change Mask Register 1      [PCINT15 PCINT14 PCINT13 PCINT12 PCINT11 PCINT10 PCINT9 PCINT8]
38
  PCMSK1 = (1<<PCINT9); // PCINT9/PB1
39
}
40
41
42
// ISR für PCINT15..8
43
ISR (PCINT1_vect)
44
{
45
  static bool ein = 0;
46
  if (!ein)
47
    LED_AN(LED1);
48
  else
49
    LED_AUS(LED1);
50
  ein ^= 1;
51
}
52
53
54
int main( void )
55
{
56
  DDR_LED = (1<<LED1)|(1<<LED1);                     
57
58
  // 10s Dauerlicht an LED1 und LED2 zeigt main() startet 
59
  // z.B. nach RESET
60
  LED_AN(LED2);
61
  for (uint8_t i=0; i<10; i++)
62
  {
63
    //_delay_ms(1000);
64
  }
65
66
  ExInt(); // Init PCINT1 = Tastendruck PB1 active-high
67
  sei();
68
 
69
  while(1)
70
  {
71
    LED_AUS(LED2);
72
    _delay_ms(500);
73
    LED_AN(LED2);
74
    _delay_ms(500);
75
    //
76
    // Pegelwechsel an PB1 (Taster1) toggelt LED1 über PCINTx ISR
77
    // Achtung Prelleffekte sind wahrscheinlich!
78
    //
79
  }  
80
}

von johannes h. (j0hannes)


Lesenswert?

Danke schön war mir eine große Hilfe.
eine Frage hätt ich noch wie hast du des simuliert ?
gibt es da ne Anleitung dazu?

von Krapao (Gast)


Lesenswert?

Ich habe das mit Start Debugging im AVR Studio und dessen eingebautem 
AVR Simulator simuliert.

Wie geschrieben, habe ich die _delay_ms() auskommentiert, weil sonst die 
Simulation zu lange dauert.

Dann kann man mit F10 bzw. F11 im Einzelschritt durch das Programm 
gehen. Einen Breakpoint habe ich mit F9 auf die ISR gesetzt.

In der I/O View habe ich PORTB geöffnet und nach dem sei() durch 
Pegelwechsel im PB1 der PINB Anzeige den Interrupt ausgelöst.

Der Simulator landet dann beim nächsten Einzelschritt auf dem Breakpoint 
in der ISR

Anleitung habe ich dazu nicht gelesen, die Tasten für den Debugger sind 
ja markiert und ich kenne die Grundfunktionen eines Debuggers aus 
anderen Toolchains.

Aber AVR Studio müsste in der Hilfe aber was zum Debugger/Simulator 
schreiben, denke ich.

von johannes h. (j0hannes)


Lesenswert?

Hallo
Ich bins nochmal ich hab mein Programm jetzt mal soweit fertig.
Ich hab mich jetzt dafür entschieden keinen Externen Interrupt zu 
verwenden.
Leider hat meine Lösung nicht funktioniert.
Jetzt stehe ich wieder vor dem Problem das mein Programm bei jedem 
Tastendruck wieder die initialisierung ausführt.
Ich frag mich jetzt ob mein Makro so richtig ist
1
#define TASTER_GEDRUECKT()  (PINB & (1<<PB1))
und ob die initialisierung passt
1
   
2
DDR_Taster |= TASTER;
1
/*------------------------------------------------------------------*/
2
/*        Funktion: Einschaltverzögerung                            */
3
/*                                                                  */
4
/*      Timer Interrupt für Zeitbasis (CTC Mode),entprellen         */
5
/*    und fallunterscheidung (nicht-,kurz- oder lang-gedrückt)      */
6
/*                                                                  */
7
/*          Quarzfrequenz = 16 MHz                                  */
8
/*                                                                  */
9
/*      Pollin Funk-AVR-Evaluationsboard v1.1 mit ATmega644P        */
10
/*                                                                  */
11
/*------------------------------------------------------------------*/
12
//verwendete Biblioteken
13
#include <avr/io.h>                  
14
#include <avr/interrupt.h>
15
#include <stdbool.h>
16
#include <stdio.h>
17
18
19
#define F_CPU           16000000          // processor clock frequency
20
21
#define TASTER        ( 1<<PB1 )          //Bitoperation für den Taster Pin
22
#define LED1      6              //Pin der LED 1
23
#define LED2            5              //Pin der LED 2
24
25
#define DDR_Taster       DDRB            //data direction des Port B
26
#define DDR_LED          DDRD            //data direction des Port D
27
28
#define PORT_LED         PORTD            //Port D 
29
#define PORT_Taster     PORTB            //Port B 
30
31
32
#define LED_AN(LED)      (PORTD |=  (1<<(LED)))  //LED an gehen "funktion"
33
#define LED_AUS(LED)    (PORTD &= ~(1<<(LED)))  //LED aus gehen "funktion"
34
#define TASTER_GEDRUECKT()  (PINB & (1<<PB1))    //if(TASTER_GEDRUECKT())
35
36
37
volatile unsigned int interrupt_zaehler = 0;    //Deklaration des Zeitbasis Zählers
38
volatile unsigned int DelayON          = 0;    //Deklaration der berechneten Verzögerung
39
volatile unsigned int tasten_zeit     = 0;    //Deklaration des entprell Zählers
40
41
volatile unsigned char tasten_modus   = 0;    // Deklaration der Tasten Modi
42
                          //0 ist nicht gedrückt 
43
                          //1 ist kurz gedrückt 
44
                          //2 st lang gedrückt
45
volatile unsigned char enable_interrupt_zaehler = 0;//Deklatation wann Zeitbasis gestartet wird
46
volatile unsigned char Funktion = 0;        //Funktionswahl 0=einschaltverzögerung 1=ausschaltverzögerung 2=treppenhausfunktion
47
48
volatile bool LedAn = 0;
49
volatile bool ein = 0;                //Deklaration des letztentlichen Einschaltend der LED
50
51
//------------------------------------------------------------------------------------------------------
52
//Funktionen
53
54
//Printf umleitung an USART, wartet immer bis ein zeichen ausgegeben ist
55
int uart_putchar( char c, FILE *stream )
56
{
57
58
    loop_until_bit_is_set( UCSR0A, UDRE0 );     //Warten bis Zeichen ausgegeben ist
59
    UDR0 = c;                     //Zeichen ins Ausgaberegister Schreiben
60
    return 0;                     //Wenn fertig 0 zurück geben
61
}
62
63
//variable mystdout vom typ file der ich den USART stream zuweise
64
static FILE mystdout = FDEV_SETUP_STREAM( uart_putchar, NULL, _FDEV_SETUP_WRITE );
65
66
//Initialisierung des Timers 2A CTC Mode
67
void timer2A_init_wave()
68
{
69
//timer konfiguration, 8bit = 256  
70
  
71
  //vergleichen: TCNT2 == OCR2A, wenn ja kann bedingung als interrupt oder waveform Pin (OC2A) Bedingung genutzt werden
72
  OCR2A = 0xFF;
73
74
  //Timermodus einstellen CTC mit WGM22 und toggle mit COM2A0
75
  //TCCR2A = Timer/Counter Control Register A [COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20] übergabe bsp (1 << COM2A0) | (1 << WGM21)
76
  //TCCR2A = 0x82;
77
78
  TCCR2A = (1 << COM2A1) | (1 << WGM21);
79
  //TCCR2B = Timer/Counter Control Register B [FOC2A FOC2B - - WGM22 CS22 CS21 CS20 ] 16MHz/(1024*256)       
80
  //TCCR2B = 0x07;
81
82
  TCCR2B = (1 << CS22) | (1 << CS21) | (1 << CS20);  
83
            
84
  //interrupt enable für CTC
85
  //TIMSK2 = Timer/Counter2 Interrupt Mask Register[- - - - - OCIE2B OCIE2A TOIE2]
86
  //TIMSK2 = 0x02;
87
  TIMSK2 = (1 << OCIE2A);  
88
    
89
}
90
91
//------------------------------------------------------------------------------------------------------
92
//Interrupt Service Rputine des Timers 2A
93
ISR (TIMER2_COMPA_vect)
94
{
95
  //Start des Entprell Zählers
96
  if( TASTER_GEDRUECKT() )
97
  {   
98
    tasten_zeit++;
99
      printf("tasten_zeit: %d \r", tasten_zeit);
100
  }
101
    
102
  else tasten_zeit = 0;
103
 
104
105
106
  //Tastenmodus 2 setzen (Taster lange gedrückt), bedingung für Interruptzähler NICHT starten
107
/*  if(tasten_zeit >= 200)
108
  {   
109
       tasten_modus = 2;
110
    enable_interrupt_zaehler = 0;
111
  }*/
112
113
  //Tastenmodus 1 setzen (Taster kurz gedrückt), bedingung für Interruptzähler starten
114
  if (tasten_zeit >= 5)
115
  {
116
    //tasten_zeit = 0;
117
    //tasten_modus = 1;
118
119
120
    switch(Funktion)
121
    {  
122
      case 1:  //Einschaltverzögerung
123
        if(LedAn) ein = 1;
124
        else 
125
        {
126
          enable_interrupt_zaehler = 1; 
127
          //printf("BLUBB \r");
128
        }
129
      break;
130
      case 2:  //Ausschaltverzögerung
131
        if(LedAn) enable_interrupt_zaehler = 1;
132
        else ein = 1;
133
      break;
134
      case 3://Treppenhausfunktion
135
        if(LedAn) interrupt_zaehler = 0;
136
        else ein = 1;
137
      break;
138
    }
139
        
140
    //printf("tasten_modus: %d \r", tasten_modus);
141
  }
142
  //Tastenmodus 0 (Taster nicht gedrückt), LED geht aus
143
  else
144
  { 
145
      tasten_modus = 0; 
146
    //printf("tasten_modus: %d \r", tasten_modus);
147
  }
148
149
  //Zeitbasis starten
150
  if(enable_interrupt_zaehler == 1)
151
  {
152
    interrupt_zaehler++;
153
    //Bedingung ob Verzögerungszeit erreicht
154
    if(interrupt_zaehler >= DelayON)
155
    {
156
      ein = 1;
157
      enable_interrupt_zaehler = 0;
158
      interrupt_zaehler = 0;
159
      //printf("ein: %d \r", ein);
160
    }
161
  }
162
  else 
163
  {
164
    interrupt_zaehler = 0;
165
    //printf("interrupt_zaehler: %d \r",interrupt_zaehler);
166
  }
167
168
169
170
171
172
173
}
174
175
176
 
177
//------------------------------------------------------------------------------------------------------
178
//Hauptroutine
179
 
180
int main( void )
181
{
182
//ununterbrochene Initialisierung
183
  cli();
184
  //mystd wird auf stdout umgeleitet
185
  stdout = &mystdout;
186
  
187
  //USART initialisierung
188
  UCSR0C = 0b00000110;
189
  UCSR0B = 0b10011000;
190
  UBRR0 = 103;  //9600 Baud bei 16Mhz System Clock
191
  
192
  //Eingabevariable in sekunden für Verzögerungszeit
193
  unsigned int Delay = 0;
194
195
196
  //Angabe in sekunden
197
  Delay = 1;
198
  //Berechnung der Anzahl der zu verzögerten Interrupts
199
  DelayON = (F_CPU * Delay)/ 262144;//(16MHz * Delay)(1024 * 256)
200
201
  // setzen der data direction in PORT D von den LEDs
202
  DDR_LED |= (1 << LED1) | (1 << LED2);
203
  
204
  // Taster initialisierung TASTER = (1<<PB1)
205
  //DDR_Taster &= ~TASTER;                // data direction PB1
206
  //PORT_Taster |= TASTER;                // pull up Widerstand angeschalten
207
 
208
   DDR_Taster |= TASTER; 
209
210
  //initialisierung des Timer 2A
211
  timer2A_init_wave();
212
  Funktion = 1; 
213
 
214
  sei();
215
216
//Hauptprogramm
217
  printf(" START \r");
218
  //printf(" DelayON:%d \r", DelayON);
219
 
220
  while(1)
221
  {
222
    //printf(" interrupt_zaehler:%d \r", interrupt_zaehler);
223
    //wenn Verzögerungszeit abgelaufen LED anschalten
224
    if( ein == 1) 
225
    {
226
      if(LedAn)
227
      {
228
        printf("LED_AN - mache jetzt aus\r");
229
        LED_AUS(LED1);
230
        LedAn = 0;
231
        ein = 0;
232
        //enable_interrupt_zaehler = 0;
233
        
234
      }
235
      else if(!LedAn)
236
      {
237
        printf("LED_AUS - mache jetzt an\r");
238
        LED_AN(LED1);
239
        LedAn = 1;
240
        ein = 0;
241
        //enable_interrupt_zaehler = 0;
242
      }
243
    }
244
        
245
246
   }  
247
}

von Karl H. (kbuchegg)


Lesenswert?

johannes häußermann schrieb:

> und ob die initialisierung passt
>
1
> DDR_Taster |= TASTER;
2
>

damit schaltest du aber den Pin auf Ausgang.
Für einen Taster nicht wirklich das, was man tun sollte.

Zum Rest deines Programms: Was soll das eigentlich machen? Das sieht 
alles sehr unübersichtlich und kompliziert aus.

von johannes h. (j0hannes)


Lesenswert?

Das programm ist eine zeitansteuerung für eine Led,
dazu benutze ich den timer zu generierung einer zeitbasis.

Im moment teste ich funktion 1 also die einschaltverzögerung.

ich schalte den pin auf ausgang weil daran der taster ist, ich dachte 
das macht man so, wie muss man den pin an dem ein taster sitz sonst 
initialisieren?

von johannes h. (j0hannes)


Lesenswert?

Hallo Alle zusammen
Bei der initialisierung habe ich mich vertan
DDR_Taster |= TASTER;//falsch
das muss lauten
DDR_Taster &= ~TASTER;//richtig
Jedoch löst das mein Problem nicht!

Wenn ich den Pull up widerstand einschalte macht das programm keinen 
reset kann damit jemand etwas anfangen mir ist es schleierhaft warum der 
Reset kommt bzw warum der Pull up widerstand den reset verhindert.
1
/*------------------------------------------------------------------*/
2
/*        Funktion: Einschaltverzögerung            */
3
/*                                  */
4
/*      Timer Interrupt für Zeitbasis (CTC Mode),entprellen    */
5
/*    und fallunterscheidung (nicht-,kurz- oder lang-gedrückt)  */
6
/*                                  */
7
/*          Quarzfrequenz = 16 MHz              */
8
/*                                  */
9
/*      Pollin Funk-AVR-Evaluationsboard v1.1 mit ATmega644P    */
10
/*                                  */
11
/*          Autor: Johannes Häußermann            */
12
/*          Email: Johannes_H88@gmx.de            */
13
/*------------------------------------------------------------------*/
14
//verwendete Biblioteken
15
#include <avr/io.h>                  
16
#include <avr/interrupt.h>
17
#include <stdbool.h>
18
#include <stdio.h>
19
20
21
#define F_CPU           16000000          // processor clock frequency
22
23
#define TASTER        ( 1<<PORTB1 )          //Bitoperation für den Taster Pin
24
#define LED1      6              //Pin der LED 1
25
#define LED2            5              //Pin der LED 2
26
27
#define DDR_Taster       DDRB            //data direction des Port B
28
#define DDR_LED          DDRD            //data direction des Port D
29
30
#define PORT_LED         PORTD            //Port D 
31
#define PORT_Taster     PORTB            //Port B 
32
33
34
#define LED_AN(LED)      (PORTD |=  (1<<(LED)))  //LED an gehen "funktion"
35
#define LED_AUS(LED)    (PORTD &= ~(1<<(LED)))  //LED aus gehen "funktion"
36
#define TASTER_GEDRUECKT()  (PINB & (1<<PORTB1))    //if(TASTER_GEDRUECKT())
37
38
39
volatile unsigned int interrupt_zaehler = 0;    //Deklaration des Zeitbasis Zählers
40
volatile unsigned int DelayON          = 0;    //Deklaration der berechneten Verzögerung
41
volatile unsigned int tasten_zeit     = 0;    //Deklaration des entprell Zählers
42
43
volatile unsigned char tasten_modus   = 0;    // Deklaration der Tasten Modi
44
                          //0 ist nicht gedrückt 
45
                          //1 ist kurz gedrückt 
46
                          //2 st lang gedrückt
47
volatile unsigned char enable_interrupt_zaehler = 0;//Deklatation wann Zeitbasis gestartet wird
48
volatile unsigned char Funktion = 0;        //Funktionswahl 0=einschaltverzögerung 1=ausschaltverzögerung 2=treppenhausfunktion
49
50
volatile bool LedAn = 0;
51
volatile bool ein = 0;                //Deklaration des letztentlichen Einschaltend der LED
52
53
//------------------------------------------------------------------------------------------------------
54
//Funktionen
55
56
//Printf umleitung an USART, wartet immer bis ein zeichen ausgegeben ist
57
int uart_putchar( char c, FILE *stream )
58
{
59
60
    loop_until_bit_is_set( UCSR0A, UDRE0 );     //Warten bis Zeichen ausgegeben ist
61
    UDR0 = c;                     //Zeichen ins Ausgaberegister Schreiben
62
    return 0;                     //Wenn fertig 0 zurück geben
63
}
64
65
//variable mystdout vom typ file der ich den USART stream zuweise
66
static FILE mystdout = FDEV_SETUP_STREAM( uart_putchar, NULL, _FDEV_SETUP_WRITE );
67
68
//Initialisierung des Timers 2A CTC Mode
69
void timer2A_init_wave()
70
{
71
//timer konfiguration, 8bit = 256  
72
  
73
  //vergleichen: TCNT2 == OCR2A, wenn ja kann bedingung als interrupt oder waveform Pin (OC2A) Bedingung genutzt werden
74
  OCR2A = 0xFF;
75
76
  //Timermodus einstellen CTC mit WGM22 und toggle mit COM2A0
77
  //TCCR2A = Timer/Counter Control Register A [COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20] übergabe bsp (1 << COM2A0) | (1 << WGM21)
78
  //TCCR2A = 0x82;
79
  TCCR2A = (1 << COM2A1) | (1 << WGM21);
80
81
  //TCCR2B = Timer/Counter Control Register B [FOC2A FOC2B - - WGM22 CS22 CS21 CS20 ] 16MHz/(1024*256)       
82
  //TCCR2B = 0x07;
83
  TCCR2B = (1 << CS22) | (1 << CS21) | (1 << CS20);  
84
            
85
  //interrupt enable für CTC
86
  //TIMSK2 = Timer/Counter2 Interrupt Mask Register[- - - - - OCIE2B OCIE2A TOIE2]
87
  //TIMSK2 = 0x02;
88
  TIMSK2 = (1 << OCIE2A);  
89
    
90
}
91
92
//------------------------------------------------------------------------------------------------------
93
//Interrupt Service Rputine des Timers 2A
94
ISR (TIMER2_COMPA_vect)
95
{
96
  //Start des Entprell Zählers
97
  if( TASTER_GEDRUECKT() )
98
  {   
99
    tasten_zeit++;
100
      printf("tasten_zeit: %d \r", tasten_zeit);
101
  }
102
    
103
  else tasten_zeit = 0;
104
 
105
106
107
  //Tastenmodus 2 setzen (Taster lange gedrückt), bedingung für Interruptzähler NICHT starten
108
/*  if(tasten_zeit >= 200)
109
  {   
110
       tasten_modus = 2;
111
    enable_interrupt_zaehler = 0;
112
  }*/
113
114
  //Tastenmodus 1 setzen (Taster kurz gedrückt), bedingung für Interruptzähler starten
115
  if (tasten_zeit >= 10)
116
  {
117
    //tasten_zeit = 0;
118
    //tasten_modus = 1;
119
120
121
    switch(Funktion)
122
    {  
123
      case 1:  //Einschaltverzögerung
124
        if(LedAn) ein = 1;
125
        else 
126
        {
127
          enable_interrupt_zaehler = 1; 
128
          //printf("BLUBB \r");
129
        }
130
      break;
131
      case 2:  //Ausschaltverzögerung
132
        if(LedAn) enable_interrupt_zaehler = 1;
133
        else ein = 1;
134
      break;
135
      case 3://Treppenhausfunktion
136
        if(LedAn) interrupt_zaehler = 0;
137
        else ein = 1;
138
      break;
139
    }
140
        
141
    //printf("tasten_modus: %d \r", tasten_modus);
142
  }
143
  //Tastenmodus 0 (Taster nicht gedrückt), LED geht aus
144
  else
145
  { 
146
      tasten_modus = 0; 
147
    //printf("tasten_modus: %d \r", tasten_modus);
148
  }
149
150
  //Zeitbasis starten
151
  if(enable_interrupt_zaehler == 1)
152
  {
153
    interrupt_zaehler++;
154
    //Bedingung ob Verzögerungszeit erreicht
155
    if(interrupt_zaehler >= DelayON)
156
    {
157
      ein = 1;
158
      enable_interrupt_zaehler = 0;
159
      interrupt_zaehler = 0;
160
      //printf("ein: %d \r", ein);
161
    }
162
  }
163
  else 
164
  {
165
    interrupt_zaehler = 0;
166
    //printf("interrupt_zaehler: %d \r",interrupt_zaehler);
167
  }
168
169
170
171
172
173
174
}
175
176
177
 
178
//------------------------------------------------------------------------------------------------------
179
//Hauptroutine
180
 
181
int main( void )
182
{
183
//ununterbrochene Initialisierung
184
  //cli();
185
  //mystd wird auf stdout umgeleitet
186
  stdout = &mystdout;
187
  
188
  //USART initialisierung
189
  UCSR0C = 0b00000110;
190
  UCSR0B = 0b10011000;
191
  UBRR0 = 103;  //9600 Baud bei 16Mhz System Clock
192
  
193
  //Eingabevariable in sekunden für Verzögerungszeit
194
  unsigned int Delay = 0;
195
196
197
  //Angabe in sekunden
198
  Delay = 1;
199
  //Berechnung der Anzahl der zu verzögerten Interrupts
200
  DelayON = (F_CPU * Delay)/ 262144;//(16MHz * Delay)(1024 * 256)
201
202
  // setzen der data direction in PORT D von den LEDs
203
  DDR_LED |= (1 << LED1) | (1 << LED2);
204
  
205
  // Taster initialisierung TASTER = (1<<PB1)
206
  DDR_Taster &= ~TASTER;                // data direction PB1
207
  PORT_Taster |= TASTER;                // pull up Widerstand angeschalten               
208
  MCUCR &= ~(1 << PUD); 
209
210
211
212
  //initialisierung des Timer 2A
213
  timer2A_init_wave();
214
  Funktion = 1; 
215
 
216
  sei();
217
218
//Hauptprogramm
219
  printf(" START \r");
220
  //printf(" DelayON:%d \r", DelayON);
221
 
222
  while(1)
223
  {
224
    //printf(" interrupt_zaehler:%d \r", interrupt_zaehler);
225
    //wenn Verzögerungszeit abgelaufen LED anschalten
226
    if( ein == 1) 
227
    {
228
      if(LedAn)
229
      {
230
        printf("LED_AN - mache jetzt aus\r");
231
        LED_AUS(LED1);
232
        LedAn = 0;
233
        ein = 0;
234
        //enable_interrupt_zaehler = 0;
235
        
236
      }
237
      else if(!LedAn)
238
      {
239
        printf("LED_AUS - mache jetzt an\r");
240
        LED_AN(LED1);
241
        LedAn = 1;
242
        ein = 0;
243
        //enable_interrupt_zaehler = 0;
244
      }
245
    }
246
        
247
248
   }  
249
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.