Hilfe bei Zeiger erstellen.

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Benutzeravatar
Maik81SE
Beiträge: 308
Registriert: Fr 30. Sep 2011, 14:07
OS, Lazarus, FPC: Debian 12 (L 3.0.0.3 FPC 3.2.2); Windows 10 (L 3.99.0.0 FPC 3.2.0)
CPU-Target: x86-64; arm; avr
Wohnort: Lübeck
Kontaktdaten:

Hilfe bei Zeiger erstellen.

Beitrag von Maik81SE »

Moin zusammen,

Leider komme ich im Zuge meines Projektes zu dem Punkt, der mit schon immer geraut hat und welche ich dadurch auch möglichst lange auf ieine Art und Weise umgangen habe.
Pointer&Zeiger

ich habe hier nun eine function auf den Zettel bekommen, welche ich C geschrieben wurde.
Das eigentlich auch nicht das Problem, damit kann ich leben, wo ich aber in's schleudern kommen ich der hier aufgeführte usi_onReceiverPtr.
im Orginal code ist dies weder in der .c noch in der entsprechenden .h definiert.

Code: Alles auswählen

#define USI_RECEIVE_CALLBACK() \
{ \
    if (usi_onReceiverPtr) \
    { \
        if (usiTwiDataInReceiveBuffer()) \
        { \
            usi_onReceiverPtr(usiTwiAmountDataInReceiveBuffer()); \
        } \
    } \
}
ebenso kommt mit auch der

Code: Alles auswählen

if(_onTwiDataRequest) _onTwiDataRequest();
Aufruf nicht ganz koscher vor, oder ist es normal, das man einen Pointer abfragt und sich neu zuweist?

Code: Alles auswählen

void (*_onTwiDataRequest)(void);

ISR( USI_OVERFLOW_VECTOR )
{

  switch ( overflowState )
  {

    // Address mode: check address and send ACK (and next USI_SLAVE_SEND_DATA) if OK,
    // else reset USI
    case USI_SLAVE_CHECK_ADDRESS:
      if ( ( USIDR == 0 ) || ( ( USIDR >> 1 ) == slaveAddress) )
      {
         // callback
         if(_onTwiDataRequest) _onTwiDataRequest();
         if ( USIDR & 0x01 )
        {
          overflowState = USI_SLAVE_SEND_DATA;
        }
        else
        {
          overflowState = USI_SLAVE_REQUEST_DATA;
        } // end if
        SET_USI_TO_SEND_ACK( );
      }
      else
      {
        SET_USI_TO_TWI_START_CONDITION_MODE( );
      }
      break;

    // Master write data mode: check reply and goto USI_SLAVE_SEND_DATA if OK,
    // else reset USI
    case USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA:
      if ( USIDR )
      {
        // if NACK, the master does not want more data
        SET_USI_TO_TWI_START_CONDITION_MODE( );
        return;
      }
      // from here we just drop straight into USI_SLAVE_SEND_DATA if the
      // master sent an ACK

    // copy data from buffer to USIDR and set USI to shift byte
    // next USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA
    case USI_SLAVE_SEND_DATA:
      USI_REQUEST_CALLBACK();
      // Get data from Buffer
      if ( txHead != txTail )
      {
        txTail = ( txTail + 1 ) & TWI_TX_BUFFER_MASK;
        USIDR = txBuf[ txTail ];
      }
      else
      {
        // the buffer is empty
        SET_USI_TO_READ_ACK( ); // This might be neccessary sometimes see http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=805227#805227
        SET_USI_TO_TWI_START_CONDITION_MODE( );
        return;
      } // end if
      overflowState = USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA;
      SET_USI_TO_SEND_DATA( );
      break;

    // set USI to sample reply from master
    // next USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA
    case USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA:
      overflowState = USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA;
      SET_USI_TO_READ_ACK( );
      break;

    // Master read data mode: set USI to sample data from master, next
    // USI_SLAVE_GET_DATA_AND_SEND_ACK
    case USI_SLAVE_REQUEST_DATA:
      overflowState = USI_SLAVE_GET_DATA_AND_SEND_ACK;
      SET_USI_TO_READ_DATA( );
      break;

    // copy data from USIDR and send ACK
    // next USI_SLAVE_REQUEST_DATA
    case USI_SLAVE_GET_DATA_AND_SEND_ACK:
      // put data into buffer
      // Not necessary, but prevents warnings
      rxHead = ( rxHead + 1 ) & TWI_RX_BUFFER_MASK;
      rxBuf[ rxHead ] = USIDR;
      // next USI_SLAVE_REQUEST_DATA
      overflowState = USI_SLAVE_REQUEST_DATA;
      SET_USI_TO_SEND_ACK( );
      break;

  } // end switch

} // end ISR( USI_OVERFLOW_VECTOR )
Wenn sich jemand mal die komplette funktion anschauen will die hängt bei.
Dateianhänge
Lib_TWI_USI_Slave_EEProm_1v3.7z
(9.26 KiB) 65-mal heruntergeladen

