Forum: Mikrocontroller und Digitale Elektronik Funktion nur ausführen in Interupt


von TS (Gast)


Lesenswert?

Guten Tag ich habe einen i2C Slave in Betrieb der mir Daten Sendet und
empfängt. Da ich das Schreiben von Werten in dem Interuptprogramm
durchfüren möchte, muss ich all diese Parameter übergeben aus dem Main
(in Funktion Set_Sensor1). Ich möchte die Funktion Set_Sensor1 im
Interupt nur durchführen also eigentlich nur Set_Sensor1(void). Da ich
diese Funktion nur benötige um die Variabeln vom Main zu transferieren
und das Senden auszuführen. Mit Globalen Variabeln würde dies ja ohne
probleme gehen aber möchte diese nicht verwenden, damit ich die
übersicht über die Einzelnen Variabeln besitze. Meine Frage wie bringe
ich die Funktion in meinen Interupt um nur die Funktion auszuführen.
Stelle Markiert wo die Funktion hinein sollte. Den eine Funtion in einer
Funktion hab ich ein wernig ausprobiert und erkennt dan die Variabeln
nicht mehr.
1
//#################################################################################################*/
2
3
#include <util/twi.h>                 // Bezeichnungen für Statuscodes in TWSR
4
#include <avr/interrupt.h>               // behandlung der Interrupts
5
#include <stdint.h>                 // definiert Datentyp uint8_t
6
#include "twislave.h"                 
7
8
9
10
//########################################################################################## init_twi_slave 
11
12
void init_twi_slave(uint8_t adr)
13
{  
14
  cli();
15
  TWAR= adr; //Adresse setzen
16
  TWCR &= ~(1<<TWSTA)|(1<<TWSTO);
17
  TWCR|= (1<<TWEA) | (1<<TWEN)|(1<<TWIE);   
18
  buffer_adr=0xFF;  
19
  sei();
20
}
21
//********************************************************************************************
22
23
void Set_Sensor1(uint8_t *A1, uint8_t *B1, uint8_t *C1, uint8_t *D1, uint8_t *E1)
24
{
25
  if (rxbuffer[0] == 0x11)
26
  {
27
    txbuffer[2]=*A1;
28
    txbuffer[3]=*B1;
29
    txbuffer[4]=*C1;
30
    txbuffer[5]=*D1;
31
    txbuffer[6]=*E1;
32
  }
33
}
34
//#################################### Macros
35
//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten
36
#define TWCR_ACK   TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);  
37
38
//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten     
39
#define TWCR_NACK   TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);
40
41
//switched to the non adressed slave mode...
42
#define TWCR_RESET   TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);  
43
//########################################################################################## ISR (TWI_vect) 
44
//ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann 
45
//ein Statuscode, anhand dessen die Situation festgestellt werden kann.
46
ISR (TWI_vect)  
47
{
48
  uint8_t data=0;
49
  switch (TW_STATUS)                 // TWI-Statusregister prüfen und nötige Aktion bestimmen 
50
    {
51
    case TW_SR_SLA_ACK:             // 0x60 Slave Receiver, wurde adressiert  
52
      TWCR_ACK;                 // nächstes Datenbyte empfangen, ACK danach
53
      buffer_adr=0xFF;             // Bufferposition ist undefiniert
54
      break;
55
56
    case TW_SR_DATA_ACK:             // 0x80 Slave Receiver,Daten empfangen
57
      data=TWDR;                 // Empfangene Daten auslesen
58
      if (buffer_adr == 0xFF)         // erster Zugriff, Bufferposition setzen
59
        {
60
          if(data<=buffer_size)      // Kontrolle ob gewünschte Adresse im erlaubten bereich
61
            {
62
              buffer_adr= data;     // Bufferposition wie adressiert setzen
63
            }
64
          else
65
            {
66
            buffer_adr=0;         // Adresse auf Null setzen. Ist das sinnvoll?
67
            }        
68
          TWCR_ACK;            // nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern
69
        }
70
      else                   // weiterer Zugriff, Daten empfangen
71
        {
72
          rxbuffer[buffer_adr]=data;     // Daten in Buffer schreiben
73
          buffer_adr++;           // Buffer-Adresse weiterzählen für nächsten Schreibzugriff
74
          if(buffer_adr<(buffer_size-1)) // im Buffer ist noch Platz für mehr als ein Byte
75
            {
76
              TWCR_ACK;        // nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern
77
            }
78
          else                 // es kann nur noch ein Byte kommen, dann ist der Buffer voll
79
            {
80
              TWCR_NACK;        // letztes Byte lesen, dann NACK, um vollen Buffer zu signaliseren
81
            }
82
        }
83
      break;
84
85
    case TW_ST_SLA_ACK:             //
86
    case TW_ST_DATA_ACK:             // 0xB8 Slave Transmitter, weitere Daten wurden angefordert
87
88
      if (buffer_adr == 0xFF)         // zuvor keine Leseadresse angegeben! 
89
        {
90
          buffer_adr=0;
91
        }  
92
      TWDR = txbuffer[buffer_adr];       // Datenbyte senden 
93
      buffer_adr++;               // bufferadresse für nächstes Byte weiterzählen
94
      if(buffer_adr<(buffer_size-1))     // im Buffer ist mehr als ein Byte, das gesendet werden kann
95
        {
96
          TWCR_ACK;             // nächstes Byte senden, danach ACK erwarten
97
        }
98
      else
99
        {
100
          TWCR_NACK;             // letztes Byte senden, danach NACK erwarten
101
        }
102
      break;
103
104
    case TW_ST_DATA_NACK:             // 0xC0 Keine Daten mehr gefordert 
105
    case TW_SR_DATA_NACK:             // 0x88 
106
    case TW_ST_LAST_DATA:             // 0xC8  Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
107
    case TW_SR_STOP:               // 0xA0 STOP empfangen
108
    default:   
109
      TWCR_RESET;               // Übertragung beenden, warten bis zur nächsten Adressierung
110
      break;  
111
      
112
    } //end.switch (TW_STATUS)
113
    
114
    //*!*!*!*! Hier soll die Funktion nur ausgeführt werden!!!***!!!    
115
116
117
} //end.ISR(TWI_vect)

