Forum: Mikrocontroller und Digitale Elektronik externer Interrupt


von Tartaruga (Gast)


Lesenswert?

Hi
tut mir Leid wenn ich euch schon wieder mit sehr einfachen Frage quäle:
Ich programmiere mit einem AT90CAN128 auf einem DVK90CAN1. Ich will die 
Tasten ansteuern damit z.B.: die Leds damit aus und eingeschalten 
werden.
In der manual vom Board hab ich gelesen das die Tasten einen externen 
Interrupt aulösen. INT7 - INT4. Leider springt mir das Programm nicht in 
die ISR. Ihr könnt ihr mir sicher helfen.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
ISR(INT7_vect){
5
6
PORTA = 0xFF;
7
8
}//end isr int7 
9
10
int main(){
11
DDRA = 0xFF;//direction for LEDs are output
12
DDRE = 0xFF;//direction is ouput
13
PINE = 0xFF;//PINE are set 1
14
EIMSK = 0xF0;//Interrupt for INT7 to INT 4 are available
15
EICRB = 0x00;//interrupt for INT7-INT4 are lowLevel
16
SREG = 0x80;//global Interrupt are available
17
18
19
20
for(;;);//endloschleife
21
22
return(0);
23
}//end main

von Patrick (Gast)


Lesenswert?

falsch ist:
1
PINE = 0xFF;//PINE are set 1
richtig wäre:
1
PORTE = 0xFF

von Tartaruga (Gast)


Lesenswert?

Danke für die schnelle Antwort. Leider funktioniert das immer noch 
nicht. Siehst du vielleicht noch einen anderen Fehler???

von Patrick (Gast)


Lesenswert?

Ausserdem ist dein Programmierstil etwas unübersichtlich. Probier doch 
mal folgendes:
1
EIMSK |= (1<<INT4) | (1<<INT5) | (1<<INT6) | (1<<INT7);
2
EICRB &= ((1<<ISC40) | (1<<ISC41) | ...);
3
SREG |= (1<<I);
Das ist zwar etwas aufwendiger, erleichtert es aber zu verstehen, was 
genau programmiert ist.

von Tartaruga (Gast)


Lesenswert?

Hmmm jetzt kenn ich mich nicht mehr aus. Wieso ist das einfacher als nur 
die Registereinstellungen in hex zuweise???

von Patrick (Gast)


Lesenswert?

Ich würde EICRB nich auf  low-level, sonder auf fallende Flanke 
implementieren (Datenblatt Seite 94, Table 10-3)
also:
1
EICRB &= ((1<<ISC40) | (1<<ISC50) | (1<<ISC60) |( 1<<ISC70));
2
EICRB |= (1<<ISC41) | (1<<ISC51) | (1<<ISC61) | (1<<ISC71);

Hast Du den Taster entprellt?

von Patrick (Gast)


Lesenswert?

>Wieso ist das einfacher
Weil Du so nachher (auch nach mehreren Wochen) noch genau siehst, welche 
Bits im Register nach Datenblatt gesetzt und gelöscht sind.

von Patrick (Gast)


Lesenswert?


von Patrick (Gast)


Lesenswert?

PORTA solltest Du am Anfang auf 0 setzen:
1
PORTA = 0x00;
Damit der Ausgang definiert auf 0 liegt.

Andere Frage:
Wie sind die LED beschalten? High- oder Low-activ?

von Patrick (Gast)


Lesenswert?

Jetzt hab ich den Fehler entdeckt.

DDRE ist ja gar kein Output.
Richtig wäre:
1
DDRE = 0x00;

von Tartaruga (Gast)


Lesenswert?

also mit dem & operator setz ich eine 1 und mit dem ODER-Operator 
schreib ich eine 0 ins Registerbit
Was heisst die Tasten entprellt?? Das komplette Programm was ich 
geschrieben habe hab ich eh im ersten Beitrag geschrieben.
Offensichtlich ist das Tastenansteuern nicht so einfach wie ich dachte.

von Patrick (Gast)


Lesenswert?

Sorry, wenn ich Dich jetzt verwirre, aber oben hab ich noch einen 
kleinen Fehler gemacht.
Es heisst nicht
1
EICRB &= ((1<<ISC40) | (1<<ISC41) | ...);
sondern jeweils
1
EICRB &= ~((1<<ISC40) | (1<<ISC41) | ...);

Ich hab das ~ vergessen.

Tasten entprellen: Entprellung

von Patrick (Gast)


Lesenswert?

lies das hier mal gründlich durch. Vielleicht ist dann einiges klarer:
Bitmanipulation

von Tartaruga (Gast)


Lesenswert?

