Forum: Compiler & IDEs Atmega 2561 Interrupt Int4 variable


von Juppo N. (juppo)


Lesenswert?

Moin an alle

Ich habe problem mit dieser interrupt routine

angeschlossen ist ein ad-wandler
bei gültigen wert (/drdy) springe ich in der int4 interrupt

erzeuge 24 clk und schaue auf den daten pin ob high oder low und 
schreibe das in "gewicht" rein.

als kontrolle setze ich "port G ."

Der Port wird richtig gesetzt ,aber die variable bekommt nur 1 mit.

Mit eine datenanalyser getestet.

habe sonst mit keil gearbeitet und denke das irgendwas mit der syntax 
oder deklarierung nicht stimmt.

Wem gerade dazu was einfällt ..



volatile long gewicht;
volatile unsigned char b_temp,i;
volatile long gewicht_res;





SIGNAL(SIG_INTERRUPT4)
{

  EIMSK &= ~(1<<INT4);   // INT4 sperren
  PORTG=0;
  PORTG=255;
  PORTG=0;
  PORTG=255;
  PORTG=0;
  PORTG=255;
  int4_counter++;  // läuft wunderbar
  gewicht=0;
  b_temp = 0;
  for(i=0;i<24;i++)
  {
    gewicht=gewicht<<1;

    SETPIN(CLK_AD);
    SETPIN(CLK_AD);// zeitverzögerung
    SETPIN(CLK_AD);
    SETPIN(CLK_AD);
    SETPIN(CLK_AD);
    SETPIN(CLK_AD);
    SETPIN(CLK_AD);
    SETPIN(CLK_AD);

    CLRPIN(CLK_AD);
    CLRPIN(CLK_AD);
    CLRPIN(CLK_AD);
    CLRPIN(CLK_AD);
  if(PINE&(1<<PE4))
  {
    gewicht=gewicht|1;  // klappt nicht
          PORTG=255;    // klappt auch wunderbar
    b_temp++;     // klappt auch nicht ergebniss immer 24
    }
  else
  {
    PORTG=0;     // klappt auch wunderbar
  }

  }

  gewicht_res=gewicht;
  EIMSK |= (1<<INT4);   // INT4 freigeben

}

in der main schleife wird gewicht_res ausgegeben.

von sven (Gast)


Lesenswert?

Um 24 Clckimpulse zu generieren solltest Du den Pin abwechselnd ein und 
ausschalten.
Also
SETPIN(CLK_AD);
CLRPIN(CLK_AD);
SETPIN(CLK_AD);
CLRPIN(CLK_AD);
.
.
.

von Juppo N. (juppo)


Lesenswert?

Hallo

dort ist eine schleife for(i=0;i<24,i++)

das doppelte ist nur fürs timming

von sven (Gast)


Lesenswert?

Und warum schreibst Du achtmal hintereinander SetPin ??? Einmal reicht 
doch...

von Juppo N. (juppo)


Lesenswert?

wegen dem timming

jedes SETPIN braucht ein µs ,sonst wird alles zu schnell

von sven (Gast)


Lesenswert?

Vielleicht ist deine Abfrage zu schnell und Du liest immer nur '1' ein ?

von Juppo N. (juppo)


Lesenswert?

nein ,der PORTG wird bei 1 auf 255 und bei 0 auf 0 gesetzt,
angeschlossen habe ich ein logik analysator

von sven (Gast)


Lesenswert?

Vielleicht liegt das Problem in main und der Ausgabe von gewicht_res ?

von Juppo N. (juppo)


Lesenswert?

Hallo

Ich habe jetzt in der interrupt routine nur ein bit gesetzt

alles ander in der main schleife.

das klappt wunderbar.

Variablen in der Interrupt routine werden irgen wie nicht verarbeitet,
Speicher ?

von Klaus F. (kfalser)


Lesenswert?

Juppo Nini schrieb:
> Variablen in der Interrupt routine werden irgen wie nicht verarbeitet,
> Speicher ?

Die Variable i ist in der ISR nicht lokal deklariert !

von Juppo N. (juppo)


Lesenswert?

die ist wie die anderen global


läft auch

die long werte laufen nicht

von Helfer (Gast)


Lesenswert?

Bei der Kontrolle/Anzeige im Hauptprogramm musst du beachten, dass du 
gewicht atomar lesen musst, d.h. mit gesperrtem INT4. Wenn du das 
nicht machst, können dir die Zeilen gewicht = 0; und gewicht <<= 1; 
Fheler vorgaukeln. Näheres siehe Interrupt.

Ansonsten:
> angeschlossen habe ich ein logik analysator

Mehrspurig?

Bei 1-4 Spuren würde mich ein LA-Diagramm von dem folgenden Code 
interessieren.

Je nach Speicherkapazität deines LA triggern auf PORTG.7 (viel 
Speicher), PORTG.1 (weniger Speicher) oder PORTG.0 (ganz wenig Speicher) 
und dabei PINE.4 messen.