von Michael B. (laberkopp)


Lesenswert?

TS schrieb:
> Mit Globalen Variabeln würde dies ja ohne probleme gehen

Tja, nun, volatile nicht vergessen.

> aber möchte diese nicht verwenden

Meinst du nicht, daß dein Problem hausgemacht ist, wegen deiner 
Weigerung, es richtig zu machen ?

Kümmere dich erst mal um die vielen Stellen, an denen dein Programm eher 
ungünstig strukturiert ist z.B. Pointer zu übergeben nur weil du die 
Werte lesen willst (ein Pointer ist wesentlich grösser als der Wert und 
zudem eine weitere Indirektionsstufe), bischen viele Vergleiche wo dein 
Pointer gerade steht...

von TS (Gast)


Lesenswert?

Ja dies kann ja sein. Nur löst dies nicht mein problem, wen ich die 
Funtion nur leditglich ausführen möchte im Interupt.

von Theor (Gast)


Lesenswert?

Ich denke Dein Problem hat zunächst mit dem Geltungsbereich von 
Variablen zu tun und deren Zusammenhängen mit Parametern.

Ich rate Dir: Nimm ganz einfache Programme um die Grundlagen zu lernen.

Formuliere am besten also ausgehend von Deinen Kenntnissen und anhand 
eines Programmes, dass sich auf das Problem konzentriert, Deine Frage 
neu. Meine Empfehlung.

von TS (Gast)


Lesenswert?

Michael B. schrieb:

> Weigerung, es richtig zu machen ?

Und Globale Variabeln sind nicht übersichtlich. Und ganz sicher nicht 
umbedingt richtig!

von TS (Gast)


Lesenswert?