Danke nochmals für deine Hilfe. Werd mich da mal ein bisserl einlesen 
und es dann nocheinmal programmieren

von Patrick (Gast)


Lesenswert?

Funktioniert es denn jetzt, wenn Du DDRE als Eingang anstatt als Ausgang 
definierst?

von Tartaruga (Gast)


Lesenswert?

nein da geht gar nichts. Ich hab ja die Tasten auch nicht entprellt weil 
ich dachte das beim ersten Kontakt ein Interrupt ausgelöst wird.

von Tartaruga (Gast)


Lesenswert?

ahh geht doch ich hab einen Beitrag von dir übersehen
super danke jetzt funkt so wie es soll

von Niels H. (monarch35)


Lesenswert?

Dazu eine Frage an die Allgemeinheit:

Warum liest man nichts mehr von sei();? Ist das im StartupCode vom GCC 
schon drin?

An der OP:
Programcode zu schreiben, den eine Maschine versteht, kann jeder. Die 
Kunst liegt darin, den Code auch für den Menschen verständlich und 
wartbar zu halten.

von Patrick (Gast)


Lesenswert?

sei() ist doch nichts anderes wie
[c]SREG |= (1<<I);

von Niels H. (monarch35)


Lesenswert?

Patrick wrote:
> sei() ist doch nichts anderes wie
> [c]SREG |= (1<<I);

ok, das war mir neu...danke.

von Tartaruga (Gast)


Lesenswert?

Ich hab die Erfrahrung gemacht das beides funktioniert. sei(); und SREG 
= 0x80;
Wenn ich das status register so SREG |= (1<<I); beschreibe bekomme ich 
eine Fehlermeldung vom Compiler

von Patrick (Gast)


Lesenswert?

Dann mach folgendes:
1
SREG |= (1<<7);  //Bit 7 von SREG auf 1

von Johannes M. (johnny-m)


Lesenswert?

Patrick wrote:
> sei() ist doch nichts anderes wie
> [c]SREG |= (1<<I);
Doch, das ist sehr wohl was anderes! "sei()" ist atomar, Deine Version 
aber nicht! Aus Deiner Version werden 3 Assembler-Befehle, sei ist ein 
einziger.

von Tartaruga (Gast)


Lesenswert?

Ok das geht jetzt
danke

von Tartaruga (Gast)


Lesenswert?

Ich hab da noch eine andere Frage die nicht so ganz zum Thema passt. 
Wenn ich mit dem Input Capture arbeite und mit die Periodendauer eines 
Rechtecksignals ausrechen will. Auf welchen Bus muss das signal anliegen 
das das funktioniert. Ich hab in der Manual nur immer 8-Bit Bus gelesen.

von crazy horse (Gast)


Lesenswert?

@Johannes:
Das kan man nicht so allgemein behaupten.
CodeVision macht daraus:
82 SREG |= (1<<I);
000a2 9478        BSET 7

von Johannes M. (johnny-m)


Lesenswert?

crazy horse wrote:
> @Johannes:
> Das kan man nicht so allgemein behaupten.
> CodeVision macht daraus:
> 82 SREG |= (1<<I);
> 000a2 9478        BSET 7
OK, wenn CodeVision das hinbekommt... Der AVR-GCC machts nicht. Und 
bevor man jedes mal erst ins Assembler-Listing schauen muss, um zu 
erfahren, was der Compiler da wirklich draus macht, schreibt man doch 
besser gleich die richtige Anweisung hin, aus der der Compiler mit 
Sicherheit den korrekten Assembler-Code macht (OK, in CodeVision gibt es 
die "Funktion" sei() nicht, da muss man eh #asm("sei") schreiben...)

Abgesehen davon halte ich es sowieso für unsinnig, so einen Ausdruck da 
hinzuschreiben, wenn es kürzer und prägnanter geht...

von Niels H. (monarch35)


Lesenswert?

Ok, ich hab aber verstanden. Die Wirkung ist die selbe... Viele Wege 
führen nach Ram...ähh Rom..

von Johannes M. (johnny-m)


Lesenswert?

Niels Hüsken wrote:
> Ok, ich hab aber verstanden. Die Wirkung ist die selbe...
Nö, ist sie nicht. Das merkst Du spätestens dann, wenn Du die Interrupts 
*de*aktivieren möchtest und das eben drei Befehle braucht anstatt einen. 
Zugegeben: beim sei (also bei der Freigabe) ist es i.d.R. wirklich 
unkritisch, aber zumindest beim cli kann es zu unerwünschten 
Nebeneffekten kommen (natürlich auch nur in Ausnahmefällen, aber 
immerhin, warum sich was unsinniges angewöhnen)...

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.