mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik [MSP430] Variablenuebergabe an ISR


Autor: Bernd Krause (berndk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe folgendes Problem: In der TimerISR-A wird in Abhaengigkeit 
eines Zaehlers eine LED eingeschaltet.
n_led=0 keine, n_led=1 P1.7, n_led=2 P1.6, n_led=3 P1.5
In der TimerISR- B wird nun der ADC aktiviert und 8-mal abgetastet, ist 
das erledigt, wird die LED abgeschaltet und das ganze geht von vorne 
los.

Ich weiss jedoch einfach nicht, weshalb die Variable n_led in der 
ADC_ISR mit der aus den TimerISRs nicht uebereinstimmt. Reduziere ich in 
der TimerA-ISR die Anzahl auf der n_led Elemente auf 3 durch entfernen 
der Messung ohne LED, funzt alles wunderbar. Weshalb wird die Variable 
n_led nicht korrekt an die ADC_ISR weitergegeben?

Vielen Dank
void timera_isr()

{  
  
   if(n_led == 0)
  { 
  P1OUT = 0x00;
  }
    if(n_led == 1)
   {
   P1OUT |= 0x80;      //P1.7 einschalten   
   }
    if(n_led == 2)
   {
   P1OUT |= 0x40;    //P1.6 einschalten 
         }
    if(n_led == 3)
   {
   P1OUT |= 0x20;    //P1.5 einschalten  1300nm
   }
   
   TBCCR0 = 0x15;    //Timer_B starten (wirksam erst nach dem ersten
        
   TBCTL |= MC_1;    //Timer_B erstmalig starten
}



void timerb_isr()

{   
   
    n_tb++;       //Inkrement des Timer_B Periodenzählers
   
    if(n_tb == 8)     //8 Durchlaeufe (n_tb=8)
   {  P1OUT = 0x00;  // LED ausschalten  
     
      TBCCR0 = 0;    //Timer_B stoppen
      n_tb = 0;    //Rücksetzen des Timer_B Periodenzählers
            n_led++;          // Zaehler naechste LED
    if(n_led == 4)
      { 
        n_led = 0;
      }
   }

   ADC12CTL0 |= ADC12SC; //SC = Start Conversion
    while ((ADC12CTL1 & ADC12BUSY) == 1);
  
}

void adc_isr()
{  
   Messwerte[n_mw] = ADC12MEM0;;  
  n_mw++;
  
  if(n_mw == 8)
  {
    n_mw = 0;

    if(n_led == 0)
    { 
      mitteln();
      
    }
    if(n_led == 1)
    { 
      mitteln(); 
      senden0();
      
    }
    if(n_led == 2)
    { 
      mitteln();
      senden1();
     }
    if(n_led == 3)
    { 
      mitteln(); 
      senden2();
    }
    
    
  }
  
  
  ADC12IFG = 0x0000;

}


Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe Interrupt, Stichwort volatile.

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

Bewertung
0 lesenswert
nicht lesenswert
volatile ?

Autor: Timo P (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wo wird die Variable denn angelegt?

Autor: Timo P (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
im Übrigen:

gefällt mir folgendes Zitat:
"C Kurs - too many ifs - I think I switch"


siehe:
http://www.peacesoftware.de/ckurs7.html

Autor: Bernd Krause (berndk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
derzeit ist die Variable als "unsigned char" deklariert. Ich werde es 
mal mit volatile probieren und mich dann melden.

Bei 3 oder 4 Variablen ist es eigentlich egal, ob man if oder switch 
nimmt, meine Meinung :)

Autor: Bernd Krause (berndk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habs jetzt mal mit volatile probiert, jedoch aendert sich das 
Verhalten nicht. Was kann ich da uebersehen haben?

Autor: Tobias Korrmann (kurzschluss81)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nochmal die Frage wo ist die Variable deklariert. Diese Variable sollte 
nämlich schon eine Globale sein wenn mehrere, besonders ISR, Teile der 
Software drauf zugreifen.

Autor: Bernd Krause (berndk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hier die Variablendeklaration:

#include <msp430x16x.h>

#include <msp430def.h>

#pragma interrupt_handler timera_isr: TIMERA0_VECTOR  timera_isr: TIMERA1_VECTOR
#pragma interrupt_handler timerb_isr: TIMERB0_VECTOR  timerb_isr: TIMERB1_VECTOR
#pragma interrupt_handler    adc_isr: ADC_VECTOR
#pragma interrupt_handler   sio0_isr: USART0TX_VECTOR

void init_Clock();
void timera_init();
void timerb_init();
void mittel();
void init_DAC();
void init_SIO();
void init_ADC();
//void wait_05ms();
void wait_250us(unsigned int ui_Faktor);

unsigned int temp;
unsigned int val_DAC;
unsigned char n_tb = 0;
volatile n_led = 0;
unsigned char n_mw = 0;
unsigned int Messwerte[4];
unsigned int Messwerte_LED0[4];
unsigned int Messwerte_LED1[4];
unsigned int Messwerte_LED2[4];
unsigned long Summe;
unsigned long dunkel;
unsigned char Ziffern[4];
unsigned int ui_Faktor;
unsigned char text[1] = "A";
unsigned char text2[1] = "B";
unsigned int *ptr_mw0;
unsigned int *ptr_mw1;
unsigned int *ptr_mw2;
unsigned int *ptr_mw;
unsigned int mw = 0;
unsigned int mw0 = 0;
unsigned int mw1 = 0;
unsigned int mw2 = 0;
unsigned int mw0_a;
unsigned int mw0_b;
unsigned long value;
unsigned char split[2];
unsigned char n_send = 0;
unsigned char Ziffern_send[4];
unsigned long Mittelwert_send = 0;

void main(void)
{
....

Autor: Tobias Korrmann (kurzschluss81)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sachmal du weist wirklich nicht was das Wörtchen Volatile bedeutet?

Das Schlüsselwort volatile teilt dem Compiler mit, daß die mit name 
bezeichnete Variable mit dem Datentyp typ durch Ereignisse außerhalb der 
Kontrolle des Programms verändert werden kann.
Der Wert der Variablen muß deshalb vor jedem Zugriff neu aus dem 
Hauptspeicher eingelesen werden, d.h. er darf nicht in einem Register 
des Prozessors zwischengespeichert werden.

Der Compiler arbeitet bei mit volatile deklarierten Variablen ohne jede 
Optimierung, d.h. läßt die entsprechenden Werte bei jedem Zugriff neu 
aus dem Hauptspeicher laden und sorgt bei Veränderungen dafür, daß die 
neuen Werte ohne Verzögerung dort sofort abgelegt werden.

Du must der Variable wenigstens noch einen datentyp Spendieren.
So geht dat jedenfalls nicht

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

Bewertung
0 lesenswert
nicht lesenswert
Bernd Krause schrieb:
> hier die Variablendeklaration:

> unsigned char text[1] = "A";
> unsigned char text2[1] = "B";

Zu kurz.
Die Strings "A" bzw. "B" sind 2 Zeichen lang.
Überlass dem Compiler in solchen Fällen das Abzählen! Der macht keine 
Fehler.

unsigned char text[] = "A";
unsigned char text2[] = "B";

> unsigned char split[2];
> unsigned char Ziffern_send[4];

Möglich, dass ich mich täusche. Aber du hast da ein paar sehr klein 
dimensionierte Arrays, deren Namen für mich danach klingt, als ob sie 
für Stringverarbeitung benutzt werden. Ziffern_send klingt für mich zb. 
danach. Und nach dem Fehler von weiter oben halte ich einen 
Array-Overflow irgendwo für durchaus möglich.

Poste mal alles, damit man den C-Code mal auf grobe Schnitzer durchsehen 
kann.

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

Bewertung
0 lesenswert
nicht lesenswert
Tobias Korrmann schrieb:

> Du must der Variable wenigstens noch einen datentyp Spendieren.
> So geht dat jedenfalls nicht

Doch das geht.
In C ist alles was du nicht explizit mit einem Datentyp versiehst ein 
int.

Autor: Bernd Krause (berndk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bin fuer jeden Ratschlag dankbar
#include <msp430x16x.h>

#include <msp430def.h>

#pragma interrupt_handler timera_isr: TIMERA0_VECTOR  timera_isr: TIMERA1_VECTOR
#pragma interrupt_handler timerb_isr: TIMERB0_VECTOR  timerb_isr: TIMERB1_VECTOR
#pragma interrupt_handler    adc_isr: ADC_VECTOR
#pragma interrupt_handler   sio0_isr: USART0TX_VECTOR

void init_Clock();
void timera_init();
void timerb_init();
void mittel();
void init_DAC();
void init_SIO();
void init_ADC();
//void wait_05ms();
void wait_250us(unsigned int ui_Faktor);

unsigned int temp;
unsigned int val_DAC;
unsigned char n_tb = 0;
volatile n_led = 0;
unsigned char n_mw = 0;
unsigned int Messwerte[4];
unsigned int Messwerte_LED0[4];
unsigned int Messwerte_LED1[4];
unsigned int Messwerte_LED2[4];
unsigned long Summe;
unsigned long dunkel;
unsigned char Ziffern[4];
unsigned int ui_Faktor;
unsigned char text[1] = "A";
unsigned char text2[1] = "B";
unsigned int *ptr_mw0;
unsigned int *ptr_mw1;
unsigned int *ptr_mw2;
unsigned int *ptr_mw;
unsigned int mw = 0;
unsigned int mw0 = 0;
unsigned int mw1 = 0;
unsigned int mw2 = 0;
unsigned int mw0_a;
unsigned int mw0_b;
unsigned long value;
unsigned char split[2];
unsigned char n_send = 0;
unsigned char Ziffern_send[4];
unsigned long Mittelwert_send = 0;

void main(void)
{
    _STOP_WATCHDOG();    //definiert in "msp430def.h"
   
   ptr_mw  = &mw; 
   ptr_mw0 = &mw0; 
   ptr_mw1 = &mw1; 
   ptr_mw2 = &mw2;    
  
   P1SEL = 0x00;      //Std.IO
   P1DIR = 0xFF;        //alles Ausgänge
   P1OUT = 0x00;        // at startup all outputs off
   P1OUT |= 0x10;        // Verstaerkung -1 
   //P1OUT |= 0x01;
   P2SEL = 0x00;      //Std.IO
   P2DIR = 0xFF;      //alles Ausgänge
   
   P5SEL = 0xFF;      //Std.IO
   
   P3SEL = 0xf0;     //P3.0..3 Standard I/O; P3.4..7 Peripheral Modul Function (UART)
   P3DIR = 0x00;     //P3.0..3 Ausgaenge; P3.4..7 = x

   P6SEL = 0xFF;        //Peripheral Modul Function (ADC12)
   
   init_Clock();
   timera_init();
   timerb_init();
   init_DAC();
   init_ADC();
   init_SIO();
   
  
   //Interruptfreigaben
   //ADC12IE = 0xFFFF;  //Int-Freigabe für das Ergebnisregister ADC12MEM0
   //ADC12IE = ADC12IE2;   
   //ADC12IE = 0x0004;             // ADC12 memory 0,2, 
   ADC12IE = 0x0001; 
   TACCTL0 |= CCIE;   //Timer A C/C Int Enable (für TACCR0)

   TBCCTL0 |= CCIE;   //Tiemr_B C/C Int Enable (für TBCCR0)
   
   IE1     |= UTXIE0;   //SIO0 TX-Int freigeben
   
   _BIS_SR(GIE);     //GIE = 1, globale Interruptfreigabe
  

   TACTL |= MC_1;    //Timer_A starten
   // CPU Takt
   DCOCTL = DCO0 + DCO1 + DCO2;
   BCSCTL1 = RSEL0 + RSEL1 + RSEL2 + DIVA_0;
   BCSCTL2 = SELM_2 + DIVM_0 + DIVS_0 + SELS;
    
  
   while(1);  //Endlosschleife - Warten auf Interrupts

}


void init_Clock( void )
{ unsigned char i = 0;
  // Turning XT1 (32kHz) on
  _BIC_SR (OSCOFF);           // Turn on XT1
  BCSCTL1 &= ~XTS;          // LF mode
  for (i = 0xFFFF; i > 0; i--);   // Time for osc. to set
  // XT1 is on

  // Turning XT2 (8MHz) on
  BCSCTL1 &= ~XT2OFF;         // Turn on XT2
  do
  {                       // pruefroutine, ob 8 Mhz-oszillator schon stabil ist
    IFG1 &= ~OFIFG;       // OSCFault flag loeschen (zeigt oszillatorfehler an)
    for (i=0xFF;i>0;i--); // warten, ob es wieder gesetzt wird
  }
  while ((IFG1 & OFIFG) != 0);   // OSCFault immer noch gesetzt?

}


void timera_init()
{
  TACTL = TASSEL_2 | ID_3;   //SourceClock = SMCLK

   TACCR0 = 0x3000;    
            
}            

                        
void timerb_init()
{
     
    TBCTL = TBSSEL_1 | ID_0;    //SourceClock = ACLK

    TBCCR0 = 0x15;          
}


void init_DAC(void)
{
  DAC12_0CTL = DAC12IR + DAC12SREF_2 + DAC12AMP_5 + DAC12ENC;   // 1 reference voltage, medium speed
  DAC12_1CTL = DAC12IR + DAC12SREF_2 + DAC12AMP_5 + DAC12ENC;   // 1 reference voltage, medium speed 
}

void init_ADC(void)
{
   ADC12CTL0 = SHT0_14 + ADC12ON ;
  ADC12CTL1 =  CSTARTADD_0 + SHS_0 + SHP + ADC12DIV_0 + ADC12SSEL_2 + CONSEQ_0;
  //ADC12MCTL0 = SREF_2 + INCH_2;    //ADC12MEM0, A2 PIN62
  ADC12MCTL0 = SREF_2 + INCH_3;    //ADC12MEM0, A3 PIN5
  ADC12CTL0 |= ENC;  //ADC startfähig machen

}

void init_SIO(void)
{
//SIO0
  ME1 |= UTXE0;                 //Transmitter enablen
  U0CTL |= CHAR;                //8 data bits, 1 stop bit, no parity (8N1)
  //U0TCTL |= 0x10;              //ACLK als UCLK festlegen
    U0TCTL |= SSEL1;           // SMCLK als UCLK festlegen
    //UBR00=0xA0; UBR10=0x01; UMCTL0=0x00; /* uart0 8000000Hz 19198bps */
  //UBR00=0x41; UBR10=0x03; UMCTL0=0x09; /* uart0 8000000Hz 9600bps */
    UBR00=0x45; UBR10=0x00; UMCTL0=0xAA; /* uart0 8000000Hz 115107bp */
  //UBR00=0x45; UBR10=0x00; UMCTL0=0xD6; /* uart0 8000000Hz 114942bps */

    //UBR00=0x22; UBR10=0x00; UMCTL0=0xDD; /* uart0 8000000Hz 230547bps */


  U0BR1 = 0x00;                 
  
  U0CTL &= ~SWRST;              //USART freigeben

//  IFG1 &= ~UTXIFG0;             //initales Int-Flag löschen
}

void sio0_isr(void)

{    

  if(n_send < 4)

  {   
     
     U0TXBUF = Ziffern[n_send];
    
    n_send++;
        
  }

  else

  {

     n_send = 0;
      

  }

}
 
void write_DAC0(unsigned int val_DAC)
{
  DAC12_0DAT = val_DAC;
}
void write_DAC1(unsigned int val_DAC2)
{
  DAC12_1DAT = val_DAC2;
}
void timera_isr()

{   /////// Initphase ////
    /// sekunden einlesen.. mitteln .. wert in unteres drittel des Wertebereichs ziehen, offset spannung waehlen und setzen,..verstaerkung auf Grundwert zurueck rechnen
     ///DAC1 Ref 2.5V  

     //TESTOV:
   write_DAC0(0xa00);
  
    if(n_led == 0)
   {
   P1OUT = 0x00; 
    
   }
    if(n_led == 1)
   {
   P1OUT |= 0x80;      //P1.7 einschalten 
   write_DAC1(0xa00);
    
   }
    if(n_led == 2)
   {
   P1OUT |= 0x40;    //P1.6 einschalten 
   write_DAC1(0x851); //LED
      
   }
    if(n_led == 3)
   {
   //write_DAC0(0x00); 
   //a00  1,5V, 334 0.5V, 670 1V
   P1OUT |= 0x20;    //P1.5 einschalten  
   write_DAC1(0xfff); //LED
   }
   
   TBCCR0 = 0x15;    //Timer_B starten (wirksam erst nach dem ersten
        
   TBCTL |= MC_1;    //Timer_B erstmalig starten
   //P2OUT &= 0xfe;
}



void timerb_isr()

{   
    //P2OUT |= 0x02;
    n_tb++;       //Inkrement des Timer_B Periodenzählers
   
    if(n_tb == 8)     //4 Durchlaeufe (n_tb=4)
   {  P1OUT = 0x00;    //P1 ausschalten  
      write_DAC1(0x00);
      P1OUT |= 0x10; //verstaerkung -1 an
    //P1OUT |= 0x01; //
      TBCCR0 = 0;    //Timer_B stoppen
      n_tb = 0;    //Rücksetzen des Timer_B Periodenzählers

    n_led++;          // Zaehler naechste LED
    if(n_led == 4)
    { 
      n_led = 0;
    }
   }

   ADC12CTL0 |= ADC12SC; //SC = Start Conversion
    while ((ADC12CTL1 & ADC12BUSY) == 1);
   //P2OUT &= 0xfd;
}

void adc_isr()
{  
  //P2OUT |= 0x04; //Pin4
    Messwerte[n_mw] = ADC12MEM0;;  
  n_mw++;
  
  if(n_mw == 8)
  {
    
    n_mw = 0;
    if(n_led == 0)
    { 
      mitteln();
     
      
    }
    
    if(n_led == 1)
    { 
      mitteln();
      to_ascii(); 
      senden0();
      
    }
    if(n_led == 2)
    { 
      mitteln();
      to_ascii(); 
      senden1();
     }
    if(n_led == 3)
    { 
      mitteln();
      to_ascii(); 
      senden2();
    }
    
    
  }
  
  
  
  ADC12IFG = 0x0000;
  
}






void senden0(unsigned long value)

{
   //split[0]= mw0 ;  // low byte
  //split[1]= mw0/256; // high byte
   U0TXBUF = 0x23;   //initiales Senden  #
}

void senden1(unsigned long value)

{
     //split[0]= mw1 ;  // low byte
  //split[1]= mw1/256; // high byte
    U0TXBUF = 0x21;   //initiales Senden  "
}

void senden2(unsigned long value)

{   
   //split[0]= mw2;  // low byte
  //split[1]= mw2/256; // high byte
   //mw2=0x600;
   U0TXBUF = 0x25;   //initiales Senden  %
}

void mitteln()

{

  unsigned char i = 0;

  

  Summe = 0;

  

  for(i=0; i<8; i++)

  {

    Summe += Messwerte[i];

  }



  Summe /= i;
  
  
  i = 0;

}





void to_ascii()

{

  unsigned char i;  



  //Beschreiben des Ziffern-Arrays mit ASCII-Nullen

  for(i=0; i<4; i++)

  {

    Ziffern[i] = 0x30;

  }  



  //Algorithmus zur Zerlegung des Spannungswertes in die einzelnen Ziffern

  while(Summe > 999)   //1.000er Stelle abspalten

  {

    Summe -= 1000;

    Ziffern[0]++;

  }

  

  while(Summe > 99)   //100er Stelle abspalten

  {

    Summe -= 100;

    Ziffern[1]++;

  }

  

  while(Summe > 9)  //10er Stelle abspalten

  {

    Summe -= 10;

    Ziffern[2]++;

  }

  

  while(Summe > 0)  //1er Stelle abspalten

  {

    Summe -= 1;

    Ziffern[3]++;

  }

}






Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Bernd Krause (berndk)

>Bin fuer jeden Ratschlag dankbar

Na dann lies mal was hier drüber steht!

"Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang"

Siehe auch Netiquette

MFG
Falk

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

Bewertung
0 lesenswert
nicht lesenswert
Erster Eindruck:
tu dir selbst einen Gefallen und reduziere die Anzahl der Leerzeilen. 
Wenn eine Leerzeile zwischen 2 Funktionsblöcken dir keine Übersicht 
bringt, dann tun es auch mehrere Leerzeilen nicht. Allerdings ziehen 
mehrere Leerzeilen den Code nur unnötig in die Länge und verringern die 
Übersicht.

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

Bewertung
0 lesenswert
nicht lesenswert
Ähm
unsigned int Messwerte[4];

...


    Messwerte[n_mw] = ADC12MEM0;;  
  n_mw++;
  
  if(n_mw == 8)
  {
    n_mw = 0;
    ....

n_mw kann also Werte von 0 bis 7 annehmen. Messwerte besitzt aber nur 4 
Elemente.

Du gehst jetzt her und korrigierst diese Out-Of-Bounds Array Zugriffe 
erst mal. Das machst du so

#define NR_MESSWERTE  4
unsigned int Messwerte[ NR_MESSWERTE ];

....

   Messwerte[n_mw] = ADC12MEM0;

   n_mw++;
   if( n_mw == NR_MESSWERTE )
   {
     n_mw = 0;
     ... 

sprich:
Du führst dir für diverse konstante Zahlenwerte, vornehmlich 
Arraygrößen, sprechende Namen in Form eines #define ein und gehst dann 
dein Programm durch, welcher konstanter Zahlenwert in deinem Programm in 
Wirklichkeit einem dieser #define entspricht bzw. davon abhängt und 
sorgst erst mal dafür, dass du nirgends mehr auf ein Array ausserhalb 
seiner Grenzen zugreifst.

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

Bewertung
0 lesenswert
nicht lesenswert
Solche Dinge
void senden0(unsigned long value)
{
   //split[0]= mw0 ;  // low byte
  //split[1]= mw0/256; // high byte
   U0TXBUF = 0x23;   //initiales Senden  #
}

ersetzt du ebenfalls. Es gibt hier keinen Grund den ASCII Code für # 
anzuführen
void senden0(unsigned long value)
{
   //split[0]= mw0 ;  // low byte
  //split[1]= mw0/256; // high byte
   U0TXBUF = '#';
}

und schon sieht man im Code was hier passiert und ist nicht mehr auf 
einen Kommentar angewiesen, der gerne auch einmal falsch sein kann.

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

Bewertung
0 lesenswert
nicht lesenswert
Und dann gehst du her und durchsuchst deine globalen Variablen, welche 
davon nicht mehr gebraucht werden und löscht sie raus. Einige davon 
werden nur von einer Funktion benutzt und sind dann dort als lokale 
Variable besser aufgehoben.

Autor: Bernd Krause (berndk)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich hab den Quelltext jetzt entruempelt, danke fuer eure Tips. Jedoch 
stehe ich immer noch vor dem Problem, dass die Variable n_led in der 
Timer_A Routine und der ADC_ISR nicht uebereinstimmen. Das macht sich 
jetzt so bemerkbar, dass das setzen von (P1OUT |= 0x20;//P1.5 
einschalten ) in der ADC_ISR nicht registriert wird.
Koennt ihr den Fehler entdecken?
Vielen Dank
Bernd

Autor: Frank M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd Krause (berndk) schrieb:

> ich hab den Quelltext jetzt entruempelt, [...]

Ich sehe da noch jede Menge Variablen, auf die in den ISRs zugegriffen 
bzw. welche dort auch verändert werden, z.B. n_mw, n_send, Ziffern[] 
usw.

Auch sind globale Variablen, die Du in Unterfunktionen, welche von den 
ISRs aufgerufen werden, davon betroffen, wie z.B. die Variable "Summe".

All diese Variablen solltest Du als volatile deklarieren.

Merkwürdigerweise hast Du die Tipps, die Du bekommen hast, immer nur auf 
die konkreten Fälle angewandt, aber nicht bei den weiteren 
Vorkommnissen, wie z.B.

   Ziffern[4]
statt
   Ziffern[NR_ZIFFERN]

oder auch
   Ziffern[i] = 0x30;
statt
   Ziffern[i] = ' ';

Insgesamt ist der Source wegen der vielen Leerzeilen und wegen der nicht 
immer korrekten Einrückungen ziemlich unleserlich. Macht nicht viel 
Freude, den Code zu lesen und verstehen zu wollen.

Gruß,

Frank

Autor: Frank M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. (Gast) schrieb:

> Ziffern[i] = ' ';

Sorry, vertippert, meinte natürlich:

Ziffern[i] = '0';

Gruß,

Frank

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

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:

> Merkwürdigerweise hast Du die Tipps, die Du bekommen hast, immer nur auf
> die konkreten Fälle angewandt, aber nicht bei den weiteren
> Vorkommnissen, wie z.B.
>

Oder auch hier.
void mitteln()

{
  unsigned char i = 0;
  Summe = 0;
    for(i=0; i<8; i++)

  {
    Summe += Messwerte[i];
  }
  Summe /= i;
  i = 0;

}

Anstelle der 8 sollte eigentlich NR_MESSWERTE stehen.
Aber na gut, kein Meister ist vom Himmel gefallen. Zumindest sind jetzt 
die offensichtlichen 'Wild in den Speicher'-Schreiborgien weg.

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

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mir jetzt die Fehlerbeschreibung noch einmal durchgelesen. Und 
je öfter ich das tue, desto mehr komme ich zur Erkenntnis, dass ich die 
Fehlerbeschreibung nicht verstehe.

Also: Wie ist das beobachtbare Verhalten? Inwieweit unterschiedet sich 
das von dem was du erwartest?
(Sag jetzt bitte nicht, dass n_led irgendwie magisch den falschen Wert 
hat. Das ist eine Diagnose von dir. Diese Diagnose kann richtig sein 
oder auch nicht. Ich will wissen: was passiert, wie stellst du den 
Fehler fest? Und danach und mit dem Quelltext stelle ich dann meine 
eigene Diagnose auf)

Autor: Bernd Krause (berndk)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe mal den funktionierenden Code zum Vergleich angehaengt. Der 
Unterschied besteht darin, dass ich den Zaehler n_led in Timer_A bis 4 
laufen lasse, anstatt bis drei. Im falle des nicht funktionierenden 
Codes geschieht folgendes:
Im falle von n_led == 3 ist  P1.5 aktiviert(LED eingeschaltet), jedoch 
geschieht das nicht. Die ADC_ISR (abtasten einer Photodiode) sendet bei 
n_led=3 die werte einer deaktivieren LED.

BSP n_led bis 3 (funktioniert wie es soll)

2.5V (senden0)
2.5V (senden1)
2.5V (senden2)

nun bis n_led =4

2.5V  (senden0)
2.5V  (senden1)
0V    (senden2)   da bei n_led= 0 alle LEDs abgeschaltet sind und nicht 
bei n_led= 3 ist hier der Fehler, sollte in diesem Fall auch 2.5V sein

Ich hoffe ich habe den Fehler verstaendlich beschrieben...

Vielen Dank
Bernd

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd Krause (berndk) schrieb:

> ich habe mal den funktionierenden Code zum Vergleich angehaengt. [...]

Ich habe mal den nicht-funktionierenden Code (4er Version) mit der 
funktionierenden 3er Version verglichen und finde da u.a. den folgenden 
Unterschied in Funktion timera_isr():

3er Version:
   if(n_led == 0)
   {
      P1OUT |= 0x80;      //P1.7 einschalten 
      write_DAC1(0xa00);
   }

4er Version:
   if(n_led == 0)
   {
     P1OUT = 0x00;   
   }

das heisst, dass der Aufruf von write_DAC1() in der 4er Version fehlt.

Trotzdem solltest Du die gestrigen Ratschläge beherzigen und die in den 
ISR-Routinen veränderten Variablen als volatile deklarieren, sonst sind 
weitere böse Überraschungen vorprogrammiert.

Ich würde Deine langen if-Ketten auch in switch-Statements umwandeln: 
erstens effektiver, zweitens lesbarer. Oder zumindest if-else-if 
verwenden, damit der arme µC sich weitere Vergleiche sparen kann, sobald 
der Vergleich mit n_led erfolgreich war.

Gruß,

Frank

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... und Du bist Dir auch sicher, dass Deine Interrupts alle zur 
richtigen Zeit ausgelöst werden und sich nicht irgendwie ineinander 
"verheddern"?
-> Timingdiagramm aufmalen und gucken, wann jeweils ein IRQ feuert und 
wie lange seine Ausführung dauert.

BTW: Wenn ich das richtig sehe, clockst Du den ADC12 mit 8MHZ?!
Erlaubt sind max. 6,3MHz!

Autor: Bernd Krause (berndk)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

zunaechst danke das ihr mich so tatkraeftig unterstuetzt.

@Stefan
Den ADC12 Takt habe ich nun auf 4Mhz reduziert. Das Timing habe ich 
nochmal uberprueft und noch veraendert. .. siehe Taktdiagramm Anhang.

@ukw
Der Unterschied bei n_led=0 war beabsichtigt. Das Programm mit lediglich 
3 LEDs laeuft bestens, jedoch wollte ich vor dem einschalten der jeweils 
3 LEDs eine Leermessung mit dem ADC machen. Dieses Ergebnis wollte ich 
dann von den spaeteren Messungen der anderen LEDs abschalten.

Die Variablen sind jetzt alle als volatile deklariert, jedoch komme ich 
damit immer noch nicht weiter. Die uebermittelten Werte bei "n_led=3" 
der ADC12_ISR  sind quasi 0. Diese sollten jedoch bei n_led=0 auftreten.
Hat jemand noch eine Idee woran das liegen koennte?

Danke
Bernd

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

Bewertung
0 lesenswert
nicht lesenswert
Kann es sein, dass das Problem bei der UART Übertragung entsteht? Die 
Ausgabe auf die UART erscheint mir da ziemlich unkoordiniert zu laufen.

Autor: Bernd Krause (berndk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Datenuebetragung kann ich ausschliessen. Schalte ich bei dem 
Programm mit drei LEDs eine ab, wird das auch richtig detektiert. Zeit 
zum senden ist auch ausreichend vorhanden. Weshalb meinst du ist das 
unkoordiniert?

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
UART passt soweit eigentlich, nur
UBR00=0x45; 
UBR10=0x00; 
UMCTL0=0xAA;
U0BR1 = 0x00;  identisch mit UBR10=0x00, also doppelt!
macht aber nix.

In der TMR_B_ISR:
ADC12CTL0 |= ADC12SC; //SC = Start Conversion
while ((ADC12CTL1 & ADC12BUSY) == 1);  <-- unnötig!
Warteschleife unnötig, dafür gibt's ja die ADC12_ISR!

Ich glaube auch, ich habe Deine Anwendung noch nicht ganz kapiert, ist 
aber vielleicht auch schwierig zu erklären...?!

Eines fällt mir auf (ist das gewollt oder nicht?):
Du startest in TMR_A_ISR mit n_led = 0.
Darauf folgt TMR_B_ISR 4x mit 4 ADC-Messungen. Sind alle 4 Messungen 
vorbei, wird in TMR_B_ISR n_led um 1 erhöht. Damit (also mit n_led == 1) 
wird dann ADC12_ISR final aufgerufen!
D.h. die Messungen mit n_led==0 werden in der ADC12_ISR unter n_led==1 
verarbeitet, usw...
Ausserdem setzt Du in TMR_B_ISR schon vor der 4. Messung P1OUT = 0, DAC1 
= 0 und P1OUT |= 0x10... sollte das nicht erst nach der 4. messung 
passieren?

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.