Code: Alles auswählen

label.caption:= 'gnublin.no-ip.info'
Debian 12 (L 3.0.0.3 FPC 3.2.2);
windows 10 (L 3.99.0.0 FPC 3.2.0)

sstvmaster
Beiträge: 576
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.2.6
CPU-Target: 32+64bit
Wohnort: Dresden

Re: Hilfe bei Zeiger erstellen.

Beitrag von sstvmaster »

Maik81SE hat geschrieben:
Fr 22. Jan 2021, 04:51
...
im Orginal code ist dies weder in der .c noch in der entsprechenden .h definiert.
...
Ist doch hier in Zeile 53 definiert: https://github.com/watterott/Arduino-Li ... WI_Slave.h
LG Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

PascalDragon
Beiträge: 829
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Hilfe bei Zeiger erstellen.

Beitrag von PascalDragon »

Maik81SE hat geschrieben:
Fr 22. Jan 2021, 04:51
ich habe hier nun eine function auf den Zettel bekommen, welche ich C geschrieben wurde.
Das eigentlich auch nicht das Problem, damit kann ich leben, wo ich aber in's schleudern kommen ich der hier aufgeführte usi_onReceiverPtr.
im Orginal code ist dies weder in der .c noch in der entsprechenden .h definiert.
sstvmaster hat es zwar schon erwähnt, aber allein auf Grund der Tatsache, dass usi_onReceiverPtr als Funktion genutzt wird, ist es letztlich in FPC als Funktionsvariable zu übersetzen:

Code: Alles auswählen

var
  usi_onReceiverPtr: procedure(... { was auch immer usiTwiAmountdataInReceiverBuffer() zurück gibt });
Maik81SE hat geschrieben:
Fr 22. Jan 2021, 04:51
ebenso kommt mit auch der

Code: Alles auswählen

if(_onTwiDataRequest) _onTwiDataRequest();
Aufruf nicht ganz koscher vor, oder ist es normal, das man einen Pointer abfragt und sich neu zuweist?
Das ist keine Zuweisung, das ist einfach nur die Prüfung und der darauf folgende Aufruf einer Funktionsvariable:

Code: Alles auswählen

if Assigned(_onTwiDataRequest) then
  _onTwiDataRequest();
FPC Compiler Entwickler

Benutzeravatar
Maik81SE
Beiträge: 308
Registriert: Fr 30. Sep 2011, 14:07
OS, Lazarus, FPC: Debian 12 (L 3.0.0.3 FPC 3.2.2); Windows 10 (L 3.99.0.0 FPC 3.2.0)
CPU-Target: x86-64; arm; avr
Wohnort: Lübeck
Kontaktdaten:

Re: Hilfe bei Zeiger erstellen.

Beitrag von Maik81SE »

sstvmaster hat geschrieben:
Fr 22. Jan 2021, 08:02

Ist doch hier in Zeile 53 definiert: https://github.com/watterott/Arduino-Li ... WI_Slave.h
mit anderen Worten, auch wenn man OHNE Arduino arbeitet ist man besser beraten, diese Libs bevorzugt zu nehmen? denn in meiner usiTwISlave.h ein komblett anderer code.

Code: Alles auswählen

#ifndef _USI_TWI_SLAVE_H_
#define _USI_TWI_SLAVE_H_

//##################################################################### includes

#include <stdbool.h>

//################################################################### prototypes

void    usiTwiSlaveInit(uint8_t ownAddress);	// send slave address

//#################################################################### variables

