PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : wie benuzt man ein INTERRUPT



dark emporer
16.05.2005, 18:05
bitte nur ein kuzes beispiel um zu testen ob ein interrapt überhaupt funktioniert

pebisoft
16.05.2005, 19:00
dann musst du sagen in was du proggen tust.
mfg pebisoft

dark emporer
16.05.2005, 20:38
volatile sagt mir leider garnichts

dark emporer
16.05.2005, 20:43
#include <stdint.h>
was mach die datei da ich sie nicht habe kann ich das leider nicht selbst herasufinden

dark emporer
16.05.2005, 21:02
in c. ich binutze winavr

lekro
16.05.2005, 21:12
Wenn du nicht am Quellcode des Compilers rumgepfuscht hast (unwahrscheinlich, da du Windows benutzt), funktionieren Interrupts auf jeden Fall.

Du musst schon genauer beschreiben, was du erreichen und testen möchtest.

dark emporer
16.05.2005, 21:15
#include <avr/pgmspace.h>
#include "kb.h"
#include "serial.h"
#include "gpr.h"
#include <avr/signal.h>
#include <avr/interrupt.h>
#include "scancodes.h"
#include <stdio.h>
#include <avr/io.h>

#define BUFF_SIZE 64

unsigned char edge, bitcount; // 0 = neg. 1 = pos.

unsigned char kb_buffer[BUFF_SIZE];
unsigned char *inpt, *outpt;



void init_kb(void)
{
DDRD = DDRD & 0xFB;
inpt = kb_buffer; // Initialize buffer
outpt = kb_buffer;
buffcnt = 0;

MCUCR = 2; // INT0 interrupt on falling edge
edge = 0; // 0 = falling edge 1 = rising edge
bitcount = 11;
// enable_external_int(SIG_INTERRUPT0);
}

SIGNAL(SIG_INTERRUPT0)
{buffcnt++; //zum testen
static unsigned char data; // Holds the received scan code

if (!edge) // Routine entered at falling edge
{
if(bitcount < 11 && bitcount > 2) // Bit 3 to 10 is data. Parity bit,
{ // start and stop bits are ignored.
data = (data >> 1);
if(PIND & 8)
data = data | 0x80; // Store a '1'
}

MCUCR = 3; // Set interrupt on rising edge
edge = 1;

} else { // Routine entered at rising edge

MCUCR = 2; // Set interrupt on falling edge
edge = 0;

if(--bitcount == 0) // All bits received
{
decode(data);
bitcount = 11;
}
}
}


void decode(unsigned char sc)
{
static unsigned char is_up=0, shift = 0, mode = 0;
unsigned char i;

if (!is_up) // Last data received was the up-key identifier
{
switch (sc)
{
case 0xF0 : // The up-key identifier
is_up = 1;
break;

case 0x12 : // Left SHIFT
shift = 1;
break;

case 0x59 : // Right SHIFT
shift = 1;
break;

case 0x05 : // F1
if(mode == 0)
mode = 1; // Enter scan code mode
if(mode == 2)
mode = 3; // Leave scan code mode
break;

default:
if(mode == 0 || mode == 3) // If ASCII mode
{
if(!shift) // If shift not pressed,
{ // do a table look-up
for(i = 0; unshifted[i][0]!=sc && unshifted[i][0]; i++);
if (unshifted[i][0] == sc) {
put_kbbuff(unshifted[i][1]);
}
} else { // If shift pressed
for(i = 0; shifted[i][0]!=sc && shifted[i][0]; i++);
if (shifted[i][0] == sc) {
put_kbbuff(shifted[i][1]);
}
}
} else{ // Scan code mode
print_hexbyte(sc); // Print scan code
put_kbbuff(' ');
put_kbbuff(' ');
}
break;
}
} else {
is_up = 0; // Two 0xF0 in a row not allowed
switch (sc)
{
case 0x12 : // Left SHIFT
shift = 0;
break;

case 0x59 : // Right SHIFT
shift = 0;
break;

case 0x05 : // F1
if(mode == 1)
mode = 2;
if(mode == 3)
mode = 0;
break;
case 0x06 : // F2
clr();
break;
}
}
}

void put_kbbuff(unsigned char c)
{
if (buffcnt<BUFF_SIZE) // If buffer not full
{
*inpt = c; // Put character into buffer
inpt++; // Increment pointer

buffcnt++;

if (inpt >= kb_buffer + BUFF_SIZE) // Pointer wrapping
inpt = kb_buffer;
}
}

int kbgetchar(void)
{
int byte;
while(buffcnt == 0); // Wait for data

byte = *outpt; // Get byte
outpt++; // Increment pointer

if (outpt >= kb_buffer + BUFF_SIZE) // Pointer wrapping
outpt = kb_buffer;

buffcnt--; // Decrement buffer count

return byte;
}

lekro
17.05.2005, 01:14
Ok, du hast einen Quellcode gepostet (benutz das nächste Mal bitte code-Tags). Und was ist nun deine Frage?

Willst du, dass ich völlig kommentarlos ein Kochrezept poste? Meine Kristallkugel ist leider gerade in der Reperatur... :/