Wer nicht versteht, was ich möchte ist dies hier Dargestellt. Nur eben 
die Variabeln werden nicht merh erkannt in der Funkton Set_Sensor1. Wie 
ändere ich dies?
1
//#################################################################################################*/
2
3
#include <util/twi.h>                 // Bezeichnungen für Statuscodes in TWSR
4
#include <avr/interrupt.h>               // behandlung der Interrupts
5
#include <stdint.h>                 // definiert Datentyp uint8_t
6
#include "twislave.h"                 
7
8
9
10
//########################################################################################## init_twi_slave 
11
12
void init_twi_slave(uint8_t adr)
13
{  
14
  cli();
15
  TWAR= adr; //Adresse setzen
16
  TWCR &= ~(1<<TWSTA)|(1<<TWSTO);
17
  TWCR|= (1<<TWEA) | (1<<TWEN)|(1<<TWIE);   
18
  buffer_adr=0xFF;  
19
  sei();
20
}
21
22
//#################################### Macros
23
//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten
24
#define TWCR_ACK   TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);  
25
26
//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten     
27
#define TWCR_NACK   TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);
28
29
//switched to the non adressed slave mode...
30
#define TWCR_RESET   TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);  
31
//########################################################################################## ISR (TWI_vect) 
32
//ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann 
33
//ein Statuscode, anhand dessen die Situation festgestellt werden kann.
34
ISR (TWI_vect)  
35
{
36
  uint8_t data=0;
37
  switch (TW_STATUS)                 // TWI-Statusregister prüfen und nötige Aktion bestimmen 
38
    {
39
    case TW_SR_SLA_ACK:             // 0x60 Slave Receiver, wurde adressiert  
40
      TWCR_ACK;                 // nächstes Datenbyte empfangen, ACK danach
41
      buffer_adr=0xFF;             // Bufferposition ist undefiniert
42
      break;
43
44
    case TW_SR_DATA_ACK:             // 0x80 Slave Receiver,Daten empfangen
45
      data=TWDR;                 // Empfangene Daten auslesen
46
      if (buffer_adr == 0xFF)         // erster Zugriff, Bufferposition setzen
47
        {
48
          if(data<=buffer_size)      // Kontrolle ob gewünschte Adresse im erlaubten bereich
49
            {
50
              buffer_adr= data;     // Bufferposition wie adressiert setzen
51
            }
52
          else
53
            {
54
            buffer_adr=0;         // Adresse auf Null setzen. Ist das sinnvoll?
55
            }        
56
          TWCR_ACK;            // nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern
57
        }
58
      else                   // weiterer Zugriff, Daten empfangen
59
        {
60
          rxbuffer[buffer_adr]=data;     // Daten in Buffer schreiben
61
          buffer_adr++;           // Buffer-Adresse weiterzählen für nächsten Schreibzugriff
62
          if(buffer_adr<(buffer_size-1)) // im Buffer ist noch Platz für mehr als ein Byte
63
            {
64
              TWCR_ACK;        // nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern
65
            }
66
          else                 // es kann nur noch ein Byte kommen, dann ist der Buffer voll
67
            {
68
              TWCR_NACK;        // letztes Byte lesen, dann NACK, um vollen Buffer zu signaliseren
69
            }
70
        }
71
      break;
72
73
    case TW_ST_SLA_ACK:             //
74
    case TW_ST_DATA_ACK:             // 0xB8 Slave Transmitter, weitere Daten wurden angefordert
75
76
      if (buffer_adr == 0xFF)         // zuvor keine Leseadresse angegeben! 
77
        {
78
          buffer_adr=0;
79
        }  
80
      TWDR = txbuffer[buffer_adr];       // Datenbyte senden 
81
      buffer_adr++;               // bufferadresse für nächstes Byte weiterzählen
82
      if(buffer_adr<(buffer_size-1))     // im Buffer ist mehr als ein Byte, das gesendet werden kann
83
        {
84
          TWCR_ACK;             // nächstes Byte senden, danach ACK erwarten
85
        }
86
      else
87
        {
88
          TWCR_NACK;             // letztes Byte senden, danach NACK erwarten
89
        }
90
      break;
91
92
    case TW_ST_DATA_NACK:             // 0xC0 Keine Daten mehr gefordert 
93
    case TW_SR_DATA_NACK:             // 0x88 
94
    case TW_ST_LAST_DATA:             // 0xC8  Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
95
    case TW_SR_STOP:               // 0xA0 STOP empfangen
96
    default:   
97
      TWCR_RESET;               // Übertragung beenden, warten bis zur nächsten Adressierung
98
      break;  
99
      
100
    } //end.switch (TW_STATUS)
101
    
102
    void Set_Sensor1(uint8_t A1, uint8_t B1, uint8_t C1, uint8_t D1, uint8_t E1)
103
    {
104
      if (rxbuffer[0] == 0x11)
105
      {
106
        txbuffer[2]=A1;
107
        txbuffer[3]=B1;
108
        txbuffer[4]=C1;
109
        txbuffer[5]=D1;
110
        txbuffer[6]=E1;
111
      }
112
    }    
113
114
115
} //end.ISR(TWI_vect)