#define buffer_size 16						     //in bytes (2..254), change ONLY here!!!!!


volatile uint8_t rxbuffer[buffer_size];         // Buffer to write data received from the master
volatile uint8_t txbuffer[buffer_size];			// Transmission buffer to be read from the master
volatile uint8_t buffer_adr; 					// Virtual buffer address register


#if 	(buffer_size > 254)
		#error Buffer to big! Maximal 254 Bytes.

#elif 	(buffer_size < 2)
		#error Buffer to small! mindestens 2 Bytes!
#endif

//##############################################################################

#endif  // ifndef _USI_TWI_SLAVE_H_
und sowas kann nur jeden in's schleudern bringen, selbst erfahrenere würde dann schreien.

Code: Alles auswählen

label.caption:= 'gnublin.no-ip.info'
Debian 12 (L 3.0.0.3 FPC 3.2.2);
windows 10 (L 3.99.0.0 FPC 3.2.0)

PascalDragon
Beiträge: 829
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Hilfe bei Zeiger erstellen.

Beitrag von PascalDragon »

Maik81SE hat geschrieben:
Fr 22. Jan 2021, 14:12
mit anderen Worten, auch wenn man OHNE Arduino arbeitet ist man besser beraten, diese Libs bevorzugt zu nehmen? denn in meiner usiTwISlave.h ein komblett anderer code.
Was auch nicht überraschend ist, da es eben komplett verschiedener Code ist, der halt letztlich das gleiche Gerät bedient. Ich sehe in deinem angehängten Code zum Beispiel nirgendwo das if(_onTwiDataRequest) _onTwiDataRequest(), das du in dem großen Codeblock zitiert hast.
Was für nen Code nutzt du nun also?
FPC Compiler Entwickler

Benutzeravatar
Maik81SE
Beiträge: 308
Registriert: Fr 30. Sep 2011, 14:07
OS, Lazarus, FPC: Debian 12 (L 3.0.0.3 FPC 3.2.2); Windows 10 (L 3.99.0.0 FPC 3.2.0)
CPU-Target: x86-64; arm; avr
Wohnort: Lübeck
Kontaktdaten:

Re: Hilfe bei Zeiger erstellen.

Beitrag von Maik81SE »

PascalDragon hat geschrieben:
Fr 22. Jan 2021, 14:36
Was auch nicht überraschend ist, da es eben komplett verschiedener Code ist, der halt letztlich das gleiche Gerät bedient. Ich sehe in deinem angehängten Code zum Beispiel nirgendwo das if(_onTwiDataRequest) _onTwiDataRequest(), das du in dem großen Codeblock zitiert hast.
Was für nen Code nutzt du nun also?
Letzteren, das ich auch der einzige, den ich zZ bei mir auf meinem Leptop laufen habe...
PascalDragon hat geschrieben:
Fr 22. Jan 2021, 09:35

Code: Alles auswählen

var
  usi_onReceiverPtr: procedure(... { was auch immer usiTwiAmountdataInReceiverBuffer() zurück gibt });
und genau dem mit komme ich iwie in's schleudern.
Procedure als var?!

bin zwar schon das öfteren darüber in etlichen Tuts gelandet, aber Näher ich da NIE jemand eingegangen...

Code: Alles auswählen

label.caption:= 'gnublin.no-ip.info'
Debian 12 (L 3.0.0.3 FPC 3.2.2);
windows 10 (L 3.99.0.0 FPC 3.2.0)

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1435
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Hilfe bei Zeiger erstellen.

Beitrag von fliegermichl »

Maik81SE hat geschrieben:
Fr 22. Jan 2021, 14:50
und genau dem mit komme ich iwie in's schleudern.
Procedure als var?!
Ja, das ist eine sogenannte Prozedur oder Funktionsvariable. In dieser kann man die Adresse einer Procedur oder Funktion speichern. Wenn man das getan hat, dann kann man diese auch aufrufen.

Code: Alles auswählen

type
 TRechne = function (op1, op2 : integer) : integer;
Diese Deklaration definiert erst einmal ganz allgemein einen Typ einer Funktion die zwei Integer Parameter bekommt und ein Integer Ergebnis zurück liefert.
diesen Typ kann man dann einer Variablen zuweisen:

Code: Alles auswählen


