Archiv verlassen und diese Seite im Standarddesign anzeigen : wie benuzt man ein INTERRUPT
dark emporer
16.05.2005, 19:05
bitte nur ein kuzes beispiel um zu testen ob ein interrapt überhaupt funktioniert
pebisoft
16.05.2005, 20:00
dann musst du sagen in was du proggen tust.
mfg pebisoft
dark emporer
16.05.2005, 21:38
volatile sagt mir leider garnichts
dark emporer
16.05.2005, 21: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, 22:02
in c. ich binutze winavr
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, 22: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;
}
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, 07: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
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, 11: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"
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, 16: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?
Da fehlt noch das Enablen vom Interrupt0. Da mußt du nachschauen
ich glaub MCUCSR /GIFR ist zuständig
dark emporer
17.05.2005, 19:19
habe leider nichts passendes gefunden. Villeicht hat das ja schon jemand benutzt?
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, 20: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, 20: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, 21: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
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.