von Theor (Gast)


Lesenswert?

Ach so. Also ist die Frage wohl speziell auf Interrupts gezielt.

1. In Interrupts ruft man keine Funktionen auf, die Anwendungsdaten 
übernehmen und sie senden. (Das gilt nicht unbedingt für gepufferte 
Daten).

2. Interrupt-Handler können keine Parameter übergeben werden. Globale 
bzw. Modul-Globale Variablen sind die einzige Möglichkeit.

von Theor (Gast)


Lesenswert?

> Wer nicht versteht, was ich möchte ist dies hier Dargestellt.
> Nur eben die Variabeln werden nicht merh erkannt in der
> Funkton Set_Sensor1. Wie ändere ich dies?

Ich denke wir verstehen schon, was Du willst.
Du verstehst nur nicht, warum das nicht geht. Dir fehlen C-Grundlagen.

Du kannst keine Funktion innerhalb einer Funktionsdefinition definieren.

Nochmal: Mache Dir klar und lerne was der Geltungsbereich von Variablen 
ist und was er für Konsequenzen hat. Achte darauf das für Interrupts 
besondere Regeln gelten.

von Michael B. (laberkopp)


Lesenswert?

TS schrieb:
> Michael B. schrieb:
>
>> Weigerung, es richtig zu machen ?
>
> Und Globale Variabeln sind nicht übersichtlich. Und ganz sicher nicht
> umbedingt richtig!

Da spricht jemand mit jahrzehntelanger Erfahrung in der 
Mikrocontrollerpogrammierung....

(findest du das nicht selbst ein bischen peinlich ?)

von vn nn (Gast)


Lesenswert?

TS schrieb:
> Mit Globalen Variabeln würde dies ja ohne
> probleme gehen aber möchte diese nicht verwenden, damit ich die
> übersicht über die Einzelnen Variabeln besitze.

Dafür gibt es in C struct und static, damit schafft man Übersicht und 
reduziert die Sichtbarkeit von Variablen. Fazit: C-Grundlagen lernen. 
Oder gleich C++. Nicht einach nur Code zusammenkopieren.

von W.S. (Gast)


Lesenswert?

TS schrieb:
> Guten Tag ich habe einen i2C Slave..

So unstrukturiert, wie du dein Anliegen vorbringst, scheint auch dein 
Code zu sein.

Also denke dir ein Protokoll aus, also ein Format, in welchem deine 
Daten über das Interface gehen sollen.

Dazu guck dir an, wie es andere I2C-Schaltkreise denn so machen.

Zumeist sieht das so aus, daß es als erstes eine Art Statusregister 
gibt, wo der Master sehen kann, ob du überhaupt was für ihn hast. Dann 
diverse Datenregister, getrennt für Senden und Empfangen. Das sind 
logischerweise GLOBALE Daten, was denn sonst!

Denke auch daran, daß der Master jederzeit jede Verbindung von sich aus 
beenden kann. Das hat Einfluß darauf, wie du als Slave empfangene Daten 
behandeln mußt. Ob und was du puffern mußt, hängt von deiner Art der 
Anwendung ab.

Also immer an die Olsenbande denken:
1. Egon macht einen Plan,
2. Egon hat den Plan - und zwar fertig
3. Nun werden die Zutaten beschafft
4. Jetzt erst wird mit dem Programmieren begonnen

So etwa geht das.

W.S.

von Purzel H. (hacky)


Lesenswert?

So eine funktion im Interrupt .. ist eher ganz schlecht. Sowas loest man 
mit einer Zustandsmaschine.

von TS (Gast)


Lesenswert?

