www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Unverständliches Verhalten von struct-Variablen bei Interrupt


Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Morgen zusammen!

Ich habe ein Problem mit einer Variablen meines structs.

Hier erstmal das struct:
struct  // Struct contains information used for communication with EEPROM
{
  uint16_t address;     // Address to be read or written
  uint8_t  byte [8];    // Byte 1 to 8 for complete page write
  uint8_t  bytecount;   // Number of bytes to read or written
  uint8_t  nextbyte;    // Next byte to be transmitted
  uint8_t  eeprom_nr;   // Selects between different EEPROMs
} eeprom;

Und hier die Interrupt-Routine:
#pragma vector = USCIAB0TX_VECTOR
__interrupt void usciab0vector (void)
{  
  if (IFG2 & UCB0TXIFG) // Byte successfully read from USCB0-TX-Buffer
  {
    
    if (eeprom.bytecount != 1) // More than one byte
    {
      eeprom.nextbyte += 1;
      if (eeprom.nextbyte < eeprom.bytecount)
      {
        UCB0TXBUF = eeprom.byte[eeprom.nextbyte];
      }
      else
      {
        eeprom.nextbyte = 0;
        EE1_WP;  // Write protect enabled
        EE1_DES; // Deselect EEPROM
      }
    }
    
  } // End if (IFG2 & UCB0TXIFG)  
}

Und zwar möchte ich damit mein EEPROM Interrupt-gesteuert beschreiben. 
In der Interrupt-Routine soll jedesmal automatisch das nächste Byte 
geladen werden. Insgesamt halt 8 Bytes für einen Page-Write.

Mein Problem: Jedesmal, wenn die ISR aufgerufen wird, also jedesmal, 
wenn der uC das Byte aus dem Sendepuffer entfernt hat und bereit für das 
nächste ist, ist meine Variable
eeprom.nextbyte

wieder 0! Somit wird natürlich jedesmal dasselbe Byte verschickt. 
Während die ISR abgearbeitet wird, wird die Variable erhöht, aber sie 
ist nächstes mal nciht mehr da.

Das struct ist global deklariert, wenn ich es zusätzlich als volatile 
deklariere, oder seine Kompnenten, dann gibts ne Warnung.


Hat jemand nen Tip?