function plus(op1, op2 : integer) : integer;
begin
 Result := op1 + op2;
end;

function minus(op1, op2 : integer) : integer;
begin
 Result := op1 - op2;
end;

procedure Machwas(operation : char; op1, op2 : integer);
var Rechne : TRechne;
begin
 Rechne := nil;
 case operation of
  '+' : Rechne := @plus;
  '-' : Rechne := @minus;
 end;
 
 if Rechne <> nil then writeln(Rechne(op1, op2));
end;
Das ist jetzt ein etwas unsinniges Beispiel, verdeutlicht aber die Procedurvariable

wp_xyz
Beiträge: 4885
Registriert: Fr 8. Apr 2011, 09:01

Re: Hilfe bei Zeiger erstellen.

Beitrag von wp_xyz »

fliegermichl hat geschrieben:
Fr 22. Jan 2021, 15:34
Das ist jetzt ein etwas unsinniges Beispiel
Überhaupt nicht, sondern in sehr sinnvolles Beispiel, das genau zeigt worum es geht.

Stellt dir vor du hast zwei riesige Arrays und musst diese mit einer Operation miteinander verknüpfen, nämlich elementweise addieren oder elementweise subtrahieren. Die naheliegende Lösung ist, die Arrays Element für Element zu durchlaufen mit einem case zu entscheiden ob "operation" '+' ist oder '-' und dann dementsprechend die Element zu addieren oder zu subtrahieren. Da in dieser Schleife nicht viel passiert, ist anzunehmen, dass ein großer Teil der Rechenzeit von dem "case" verbraten wird. Stattdessen ist es schlauer eine Prozedurvariable einzuführen und das "case" vor die Schleife zu stellen, wobei das "case" dieser Prozedurvariablen entsprechend entweder die Addier- oder die Subtraktions-Funktion zuweist. In der Schleife selbst ruft man dann jeweils die Prozedurvariable auf und kann sich das "case" in der Schleife sparen.

Nach dem gleichen Prinzip funktionieren übrigen die Events von Lazarus.,

Benutzeravatar
Maik81SE
Beiträge: 308
Registriert: Fr 30. Sep 2011, 14:07
OS, Lazarus, FPC: Debian 12 (L 3.0.0.3 FPC 3.2.2); Windows 10 (L 3.99.0.0 FPC 3.2.0)
CPU-Target: x86-64; arm; avr
Wohnort: Lübeck
Kontaktdaten:

Re: Hilfe bei Zeiger erstellen.

Beitrag von Maik81SE »

fliegermichl hat geschrieben:
Fr 22. Jan 2021, 15:34
Maik81SE hat geschrieben:
Fr 22. Jan 2021, 14:50
und genau dem mit komme ich iwie in's schleudern.
Procedure als var?!
Ja, das ist eine sogenannte Prozedur oder Funktionsvariable. In dieser kann man die Adresse einer Procedur oder Funktion speichern. Wenn man das getan hat, dann kann man diese auch aufrufen.

Code: Alles auswählen

type
 TRechne = function (op1, op2 : integer) : integer;
Diese Deklaration definiert erst einmal ganz allgemein einen Typ einer Funktion die zwei Integer Parameter bekommt und ein Integer Ergebnis zurück liefert.
diesen Typ kann man dann einer Variablen zuweisen:

Code: Alles auswählen


function plus(op1, op2 : integer) : integer;
begin
 Result := op1 + op2;
end;

function minus(op1, op2 : integer) : integer;
begin
 Result := op1 - op2;
end;

procedure Machwas(operation : char; op1, op2 : integer);
var Rechne : TRechne;
begin
 Rechne := nil;
 case operation of
  '+' : Rechne := @plus;
  '-' : Rechne := @minus;
 end;
 
 if Rechne <> nil then writeln(Rechne(op1, op2));
end;
Das ist jetzt ein etwas unsinniges Beispiel, verdeutlicht aber die Procedurvariable
Lieber ein Unsinniges Beispiel, indemm JEDER versteht, um was es geht als eine Hochgeschrieben Text, den keiner Versteht...

Code: Alles auswählen

label.caption:= 'gnublin.no-ip.info'
Debian 12 (L 3.0.0.3 FPC 3.2.2);
windows 10 (L 3.99.0.0 FPC 3.2.0)

Antworten