Kannst du das aufnehmen?

1
// PORTG.7 = Anzeige wann sich das Programm im Interrupt befindet
2
#define DEBUG_START_INT4()       do { PORTG |= (1<<7); } while (0)
3
#define DEBUG_ENDE__INT4()       do { PORTG &= ~(1<<7); } while (0)
4
5
// PORTG.0 = Anzeige wann das Programm PINE.4 auswertet
6
#define DEBUG_EVAL_PINE4_START() do { PORTG |= (1<<0); } while (0)
7
#define DEBUG_EVAL_PINE4_ENDE()  do { PORTG &= ~(1<<0); } while (0)
8
9
// PORTG.1 = Anzeige wann das Programm in der for-Schleife ist
10
#define DEBUG_FOR_START()        do { PORTG |= (1<<1); } while (0)
11
#define DEBUG_FOR_ENDE()         do { PORTG &= ~(1<<1); } while (0)
12
13
// PINE.4 = zu pollendes Disgitalsignal
14
15
// Ausgelagert für bessere Übersicht in der Interruptroutine
16
#define WARTE() do { \
17
    SETPIN(CLK_AD);  \
18
    SETPIN(CLK_AD);  \
19
    SETPIN(CLK_AD);  \
20
    SETPIN(CLK_AD);  \
21
    SETPIN(CLK_AD);  \
22
    SETPIN(CLK_AD);  \
23
    SETPIN(CLK_AD);  \
24
    SETPIN(CLK_AD);  \
25
    CLRPIN(CLK_AD);  \
26
    CLRPIN(CLK_AD);  \
27
    CLRPIN(CLK_AD);  \
28
    CLRPIN(CLK_AD);  \
29
  } while (0)
30
31
volatile long gewicht;
32
volatile long gewicht_res;
33
volatile unsigned char b_temp;
34
35
SIGNAL(SIG_INTERRUPT4)
36
{
37
  EIMSK &= ~(1<<INT4);   // INT4 sperren
38
  DEBUG_START_INT4();
39
  int4_counter++;  // läuft wunderbar <=== DATENTYP?
40
  gewicht = 0;
41
  b_temp = 0;
42
  for ( unsigned char i = 0; i < 24; i++ )
43
  {
44
    unsigned char pine4;
45
    DEBUG_FOR_START();
46
    gewicht <<= 1;
47
    WARTE();
48
    DEBUG_EVAL_PINE4_START();
49
    pine4 = PINE & (1<<PE4);
50
    DEBUG_EVAL_PINE4_ENDE();
51
    if ( pine4 != 0 ) 
52
    {
53
      gewicht |= 1;
54
      b_temp++;
55
    }
56
    DEBUG_FOR_ENDE();
57
  }
58
  gewicht_res = gewicht;
59
  DEBUG_ENDE__INT4();
60
  EIMSK |= (1<<INT4);   // INT4 freigeben
61
}

Wie sieht die Hardwareschaltung an PINE.4 aus?

von Helfer (Gast)


Lesenswert?

Der Anmerkung von Sven sollte man unbedingt nach gehen. Dazu müsste man 
auch die Definitionen von SETPIN und CLRPIN sehen.

> angeschlossen ist ein ad-wandler

Ist ein Datenblatt oder Link zum Datenblatt bekannt?

von Juppo N. (juppo)


Lesenswert?

Mehrspurig gemessen habe ich ,wie geschrieben wird der Port gesetzt oder 
halt nicht.


Interuppt sperren und öffnen mache ich

EIMSK &= ~(1<<INT4);   // INT4 sperren

EIMSK |= (1<<INT4);   // INT4 freigeben


Angeschlossen ist ein ADS1231

Die Datenleitung gibt ein /DRDY Signal aus
Anschliesend müssen 24 Clock angelegt werden und der gleiche

Port PORT E pin 4 bringt die daten.


also:
interrupt INT4 (Port E,4) wartet auf fallende Flanke
dann interrupt sperren
dann (for to do ) 24 Clock anlegen(zum AD1231) und den PORT E 4 in long 
variable einlesen
interuppt 4 freigeben



jetzt habe ich:
 in der Interuppt routine int4 wird ein bit gesetzt
dann funktion mit dem clock anlegen und daten lesen
und int 4 variable zurücksetzen

das klappt wunderbar.


wenn ich aber die einlese funktion direkt in der interrupt routine mache
sind die daten wieder falsch.

Wie schon geschrieben habe ich ein ATMEGA 2561 mit AVR Studio



wie muss die long variable deklariert sein und wo?
wie geschrieben wird bei der if PE4 gesetzt ein HardwarePort G gesetzt 
und ist auch mit dem Logikanalyser zu sehen.




gruß juppo

von Helfer (Gast)


Lesenswert?