dark emporer
17.05.2005, 06:43
ich habe zum testen

SIGNAL(SIG_INTERRUPT0)
{
buffcnt++; //zum testen

reingeschriben. In der main lase ich buffcnt auf einem LCD anzeigen. buffcnt bleibt null egal was ich an dem pin mache

PicNick
17.05.2005, 09:42
Du mußt buffcnt mit dem berühmten "volatile" definieren.

volatile datatyp name;

WinAvr hat die Eigenschaft, für datendefinitionen ganz einfach Register-space zu verwenden. dadurch geht manches recht flott.
ABER: beim interrrupt werden die Register gepusht und dann gepoppt, d.h. was immer die Interrupt routine reinschreibt, ist nachher wieder weg.
Durch "volatile" zwingt man ihn, den Wert im SRAM zu führen, dort hinzuschreiben und zu holen. dadurch funktioniert erst der datenaustausch mit Interrupt-routinen.
Wenn man mich fragt (was aber keiner tut), ist die Bezeichnung nicht ganz glücklich.

palme|kex`
17.05.2005, 10:06
So da bin ich...
Ich bin gerade daran Interrupts zu erlernen und komme auch nach durchlesen des Datenblattes nicht weiter.
Könnt ihr mir eine ganz einfache Lösung zeigen wie ich einen Interrupt verwende (einfach nur lich an lich aus oder ähnliches).

Ich benutzte AT90s8535 und benutzte den Compiler "CodeVisionAVR"

PicNick
17.05.2005, 10:24
Tut mir leid, zum Codevision kann ich im Detail nix sagen.
Im Prinzip läuft das Ganze aber immer gleich

du definierst beim WinAvr z.B,


volatile char bByte = 0;

SIGNAL(SIG_xxxxxxx)
{
bByte |= 1;
}

main()
{
// definieren speziellen Interrupt & enablen

sei(); / Alle Interrupts enablen

while (1)
{
if ( bByte & 1) // warten auf interrupt
{
bByte &= ~1; // zurücksetzen
// mach irgendwas
}
}
}


Das ist nur ein Strickmuster, aber so läuft's im Prinzip

dark emporer
17.05.2005, 15:14
#include <avr/signal.h>
#include <avr/interrupt.h>

#include <stdio.h>
#include <avr/io.h>


volatile char bByte = 0;

SIGNAL(SIG_INTERRUPT0)
{
bByte |= 1;
}

main()
{
DDRA = 0xFF;
DDRD = 0x00;
PORTA=0xF0;
PORTD=0xFF;
// definieren speziellen Interrupt & enablen

sei(); // Alle Interrupts enablen

while (1)
{
if ( bByte & 1) // warten auf interrupt
{
bByte &= ~1; // zurücksetzen
PORTA=~PORTD;
}
}
}


bringt bei mir garnichts habe ich irgendwas vergessen oder falsch gemacht?

PicNick
17.05.2005, 15:32
Da fehlt noch das Enablen vom Interrupt0. Da mußt du nachschauen
ich glaub MCUCSR /GIFR ist zuständig

dark emporer
17.05.2005, 18:19
habe leider nichts passendes gefunden. Villeicht hat das ja schon jemand benutzt?

Pascal
17.05.2005, 19:06
im Register GICR musst du den externen Interrupt0 aktivieren, also in deinem Fall INT0 auf 1 setzen

dann musst du noch im Register MCUCR festlegen, wann der Interrupt ausgelöst werden soll, mit ISC01=0 und ISC00=1 wird der Interrupt bei jedem Wechsel(0V->5V, 5V->0V) der Spannung am Pin für den externen Interrupt ausgelöst

dark emporer
17.05.2005, 19:20
GICR=GICR | 1 << INT0;
MCUCR=MCUCR & ~(1<<ISC01);

ich habe vermutet das du das so meinst ist aber falsch
kannst du das auch in code ausdrücken mit registern habe ich bei avr keine erfahrung



MCUCR = 2; // INT0 interrupt on falling edge
edge = 0; // 0 = falling edge 1 = rising edge stand von vorn herein drinne ist das richtig?

dark emporer
17.05.2005, 19:43
hier mein funktionsfähiger code :-({|=


#include <avr/signal.h>
#include <avr/interrupt.h>

#include <stdio.h>
#include <avr/io.h>


volatile char bByte = 0;

SIGNAL(SIG_INTERRUPT0)
{
bByte |= 1;
}

main()
{
DDRA = 0xFF;
DDRD = 0x00;
PORTA=0xF0;
PORTD=0xFF;
sei(); // Alle Interrupts enablen

// definieren speziellen Interrupt & enablen
MCUCR = 2; //
GICR=0x40;

while (1)
{
if ( bByte & 1) // warten auf interrupt
{
bByte &= ~1; // zurücksetzen
PORTA=~PORTA;
}
}
}

Arexx-Henk
18.05.2005, 20:53
Hallo Dark emporer,

ich hab mahl das AT90s8535.pdf durchgeguckt

um die einzelne INT0 interrupt ein zu schalten braucht mann

GIMSK |= 0x40;

(General Interrupt MaSK register) Seite 25 der .pdf

gruss

Henk