mikrocontroller.net

Forum: Compiler & IDEs Atmega 2561 Interrupt Int4 variable


Autor: Juppo Nini (juppo)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);
.
.
.

Autor: Juppo Nini (juppo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

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

das doppelte ist nur fürs timming

Autor: sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und warum schreibst Du achtmal hintereinander SetPin ??? Einmal reicht 
doch...

Autor: Juppo Nini (juppo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wegen dem timming

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

Autor: sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht ist deine Abfrage zu schnell und Du liest immer nur '1' ein ?

Autor: Juppo Nini (juppo)
Datum:

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

Autor: sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht liegt das Problem in main und der Ausgabe von gewicht_res ?

Autor: Juppo Nini (juppo)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht 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 !

Autor: Juppo Nini (juppo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die ist wie die anderen global


läft auch

die long werte laufen nicht

Autor: Helfer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

// PORTG.7 = Anzeige wann sich das Programm im Interrupt befindet
#define DEBUG_START_INT4()       do { PORTG |= (1<<7); } while (0)
#define DEBUG_ENDE__INT4()       do { PORTG &= ~(1<<7); } while (0)

// PORTG.0 = Anzeige wann das Programm PINE.4 auswertet
#define DEBUG_EVAL_PINE4_START() do { PORTG |= (1<<0); } while (0)
#define DEBUG_EVAL_PINE4_ENDE()  do { PORTG &= ~(1<<0); } while (0)

// PORTG.1 = Anzeige wann das Programm in der for-Schleife ist
#define DEBUG_FOR_START()        do { PORTG |= (1<<1); } while (0)
#define DEBUG_FOR_ENDE()         do { PORTG &= ~(1<<1); } while (0)

// PINE.4 = zu pollendes Disgitalsignal

// Ausgelagert für bessere Übersicht in der Interruptroutine
#define WARTE() do { \
    SETPIN(CLK_AD);  \
    SETPIN(CLK_AD);  \
    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);  \
  } while (0)

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

SIGNAL(SIG_INTERRUPT4)
{
  EIMSK &= ~(1<<INT4);   // INT4 sperren
  DEBUG_START_INT4();
  int4_counter++;  // läuft wunderbar <=== DATENTYP?
  gewicht = 0;
  b_temp = 0;
  for ( unsigned char i = 0; i < 24; i++ )
  {
    unsigned char pine4;
    DEBUG_FOR_START();
    gewicht <<= 1;
    WARTE();
    DEBUG_EVAL_PINE4_START();
    pine4 = PINE & (1<<PE4);
    DEBUG_EVAL_PINE4_ENDE();
    if ( pine4 != 0 ) 
    {
      gewicht |= 1;
      b_temp++;
    }
    DEBUG_FOR_ENDE();
  }
  gewicht_res = gewicht;
  DEBUG_ENDE__INT4();
  EIMSK |= (1<<INT4);   // INT4 freigeben
}

Wie sieht die Hardwareschaltung an PINE.4 aus?

Autor: Helfer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Juppo Nini (juppo)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Helfer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deine SCLK stimmt nicht, wenn man sich die Anforderungen aus dem 
Datenblatt betrachtet.
// Min. 100ns Delay für t_sclk erforderlich
// 1. Ansatz: grobes 1 µs Delay aus der acr-libc
//            Gefahr: 24*2*1µs = 50 µs > t_conv 
//            t_conv typ. 12,5 oder 100ms => Gefahr besteht nicht
#define TSCLK() _delay_us(1)
  
// Ausgelagert für bessere Übersicht in der Interruptroutine
// 
#define SCLK_ERZEUGEN() do { \
    SETPIN(CLK_AD);  \
    TSCLK();         \
    CLRPIN(CLK_AD);  \
    TSCLK();         \
  } while (0)

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;
  }
  gewicht_res = gewicht;
  EIMSK |= (1<<INT4);
}

Autor: Helfer (Gast)
Datum:

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

Autor: Juppo Nini (juppo)
Datum:

Bewertung
0 lesenswert
nicht 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);
}

Autor: Helfer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Helfer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?".

Autor: Helfer (Gast)
Datum:

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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

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

NEIN!

http://www.nongnu.org/avr-libc/user-manual/FAQ.htm...
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.

Autor: Juppo Nini (juppo)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.