Deine SCLK stimmt nicht, wenn man sich die Anforderungen aus dem 
Datenblatt betrachtet.
1
// Min. 100ns Delay für t_sclk erforderlich
2
// 1. Ansatz: grobes 1 µs Delay aus der acr-libc
3
//            Gefahr: 24*2*1µs = 50 µs > t_conv 
4
//            t_conv typ. 12,5 oder 100ms => Gefahr besteht nicht
5
#define TSCLK() _delay_us(1)
6
  
7
// Ausgelagert für bessere Übersicht in der Interruptroutine
8
// 
9
#define SCLK_ERZEUGEN() do { \
10
    SETPIN(CLK_AD);  \
11
    TSCLK();         \
12
    CLRPIN(CLK_AD);  \
13
    TSCLK();         \
14
  } while (0)
15
16
volatile long gewicht;
17
volatile long gewicht_res;
18
19
SIGNAL(SIG_INTERRUPT4)
20
{
21
  EIMSK &= ~(1<<INT4);
22
  gewicht = 0;
23
  for ( unsigned char bit = 0; bit < 24; bit++ )
24
  {
25
    gewicht <<= 1; // MSB first
26
    SCLK_ERZEUGEN();
27
    if ( PINE & (1<<PE4) ) gewicht |= 1;
28
  }
29
  gewicht_res = gewicht;
30
  EIMSK |= (1<<INT4);
31
}

von Helfer (Gast)


Lesenswert?

Wie triggert dein INT4? Ich würde auf fallende Flanke von /DRDY auslösen 
lassen.

von Juppo N. (juppo)


Lesenswert?

Hallo

Mit dem CLK habe ich rumgespielt bis zur vergasung

Bei der
 if ( PINE & (1<<PE4) ) gewicht |= 1;

werden nur 1 reingeschrieben.
aber PORT setzen klappt wunderbar


IST DAS RICHTIG

volatile long gewicht;
volatile long gewicht_res;






SIGNAL(SIG_INTERRUPT4)
{
  EIMSK &= ~(1<<INT4);
  gewicht = 0;
  for ( unsigned char bit = 0; bit < 24; bit++ )
  {
    gewicht <<= 1; // MSB first
    SCLK_ERZEUGEN();
    if ( PINE & (1<<PE4) ) gewicht |= 1;  Hier werden nur 1 
reingeschrieben.
  }
  gewicht_res = gewicht;
  EIMSK |= (1<<INT4);
}

von Helfer (Gast)


Lesenswert?

>   EIMSK |= (1<<INT4); // INT4 wieder enablen

Da würde ich vorher zur Sicherheit das Interruptflag löschen. Oder - um 
die Sache genauer zu untersuchen - eine Debugmöglichkeit einbauen, die 
zeigt, ob das Flag wider den gewollten Programmablauf gesetzt ist.

von Helfer (Gast)


Lesenswert?

> if ( PINE & (1<<PE4) ) gewicht |= 1;  Hier werden nur 1 reingeschrieben.

Das niederwertigste Bit wird auf 1 gesetzt, wenn ein 1 Bit am PINE.4 
anliegt. Da zuvor gewicht mit gewicht <<= 1; um eine Stelle nach links 
geschoben wurde steht eine 0 an der Bitposition und die bleibt auch für 
diese Bitleserunde dort, wenn an PINE.4 ein 0 Bit anliegt.

Du hast doch mit dem LA ein super Debugtool... Kann dein LA keine 
Diagramme speichern? Wenn doch: Zeig doch mal welche /DRDY Leitung 
PINE.4 Leitung und SCLK/CLK_AD Leitung. Das Diagramm kann man dann mit 
dem Diagramm im Datenblatt vergleichen. Und mit dem LA umgehst du die 
noch unbeantwortete Falle "Wie verlässlich ist die Anzeige der Variablen 
gewicht?".

von Helfer (Gast)


Lesenswert?

> Da würde ich vorher zur Sicherheit das Interruptflag löschen.
1
  EIFR |= (1<<INTF4); // INTF4 löschen durch Schreiben einer 1 
2
  EIMSK |= (1<<INT4); // INT4 wieder enablen

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Helfer schrieb:
>> Da würde ich vorher zur Sicherheit das Interruptflag löschen.
>
>
1
>   EIFR |= (1<<INTF4); // INTF4 löschen durch Schreiben einer 1
2
>

NEIN!

http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_intbits
1
EIFR = (1<<INTF4);

Selbst, falls es hier egal sein sollte (keine weiteren Interruptflags
können gesetzt sein in EIFR), bitte nicht erst falsch angewöhnen.

von Juppo N. (juppo)


Lesenswert?

Klappt auch nicht.

Besten Dank für eure Hilfe .
Ich komme erst mal klar ,eventuell in einem biergarten und schweinzhaxen 
fällt uns was ein.
Gruß juppo

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.