Michael B. schrieb:
> TS schrieb:
>> Michael B. schrieb:
>>
>>> Weigerung, es richtig zu machen ?
>>
>> Und Globale Variabeln sind nicht übersichtlich. Und ganz sicher nicht
>> umbedingt richtig!
>
> Da spricht jemand mit jahrzehntelanger Erfahrung in der
> Mikrocontrollerpogrammierung....
>
> (findest du das nicht selbst ein bischen peinlich ?)

Also peinlich ist wenn man denkt Globale Variabeln überall einzusetzen. 
Wenn du jetzt sagst,dass es Übersichtlicher sei dann solltest du dich 
selbst fragen wiso das du überhaupt dir erlaubst deinen Mund 
aufzumachen. Ich will ja sehen wen ich dir ein Programm erstelle, wo nur 
Globale Variabeln besitzt und 100te von Parametern ausgetauscht werden, 
das du noch den überblich behältst wo die Variabel sich gerade verändert 
im Programm oke! Aber ist ja übersichtlich stimmt ganz vergessen

Beitrag #5644903 wurde von einem Moderator gelöscht.
von Theor (Gast)


Lesenswert?

TS schrieb:
> Michael B. schrieb:
>> TS schrieb:
>>> Michael B. schrieb:
>>>
>>>> Weigerung, es richtig zu machen ?
>>>
>>> Und Globale Variabeln sind nicht übersichtlich. Und ganz sicher nicht
>>> umbedingt richtig!
>>
>> Da spricht jemand mit jahrzehntelanger Erfahrung in der
>> Mikrocontrollerpogrammierung....
>>
>> (findest du das nicht selbst ein bischen peinlich ?)
>
> Also peinlich ist wenn man denkt Globale Variabeln überall einzusetzen.
> ...

Bleiben wir doch ganz ruhig und freundlich.

Es sagt ja keiner dass Du überall globale Variablen einsetzen sollst.
Nur, dass in diesem Fall einfach nicht anders geht.

Ein struct geht auch. Es hat Vorteile wegen der Übersicht. Es erfordert 
aber dennoch wenigstens diese eine Variable, die den struct-Typ hat, als 
globale Variable.

von Amateur (Gast)


Lesenswert?

Es ist eigenartig, aber Grunde genommen kann man, in einer 
Unterbrechung, machen was man will. So man die Gültigkeit einiger 
Variablen beachtet.

... aber eigentlich sollte man es nicht machen.

Es sind fast immer die gleichen Gründe, die dagegen sprechen einfach 
irgendwelche Funktionen aufzurufen.
- Keine Parameterübergabe.
- Keine Kontrolle darüber wann was gemacht wird.
- Keine Übersicht über das zeitliche Verhalten. Bis zum Stacküberlauf.
- Kaum noch Debugmöglichkeiten.

Übrigens: Selbst wenn es 1000 Mal gut geht, heißt das immer noch nicht, 
dass es beim 1001-ten Mal auch läuft. Oft hängt die Laufzeit einer 
Funktion, von den zu verarbeitenden Werten ab. Nach meiner Meinung sind 
hier Fließkommazahlen am schlechtesten vorhersehbar.

von JGP (Gast)


Lesenswert?

TS schrieb:
> Wenn du jetzt sagst,dass es Übersichtlicher sei dann solltest du dich
> selbst fragen wiso das du überhaupt dir erlaubst deinen Mund
> aufzumachen. Ich will ja sehen wen ich dir ein Programm erstelle, wo nur
> Globale Variabeln besitzt und 100te von Parametern ausgetauscht werden,
> das du noch den überblich behältst wo die Variabel sich gerade verändert
> im Programm oke! Aber ist ja übersichtlich stimmt ganz vergessen

Du hast völlig recht, globale Variablen sind nur zu verwenden, wenn es 
gar nicht anders geht. Wer darüber herzieht, ist der, der von 
strukturierter Programmierung nichts versteht.

Es gibt hier aber Leute, die warten nur auf darauf, dass irgend etwas 
"anders" ist. Damit sie sich auf die Schreiber stürzen können wie die 
Geier. Einfach ignorieren. Solche Leute sind am allerwenigsten vom Fach. 
Denn sonst hätten sie ja Arbeit, und wären nicht (den ganzen Tag) in 
Foren. Klar, oder :D

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.