Autor: Mandrake (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Überleg nochmal, ob dein 2. if in deiner ISR wirklich die Bedingung 
prüft, die du willst. Das Kommentar dahinter sagt nämlich was 
anderes....

Dann müsste es heißen:
if (eeprom.bytecount > 1)

Gruß

Mandrake

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wie so oft fehlt volatile.

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, dann noch der Code dazu:
void eeprom_write (void) // ONSemi CAT25256 256kB SPI
{
  EE1_WE; // Enable writing
  EE1_SEL; // Select EEPROM 1
  
  
  eeprom.bytecount = 5; 
  UCB0TXBUF = eeprom.byte[0];
}

in
byte.count
 lege ich hier fest, dass es 5 Bytes sind, die übertragen werden sollen.

Dann wird das erste in den TX-Buffer geschrieben und nach erfolgreichem 
Lesen aus dem TX-Buffer wird die ISR aufgeruen und das zweite Byte soll 
gesendet werden.
if (eeprom.bytecount != 1) // More than one byte
    {
      eeprom.nextbyte += 1;
      if (eeprom.nextbyte < eeprom.bytecount)
      {
        UCB0TXBUF = eeprom.byte[eeprom.nextbyte];
      }
      else
      {
        eeprom.nextbyte = 0;
        EE1_WP;  // Write protect enabled
        EE1_DES; // Deselect EEPROM
      }
    }

Die if-Anweisung stellt nur sicher, dass wenn nur ein Byte zum 
Übertragen war, kein neuer Wert in den Puffer geschrieben wird und somit 
auch kein neuer Interrupt vom USCI-Modul kommt.

Also ab zwei Bytes ght das Programm in die Anweisung rein und soll nun 
den
eeprom.nextbyte
 um 1 erhöhen, wodurch aus dem Array das Byte 1 (also das Zweite 
gesendet werden soll. Das funktioniert auch, Der TX-Buffer bekommt
byte[1]
.

Nächste if-Anweisung ist auch wahr, da 1 < 5 und der TX-Buffer wird 
neugeladen. So, bei der nächsten ISR ist
eeprom.nextbyte
 jedoch nicht mehr 1, sondern wieder 0 und ab da drehts sich natürlich 
rum und rum...

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mandrake schrieb:
> Dann müsste es heißen:
> if (eeprom.bytecount > 1)

Ja, OK, das stimmt, hat den selben Effekt, schließt nur auch noch die 0 
mit ein, obgleich ich den Sendebefehl natürlich nicht aufrufe, wenn 
nichts zum Senden da ist.

A. K. schrieb:
> Und wie so oft fehlt volatile.

Nein, das fehlt nicht, habe es jetzt in verschiedenen Varianten 
ausprobiert, habe erst das gesamte struct als volatile deklariert, gibts 
ne Warnung mit undefined behaviour. Erstmal ignoriert -> selbes Ergebnis

Dann habe ich die einzelnen Komponenten im struct als volatile 
deklariert, selbe Warnung -> selbes Ergebnis

Dann mal nur die betroffene Variable als volatile -> keine Warnung, aber 
selbes Ergebnis

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat da niemand nen Tip für mich?

Ist ja nicht Controller bezogen, ist ja mehr generell irgendein Fehler 
in meinem C Quelltext.


Ich ste grad echt aufm Schlauch, probiere hier um, aber kriegs nicht 
hin.

Autor: Frank Schrader (herrschrader)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da hilft nur Reduktion.
Schmeiss mal alles aus dem Programm raus, was nicht unbedingt für das 
EEProm schreiben nötig ist und stell dann das komplette Teil mal hier 
rein.

Ich vermute mal, du überschreibst dir irgendwo ganz anders die Variable 
bytecount.

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In meinem Quelltext ist schon fast nichts mehr drin :)
#include "msp430x24x.h"
#include "stdint.h"

// #############################################################################
// # EEPROM Definitions #                                                      #
// ######################                                                      #
#define EE1_SEL (P3OUT &= ~0x01) // Chip selected EEPROM 1 °CS 'low'           #
#define EE1_DES (P3OUT |= 0x01)  // Chip deselected EEPROM 1 °CS 'high'        #
#define EE1_WP  (P2OUT &= ~0x80) // EEPROM 1 writing protected °WP 'low'       #
#define EE1_WE  (P2OUT |= 0x80)  // EEPROM 1 writing enabled °WP 'high'        #
#define EE1_HLD (P2OUT &= ~0x40) // EEPROM 1 holded °HOLD 'low'                #
#define EE1_ACT (P2OUT |= 0x40)  // EEPROM 1 not holded °HOLD 'high'           #
// #############################################################################


#define TRUE 1
#define FALSE 0

void eeprom_write (void);


struct  // Struct contains information used for communication with EEPROM
{
  uint16_t address;     // Address to be read or written
  uint8_t  byte [8];    // Byte 0 to 7 for complete page write
  uint8_t  bytecount;   // Number of bytes to be read or written
  uint8_t  nextbyte;    // Next byte to be transmitted
  uint8_t  eeprom_nr;   // Selects between different EEPROMs
}eeprom;


void  main (void)
{
  WDTCTL = WDTPW + WDTHOLD;

  // Initialisierung der Taktquelle - Quarz 1,8432 MHz
  
  // BCSCTL1: BASIC CLOCK SYSTEM CONTROL REGISTER 1
  // XT2OFF:  XT2 Oscillator (Bit geloescht: XT2 ist an)
  BCSCTL1 &= ~XT2OFF;
  
  // BCSCTL3: BASIC CLOCK SYSTEM CONTROL REGISTER 3
  // XT2Sx:   XT2 Range Select (hier SELM_1: 1-3 MHz)
  // XCAPx:   Oscillator Capacitor Selection (hier: ~12,5pF)
  BCSCTL3 = XT2S_1 + XCAP_3;
  
  do
  {
    IFG1 &= ~ OFIFG;                   // Oszillator-Fault IF loeschen
    for (unsigned int i = 0xFF; i > 0; i--)     // Zeit zum Einschwingen
    {}                                 // Schleife
  } while (IFG1 & OFIFG);              // Ausfuehren solange Oszillator-Fault da
  
  // BCSCTL2: BASIC CLOCK SYSTEM CONTROL REGISTER 2
  // SELMx:   Select MCLK (hier SELM_2: XT2CLK)
  // SELS:    Select SMCLK (Bit gesetzt: XT2CLK)
  BCSCTL2 = SELM_2 + SELS;
  
  
  // ******************** USCI B0 Konfiguration: SPI Modus ***********************
  
  // USCI B0 CONTROL REGISTER 0
  // UCCKPH   : Daten werden bei erster Flanke uebernommen, bei zweiter geaendert
  // UCMSB    : MSB wird als erstes gesendet
  // UCMST    : Mikrocontroller ist Master
  // UCSYNC   : Synchroner Modus
  UCB0CTL0 = UCCKPH + UCMSB + UCMST + UCSYNC;
  
  // USCI B0 CONTROL REGISTER 1
  // UCSSEL_2 : USCI Taktquelle ist SMCLK
  // UCSWRST  : USCI Modul ist im Reset-Modus
  UCB0CTL1 = UCSSEL_2 + UCSWRST;
  
  // USCI B0 BIT RATE CONTROL REGISTER
  // UCA1BR0  : Low-Byte vom Prescaler
  // UCA1BR1  : High-Byte vom Prescaler
  UCB0BR0 = 0x00;
  UCB0BR1 = 0x00;
  
  // USCI B0 STATUS REGISTER
  // UCBUSY   : Status-Bit zeigt an, ob momentan eine Uebertragung laeuft
  UCB0STAT = UCBUSY;
  
  UCB0CTL1 &= ~UCSWRST;                               // Software-Reset loeschen -> USCI B0 aktiv
  
  // USCI A0/B0 INTERRUPT ENABLE REGISTER
  // UCB0TXIE : Interrupt fuer erfolgreiches Laden aus dem Sendepuffer
  // UCB0RXIE : Interrupt fuer erfolgreich empfangenes Zeichen
  IE2 = UCB0TXIE + UCB0RXIE;
  
  IFG2 &= ~(UCB0TXIFG + UCB0RXIFG);

// ************************Ende Konfiguration USCI B0***************************
  
  
  P3SEL |= 0x0E; // P3.1,2,3 Special Function
  P3DIR |= 0x0F; // P3.0,1,2,3 Output Direction
  
  
  
  
  _BIS_SR (GIE);
  
  eeprom.byte[0] = 0xAA;
  eeprom.byte[1] = 0x5B;
  eeprom.byte[2] = 0x4C;
  eeprom.byte[3] = 0xCC;
  eeprom.byte[4] = 0xFB;
  
  eeprom_write ();
  
  while (1)
  {
    
  }
  
} // Ende main


void eeprom_write (void) // ONSemi CAT25256 256kB SPI
{
  EE1_WE; // Enable writing
  EE1_SEL; // Select EEPROM 1
  
  
  eeprom.bytecount = 5;
  eeprom.nextbyte = 0;
  UCB0TXBUF = eeprom.byte[0];
}


#pragma vector = USCIAB0TX_VECTOR
__interrupt void usciab0vector (void)
{  
  if (IFG2 & UCB0TXIFG) // Byte successfully read from USCB0-TX-Buffer
  {
    
    if (eeprom.bytecount > 1) // More than one byte
    {
      eeprom.nextbyte += 1;
      if (eeprom.nextbyte < eeprom.bytecount)
      {
        UCB0TXBUF = eeprom.byte[eeprom.nextbyte];
      }
      else
      {
        eeprom.nextbyte = 0;
        EE1_WP;
        EE1_DES;
      }
    }
    
  } // End if (IFG2 & UCB0TXIFG)  
}

Wie gesagt, sämtliche volatile-Varianten habe ich schon durchprobiert. 
Immer dasselbe

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wie äussert sich darin der Fehler?

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> eeprom.nextbyte += 1;

Der Fehler liegt darin, dass
eeprom.nextbyte += 1;

nicht übernommen wird, sondern beim nächsten Aufruf von der ISR, es 
wieder "0" ist und sich ab da eine nicht endende Schleife bildet.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Woran siehst du das? Weil immer das gleiche Byte versendet wird? Das 
könnte auch ein permanenter Restart bewirken.

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha schrieb:
> UCB0CTL0 = UCCKPH + UCMSB + UCMST + UCSYNC;

Ich habe in diesem Fall keine Ahnung, aber das sieht für mich komisch 
aus (repräsentativ für ähnliche Konstrukte).

Das soll doch hoffentlich kein Zusammensetzen eines Steuerbytes sein.
Ich kenne das eher als
UCB0CTL0 = UCCKPH | UCMSB | UCMST | UCSYNC

Es kann natürlich in diesem Fall anders sein.
Wenn ja, bitte erklären. Ich lerne gerne neues dazu.

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moment, ich hab jetzt erstmal Feierabend, melde mich gleich von zuhause 
zurück.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was genau wird wiederholt?
Nur ein Zeichen oder die ganze Sequenz?


Ich würde mir auf jeden Fall hier
    if (eeprom.bytecount > 0) // More than one byte
    {
      eeprom.nextbyte += 1;
      if (eeprom.nextbyte < eeprom.bytecount)
      {
        UCB0TXBUF = eeprom.byte[eeprom.nextbyte];
      }
      else
      {
        eeprom.nextbyte = 0;
        eeprom.bytecount = 0;
        EE1_WP;
        EE1_DES;
      }

den Bytecount auch noch auf 0 setzen (und auch auf größer 0 testen). 
Denn genau das ist ja passiert: Es sind keine Daten mehr zu versenden.
So wie du das hast, darf die UART keine Zeichen für sich puffern. Sobald 
die UART selbt noch ein Zeichen zwischenspeichert, geht dein Mechanismus 
schief, weil du nach dem Erkennen des Endes (und nicht mehr Einstellen 
eines Bytes) noch einen Interrupt kriegst.

Mit deinem Meschanismus, so wie er jetzt ist, hast du keine Möglichkeit 
anhand der Variableninhalte festzustellen, ob du überhaupt noch etwas zu 
versenden hast. nextbyte auf 0 zu setzen reicht nicht. Du kannst dann 
die Fälle "Senden hat gerade erst begonnen" nicht vom Fall "Senden ist 
beendet" unterscheiden.

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe im Debugger einen Break hinter
eeprom.nextbyte += 1;
...also jede Runde, wo die ISR aufgerufen wird, komme ich da an. Und da 
ist jedesmal halt die Variable wieder auf 0. Die ersten zwei Bytes 
werden gesendet, danach nurnoch das zweite immer wieder in Folge, weil 
diese Variable immer wieder "0" ist.

Byte eins wird ja noch aus der main() gesendet, bzw. aus der 
eeprom_write() und ab da wird das nächste Byte ja in jeder ISR 
verschickt, sollte zumindest, beim zweiten klappt das ja auch noch, weil 
da dann byte[1] verschickt wird, ab da dann halt immer byte[1]

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Sobald
> die UART selbt noch ein Zeichen zwischenspeichert, geht dein Mechanismus
> schief, weil du nach dem Erkennen des Endes (und nicht mehr Einstellen
> eines Bytes) noch einen Interrupt kriegst.

Ich bekomme noch einen Interrupt, klar, aber der geht ja mit
if (eeprom.bytecount > 1)
 ins leere, weil ich den ja nach dem letzten Byte auf "0" gesetzt habe.

Der USART speichert ein Byte zwischen klar, aber er ruft die ISR ja auf, 
wenn er bereit für ein neues Zeichen ist, das bekommt er dann, bzw. soll 
es sich selber nehmen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha schrieb:

> Ich bekomme noch einen Interrupt, klar, aber der geht ja mit
>
if (eeprom.bytecount > 1)
> ins leere, weil ich den ja nach dem letzten
> Byte auf "0" gesetzt habe.

Wo genau hast du das in deinem Code gemacht?

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der UART generiert ja immer ein Interrupt, wenn er seinen Puffer frei, 
das vorige Byte jetzt versenden wird und für einen nahtlosen Datenstrom 
schonmal das nächste im Puffer haben will.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha schrieb:
> Ich habe im Debugger einen Break hinter
>
eeprom.nextbyte += 1;
> ...also jede Runde, wo die ISR aufgerufen wird, komme ich da an.

Ist dein Optimizer eingeschaltet?
Wenn ja, dann kannst du der Anzeige des Debuggers nicht unbedingt 
trauen.

Hats du die Variante
struct  // Struct contains information used for communication with EEPROM
{
  volatile uint16_t address;     // Address to be read or written
  volatile uint8_t  byte [8];    // Byte 0 to 7 for complete page write
  volatile uint8_t  bytecount;   // Number of bytes to be read or written
  volatile uint8_t  nextbyte;    // Next byte to be transmitted
  volatile uint8_t  eeprom_nr;   // Selects between different EEPROMs
}eeprom;

schon probiert?

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, ich habe alles durch! Habe auch schon die Variable aus dem struct 
genommen und sie einzeln deklariert - keine Änderung. Aber ich sehe es 
auf dem Oszi ja auch, die beiden ersten Bytes gehen, danach nurnoch das 
Zweite fortlaufend. Wenn er in den Reset gehen würde, dann müsste ja 
erstmal wieder das Erste kommen.

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian H. schrieb:
> Das soll doch hoffentlich kein Zusammensetzen eines Steuerbytes sein.
> Ich kenne das eher als UCB0CTL0 = UCCKPH | UCMSB | UCMST | UCSYNC

Doch genau das ist es und auch völlig OK.

Das wird in den Code-Examples auch so gemacht.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha schrieb:
> Christian H. schrieb:
>> Das soll doch hoffentlich kein Zusammensetzen eines Steuerbytes sein.
>> Ich kenne das eher als UCB0CTL0 = UCCKPH | UCMSB | UCMST | UCSYNC
>
> Doch genau das ist es und auch völlig OK.

UCCKPH und Konsorten sind offenbar irgendwelche Konstante, in denen die 
richtigen Bits gesetzt sind. Solange es keine Bitüberschneidungen bei 
einzelnen Konstanten gibt, ist das ok

  0x01 + 0x02  -> 0x03
  0x01 | 0x02  -> 0x03

Aber
  0x01 | 0x03  -> 0x03
  0x01 + 0x03  -> 0x04

> Das wird in den Code-Examples auch so gemacht.

Das ist kein guter Grund.

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß schon, was du meinst, aber ich kann auch:

P1OUT &= ~(LED1 + LED2);

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber das hab ich mich auch schon gefragt, jedoch ist es in jedem 
Code-Example von TI so gehalten. Weiß nicht, ob es speziell im Header 
des uCs  definiert ist, oder im IAR.

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier mal ein Ausschnitt:
//******************************************************************************
//  MSP430x26x Demo - USCI_B0 to USCI_B1 I2C RX and TX single bytes
//
//  Description: This demo connects both USCI_B channels on one MSP430 via the 
//  I2C bus. The master (B0) reads from the slave(B1), then the slave (B1) reads
//  from the master (B0). 
//  ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = ~1.045MHz
//
//                                /|\              /|\
//               MSP430F261x      10k              10k     
//             -----------------   |                |
//           -|XIN  P5.1/UCB0SDA|<-|---+----|       |
//            |                 |           |       |
//           -|XOUT             |           |       |
//            |     P5.2/UCB0SCL|<-+------- | ------|
//            |                 |           |       |
//            |     P3.1/UCB0SDA|<----------|       |
//            |                 |                   |
//            |                 |                   |
//            |     P3.2/UCB0SCL|<------------------|
//            |                 |        
//
//  R. B. Elliott / H. Grewal
//  Texas Instruments Inc.
//  January 2008
//  Built with IAR Embedded Workbench Version: 3.42A
//******************************************************************************
#include "msp430x26x.h"

....
....
void SlaveUSCIB1TX (void){
  
  UC1IE &= ~UCB1RXIE;                       // Disable RX interrupt
  UCB1CTL1 |= UCSWRST;                      // Enable SW reset 
  UCB1CTL0 = UCMODE_3 + UCSYNC;             // I2C Slave, synchronous mode
  UCB1I2COA = 0x48;                         // Own Address is 048h
  UCB1CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
  Slave_RX = 0;
  UCB1I2CIE  |= UCSTPIE + UCSTTIE;          // Enable STT and STP interrupt
  UC1IE |= UCB1TXIE;                        // Enable TX interrupt
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha schrieb:
> Ich weiß schon, was du meinst,

Offenbar nicht.

Das das in den TI Beispielen auch so gemacht wird, ist kein guter Grund.

Ein guter Grund wäre, dass man in den Header Files die entsprechenden 
#define rausgesucht hat und verifiziert hat, dass es zu keinen 
Überschneidungen kommt.

Nur weil andere etwas so machen, ist das noch lange kein Grund es auch 
so zu machen. Vor allen Dingen, wenn es bei

    FLAG1 + FLAG2

eine Fehlermöglichkeit existiert, die bei

    FLAG1 | FLAG2

nicht existiert.
Wenn beide Versionen im Nicht-Fehler Fall das gleiche Ergebnis liefern, 
im Fehlerfall die eine aber immer noch ein richtiges Ergebnis liefert 
und die andere nicht, dann nehm ich zumindest lieber die Version, die 
auch dann noch funktioniert.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha schrieb:
> Ich weiß schon, was du meinst, aber ich kann auch:
>
> P1OUT &= ~(LED1 + LED2);

Und wenn du dich vertust und schreibst
P1OUT &= ~(LED1 + LED2 + LED1);
dann liefert diese Version etwas nicht Beabsichtigtes, während

P1OUT &= ~(LED1 | LED2 | LED1);

immer noch das Beabsichtigte macht. LED1 wird halt quasi '2 mal 
abgeschaltet'. Macht aber nichts. Abgeschaltet ist abgeschaltet und mehr 
als abgeschaltet kann die LED nicht sein.

Nennt sich 'defensives programmieren'. Man rechnet als Programmierer 
damit, dass man selbst Fehler macht und gestaltet seinen Code so, dass 
der Code einige der Programmierfehler von alleine abfangen kann und sie 
sich nicht auswirken.


Aber das ist jetzt nicht unbedingt der springende Punkt.
Deine Interrupt Steuerung ist das Problem.

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, sehe ich vollkommen ein, es funktioniert auch mit OR. Dann werde ich 
das ab jetzt benutzen, Wir haben in der Fachhochschule das Thema 
Mikrocontroller nur sehr kurz angeschnitten und mussten uns eigentlich 
alles anhand der Examples von TI beibringen. Da hat sich das irgendwie 
so festgesetzt.

Aber Recht hast du natürlich!

Trotzdem haben alles diese Einstellungen leider keinen Bezug auf die ISR 
:) Der Hund liegt woanders begraben. Nur kann ich ihn nicht 
ausbuddeln...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hier
Beitrag "Re: Unverständliches Verhalten von struct-Variablen bei Interrupt"
ist dein kompletter Code?

Dann deaktiviere mal den Interrupt für 'Zeichen empfangen'. Du hast 
keinen Handler dafür. Wer weiß was passiert, wenn dieser Interrupt 
anspricht.

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> ist dein kompletter Code?

Ja ist er. Mit dem IR-Handler für RXIFG ist vielleicht ein Punkt mit dem 
du Recht haben könntest. Das werde ich mal ausprobieren. Leider erst 
morgen, hab das nebenbei bei der Arbeit geschrieben (in der Pause 
natürlich :))

Ich werde das Ergebnis berichten!

Danke schonmal!

Autor: Frank Schrader (herrschrader)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn soviele Leute den Code ankucken und keine Fehler finden, gibt es 
noch die Möglichkeit eines Compiler-Fehlers, d.h. der Compiler generiert 
falschen Code. Ist zwar sehr selten, kommt aber vor.

Wenn möglich schau dir mal in einem Listing den generierten 
Assembler-Code an, ob der Sinn macht.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kenne mich mit Deiner CPU nicht aus.

Aber wenn Du was mit nem Interrupt machst, dann solltest Du erst den 
Interrupt sperren, die Struct mit gültigen Daten füllen und als letztes 
den Interrupt wieder freigeben.

D.h. der Interupt darf nicht mit ner halb vollen Struct schon irgendnen 
Mumpitz machen dürfen.



Wenn Du denkst, daß der Interrupt die Struct zerstört, dann gib mal die 
komplette Struct vor und nach dem Interrupt aus:

- Interrupts global sperren
- warten bis Interruptflag gesetzt
- Struct ausgeben
- Interrupts global freigeben
- NOP (Interrupt ausführen)
- Interrupts global sperren
- Struct ausgeben
usw.


Peter

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten morgen zusammen,

so, neues Spiel, neues Glück - ES LÄUFT!

Karl-Heinz hat den ehler gefunden. Es lag tatsächlich daran, dass mein 
RXIFG freigeschlatet war und ich keinen Handler dafür definiert hatte. 
Jetzt wird alles wie gwünscht hochgezählt.

Vielen Dank an alle!

Eine letzte Frage noch: Wie schon erwähnt, gibt der Compiler mir bei 
einer kompletten volatile-Deklaration des structs eine Warnung mit 
"undefined behaviour" aus - soweit ich das verstehe, liegt es daran, 
dass er zwei volatile-Variablen miteinander vergleicht, und zwar in der 
Zeile
if (eeprom.nextbyte < eeprom.bytecount)

Ist das schlimm, bzw. wie werde ich diese Warnung noch los?

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha schrieb:
> Ist das schlimm, bzw. wie werde ich diese Warnung noch los?
Leg die beiden Werte vor dem Vergleich in eine lokale Variable.

Das ist sowieso anzuraten da der Compiler bei jedem Zugriff alles neu 
aus derm Speicher holen muß.
DU könntest also erstmal eeprom.nextbyte und eeprom.bytecount am Anfang 
lokal holen, und am ende in den Strukt zurückschreiben.

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.