Forum: Mikrocontroller und Digitale Elektronik folgender code nicht compilierbar


von Timo P. (latissimo)


Lesenswert?

Fehlermeldung: c:65: error: lvalue required as left operand of 
assignment

1
typedef union 
2
{ unsigned int i;
3
  float f;
4
} value;
5
6
char s_write_byte(unsigned char value)
7
//----------------------------------------------------------------------------------
8
// writes a byte on the Sensibus and checks the acknowledge 
9
{ 
10
  unsigned char i,error=0;  
11
  for (i=0x80;i>0;i/=2)             //shift bit for masking
12
  { 
13
65   if (i & value) DATA=1;          //masking value with i , write to 
14
     else DATA=0;

von Klaus (Gast)


Lesenswert?

Meine Glaskugel sagt mir, dass DATA keine Variable ist, der du was 
zuweisen kannst.

Aber ich verrate dir mal ein Geheimnis: Glaskugeln gibts nur bei Harry 
Potter und leider nicht im richtigen Leben. Wie wärs also, wenn du uns 
mit einem vollständigen Quellcode versorgst?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> 65   if (i & value) DATA=1;          //masking value with i , write to

Vielleicht meinst du

65   if (i & value.i) DATA=1;          //masking value with i , write to

jedenfalls kannst du nicht "pur" auf die Union value zugreifen

von Timo P. (latissimo)


Angehängte Dateien:

Lesenswert?

#define DATA PORTA & (1<<1)

verwendung ist DATA = 1;

sollte doch eigentlich gehen oder? AStudio 4 mit Winavr


(im anhang wäre der ganze code)

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Timo P. schrieb:
> #define DATA PORTA & (1<<1)
>
> verwendung ist DATA = 1;
>
> sollte doch eigentlich gehen oder? AStudio 4 mit Winavr

Nö. Bitmanipulation

von Karl H. (kbuchegg)


Lesenswert?

Timo P. schrieb:
> #define DATA PORTA & (1<<1)
>
> verwendung ist DATA = 1;
>
> sollte doch eigentlich gehen oder?


Aha.
Dann spiel doch einfach mal Präprozessor

Aus
1
  DATA = 1;

wird
1
  PORTA & (1<<1) = 1;

Und jetzt erklär mit mal, was der Compiler da draus deiner Meinung nach 
machen soll.

von Timo P. (latissimo)


Lesenswert?

@ stefan, die union ist zu vergessen, hierbei geht es um value als 
parameter der funktion. dies ist ein Byte, wo man einzelne bits 
ausmaskiert. Diese Variable(zu versendende Daten) heiß zufälligerweise 
auch "value".

mein prob ist glaube ich die verwendung von dem define DATA:

#define DATA PORTA & (1<<1)
verwendung ist:
 DATA = 1;        // das geht irgendwie nicht :(

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Timo P. schrieb:

> @ stefan, die union ist zu vergessen, hierbei geht es um value als
> parameter der funktion. dies ist ein Byte, wo man einzelne bits
> ausmaskiert. Diese Variable(zu versendende Daten) heiß zufälligerweise
> auch "value".

Ah. Habe ich übersehen.

von Timo P. (latissimo)


Lesenswert?

der compiler macht doch aus (1<<1) ne 00000010 wenn er diese mit rem 
Register PORTA verundet, dann bleibt doch das einzelne Bit aus PORTA 
über oder?

von Karl H. (kbuchegg)


Lesenswert?

Timo P. schrieb:

> mein prob ist glaube ich die verwendung von dem define DATA:
>
> #define DATA PORTA & (1<<1)
> verwendung ist:
>  DATA = 1;        // das geht irgendwie nicht :(

Da hast du recht.
So wird das nichts.

von Timo P. (latissimo)


Lesenswert?

Verdammt, wie muss denn mein define aussehen?
Bei Infineon und Microvision gab es einen schönen sbit befehl, der hat 
genau das gemacht, ein Bit ausmaskieren und einen handelbaren namen 
dafür vergeben.

von Karl H. (kbuchegg)


Lesenswert?

Timo P. schrieb:
> der compiler macht doch aus (1<<1) ne 00000010 wenn er diese mit rem
> Register PORTA verundet, dann bleibt doch das einzelne Bit aus PORTA
> über oder?

Ein Bit bleibst schon einmal gar nicht übrig, weil es das in C so nicht 
gibt. Die kleinste Einheit, die für dich manipulierbar ist, ist ein Byte 
in Form eines unsigned char.

Ein einzelnes Bit ist so nicht adressierbar (ausser man macht es mit 
Bitfeldern in einer struct)

von Mark B. (markbrandis)


Lesenswert?

Timo P. schrieb:
> #define DATA PORTA & (1<<1)
>
> verwendung ist DATA = 1;
>
> sollte doch eigentlich gehen oder?

Nein. Das kann nicht gehen. DATA ist keine Variable, man kann ihr keinen 
Wert zuweisen.

Vielleicht sollte es PORTA anstatt DATA heißen?
Oder

#define DATA PORTA

würde eventuell auch Sinn ergeben.

von Karl H. (kbuchegg)


Lesenswert?

Timo P. schrieb:
> Verdammt, wie muss denn mein define aussehen?
> Bei Infineon und Microvision gab es einen schönen sbit befehl, der hat
> genau das gemacht, ein Bit ausmaskieren und einen handelbaren namen
> dafür vergeben.

Und?

Warum baust du dir dann nicht einfach ein sbit nach?
Du bist Programmierer. Manchmal muss man sich eben seine Werkzeuge 
selber machen, wenn die vorgefertigen nicht ausreichen.

Ist doch nicht schwer
1
#define SBIT( wo, bit )    (wo) |= ( 1 << (bit) )
2
#define CBIT( wo, bit )    (wo) &= ~( 1 << (bit) )
3
4
char s_write_byte(unsigned char value)
5
//----------------------------------------------------------------------------------
6
// writes a byte on the Sensibus and checks the acknowledge 
7
{ 
8
  unsigned char i,error=0;  
9
  for (i=0x80;i>0;i/=2)             //shift bit for masking
10
  { 
11
    if (i & value)
12
      SBIT( DATA_PORT, DATA_BIT );
13
    else
14
      CBIT( DATA_PORT, DATA_BIT );
15
  }
16
}

von Timo P. (latissimo)


Lesenswert?

Jo hätt ich auch selbst machen können. Manchmal kommt man halt nicht 
selbst drauf. Im übrigen bin ich halt noch Anfänger, der zwar schon 
einiges an Grundwissen hat, aber anscheinend einiges auch noch nicht...

Danke auf jeden Fall!

von Timo P. (latissimo)


Lesenswert?

Sinn der sache wäre doch, eine define Zeile zu verwenden und dann
via "definetes wort" = 0; oder =1; schreiben zu können,

anstatt folgenden langen code verwenden zu müssen:

#define SBIT( wo, bit )    (wo) |= ( 1 << (bit) )
#define CBIT( wo, bit )    (wo) &= ~( 1 << (bit) )
#define DATA_PORT          PORTA
#define DATA_BIT           5

und als Verwendung muss ich zu allem Übel noch zwei verschiedene Zeilen 
nutzen um ein Bit zu setzen/rücksetzen:

SBIT( DATA_PORT, DATA_BIT ); oder:
CBIT( DATA_PORT, DATA_BIT );


Ich wünsche mir ein define, welches mir folgende Verwendung ermöglicht:

DATA = 1; oder DATA = 0; Und damit wird ein vorher (auf welche Weise?!?) 
defineter Portpin getoggelt.

von Timo P. (latissimo)


Lesenswert?

@Mark Brandis:

nein PORTA sollte nicht anstelle von DATA stehen, weil ich ja nicht den 
ganzen PORT auf Hih stellen will, sondern lediglich einen einzigen PIN.

Wenn ich DATA als PORTA definen würde könnte ich ja problemlos den PORT 
auf 0xFF oder 0x00 setzen. Aber wie gesagt, es geht um PIN-Toggeln

und zwar durch die Verwendung:

DATA = 0;
DATA = 1;

von Karl H. (kbuchegg)


Lesenswert?

Timo P. schrieb:

> Ich wünsche mir ein define, welches mir folgende Verwendung ermöglicht:

Das kriegst man mit einem simplen #define nicht hin.
Dazu muss man sich im Kern eine Struktur mit einem Bitfeld bauen, dann 
erledigt der Compiler den Schweinkram.

PeDa verwendet gerne so etwas. Aber wie die Details dazu aussehen, hab 
ich auch nicht auswändig im Kopf.

von Timo P. (latissimo)


Lesenswert?

Da bisher keiner eine Lösung hatte,

werde ich ausweichen und folgenden Umweg gehen müssen:

#define DATA_PORT PORTA
#define DATA_PIN  (1<<5)


und nun JEDE Verwendung im GESAMTEN CODE :

von DATA = 1; in :
DATA_PORT |= DATA_PIN;

und :

von DATA = 0; in :
DATA_PORT &=~DATA_PIN;

ändern. :( Schade, dass es anscheinend nicht anders geht. Zum Glück gibt 
es in allen editoren eine find+replace funktion......

DANKE trotzdem für die rege beteiligung an die Leute, die Anregungen 
hatten

Gruß timo

von Karl H. (kbuchegg)


Lesenswert?

So müsste es klappen.
Wenn man im DATA Makro anstelle der Konstanten für die Bitdefinition 
selbst wieder Makros benutzen will, müsste man noch einen Umweg gehen.
1
struct EinzelBit
2
{
3
  uint8_t Bit0 : 1;
4
  uint8_t Bit1 : 1;
5
  uint8_t Bit2 : 1;
6
  uint8_t Bit3 : 1;
7
  uint8_t Bit4 : 1;
8
  uint8_t Bit5 : 1;
9
  uint8_t Bit6 : 1;
10
  uint8_t Bit7 : 1;
11
};
12
13
#define SBIT( p, b )   ( ((struct EinzelBit*)(p))->Bit##b )
14
15
#define DATA  SBIT( PORTA, 1 )
16
17
int main()
18
{
19
  DATA = 1;
20
}

von Timo P. (latissimo)


Lesenswert?

Ok Verwendung ist möglich!
RESPEKT an Kbuchegg

Wie kann ich denn nop() mit winavr nachbilden? Gerne möchte ich mal 
wissen, wie nop() überhaupt aufgebaut ist, ob es wirklich ein 
Funktionsaufruf ist und was er tut.(Oder wie er nichts tut)

von (prx) A. K. (prx)


Lesenswert?

Ungefähr so:
1
static __inline void nop(void) { __asm__ volatile ("nop"); }

M.a.W: Das ist exakt der Maschinenbefehl NOP. Inline, kein 
Funktionsaufruf. Und was dieser Befehl macht steht in aller 
Ausführlichkeit in Atmels Dokumentation.

von Timo P. (latissimo)


Lesenswert?

Ahso also macht die Funktion einen Taktzyklus lang "nix" ;)

hier steht, dass dies eine genaue delay möglichkeit ist. Wird sie denn 
oft als delay verwendet, auch wenn man timer benutzen kann?!?

von (prx) A. K. (prx)


Lesenswert?

Ein Timer für nur 1-2 Takte zu verwenden ist etwas schwierig.

von Timo P. (latissimo)


Lesenswert?

A. K. schrieb:
> Ungefähr so:
>
1
> static __inline void nop(void) { __asm__ volatile ("nop"); }
2
>
>

wenn ich das kompiliere, meckert der rum, elf file does not exist!
kommentiere ich die oben genannte zeile aus, dann kompiliert der zwar, 
aber kennt halt die nop()`s nicht...

von (prx) A. K. (prx)


Lesenswert?

Timo P. schrieb:

> wenn ich das kompiliere, meckert der rum, elf file does not exist!

Dann muss er aber vorher schon gemeckert haben.

von Timo P. (latissimo)


Lesenswert?

Klar vorher hat er gemeckert, weil er die nop() funktionen nicht kannte.

mit der inline zeile habe ich aber als einzige Fehlermeldung die oben 
angegebene, anstatt Fehler im Code zu sehen, wenn ich z.B. bewusst einen 
syntaxfehler mache, semikolon weg oder so, dann sehe ich das nicht in 
den fehlern, soweit kommt der garnicht.

also scheint die zeile:

static __inline void nop(void) { _asm_ volatile ("nop"); }

für mich quatsch zu sein.

von (prx) A. K. (prx)


Lesenswert?

"Vorher" meint: weiter vorne im Protokoll des Compilers. ELF ist das 
Äquivalent des EXE-Files von PCs, d.h. er muss schon in den Zeilen davor 
grösszügig darauf vezichtet haben, ein solches File überhaupt zu 
erzeugen. Und das sollte einen Grund haben.

von Timo P. (latissimo)


Lesenswert?

A. K. schrieb:

> Und das sollte einen Grund haben.

Da hast du wohl Recht mit deiner Aussage.....
Ich denke dass diese Inline-Funktion mein Problem ist.

von (prx) A. K. (prx)


Lesenswert?

Timo P. schrieb:

> Da hast du wohl Recht mit deiner Aussage.....
> Ich denke dass diese Inline-Funktion mein Problem ist.

Kann schon sein, aber dann nur in grösserem Zusammenhang, vielleicht 
doppelt definiert, nop als Makro, ... Denn Code wie
1
static __inline void nop(void) { __asm__ volatile ("nop"); }
2
3
int main(void)
4
{
5
        nop();
6
}
frisst wohl jeder GCC anstandslos, egal für welche Maschine.

von Timo P. (latissimo)


Lesenswert?

Winavr mit Astudio habe ich...

geht jedenfalls nicht. :(

von Micha (Gast)


Lesenswert?

>Winavr mit Astudio habe ich...
Dann sollte es ja funktionieren (vorausgesetzt du meinst mit Astudio das 
AVRStudio). Bei mir funktioniert es in dieser Kombination jedenfalls...

von Timo P. (latissimo)


Lesenswert?

AVR Studio    4.14.589
GUI Version    4, 14, 0, 589


und WINAVR 20080610


bei mir gehts nicht :(

von (prx) A. K. (prx)


Lesenswert?

Mach das mal auf der Kommandozeile, also
  avr-gcc -mmcu=atmega8 -Os -c testcode.c

von Micha (Gast)


Lesenswert?

Mit AVRStudio 4.15.623 und WinAVR-20081205 läuft es...

von Timo P. (latissimo)


Lesenswert?

kann man

  nop();

nicht durch :

  variable++;

ersetzen?

Wie viele Taktzyklen benötigt das Inkrementieren einer Variable bei 
einem Atmega-Controller? Soweit ich weiß, war das bei einem PIC 
Controller so, dass 4 FOSC Zyklen einen Befehl ausmachen.
Wie ists Bei ATMEGAs fürs ....++;?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Timo P. schrieb:
> kann man
>
>   nop();
>
> nicht durch :
>
>   variable++;
>
> ersetzen?

Nein.


> Wie viele Taktzyklen benötigt das Inkrementieren einer Variable bei
> einem Atmega-Controller?

Kommt drauf an. Mindestens 0 bis um die 80 Ticks.

Johann

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

Timo P. schrieb:
> AVR Studio    4.14.589
> GUI Version    4, 14, 0, 589
>
>
> und WINAVR 20080610
>
>
> bei mir gehts nicht :(

Leg ein neues Projekt an, such dir einen Mega16 aus und kopiere diesen 
Code in das vom AVR-Studio angelegte Source Code File
1
static __inline void nop(void) { __asm__ volatile ("nop"); }
2
3
int main(void)
4
{
5
        nop();
6
}

dann F7.
Kriegst du eine Fehlermeldung?

(Tu es aber wirklich! Nicht einfach nur sagen "bei mir gehts das nicht", 
weil es in deinem realen Projekt, in dem du das letztendlich einsetzen 
willst, nicht geht. Wir müssen jetzt erst mal aussortieren ob es ein 
Problem in deiner generellen WinAVR/AVR-Studio Konfiguration gibt, oder 
ob das Problem auf dein reales Projekt beschränkt ist)

von Thomas W. (wagneth)


Lesenswert?

@ Johann

Der Compiler Optimiert bei nichtverwendung einfach weg, oder ?
(Variable++;)

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Thomas W. schrieb:
> @ Johann
>
> Der Compiler Optimiert bei nichtverwendung einfach weg, oder ?
> (Variable++;)
Nicht wenn die Variable als 'volatile' markiert ist...

von Karl H. (kbuchegg)


Lesenswert?

Thomas W. schrieb:
> @ Johann
>
> Der Compiler Optimiert bei nichtverwendung einfach weg, oder ?
> (Variable++;)

kommt drauf an.
Wenn die Variable als volatile markiert ist, kann er die Variable nicht 
einfach wegoptimieren.
kommt auch drauf an, was das für eine Variable ist. Eine funktionslokale 
oder filelokale Variable könnte er wegoptimieren. Eine globale Variable 
kann er aber nicht so einfach wegoptimieren.

von Timo P. (latissimo)


Lesenswert?

variable ++ ist ja eine verwendung der variable oder?

mal ne frage, mit ist bekannt, was volatile bedeutet.
ich kenne das nur beim anlegen von variablen, zb:

volatile unsigned char a;

gibt es auch eine möglichkeit einen Codeblock als volatile zu "machen" ?

zb durch irgendeine Präprozessoranweisung? WINAVR?

@ (kbuchegg): ich werde gleich mal ein neues Projekt für nen ATMEGA 
anlegen....

von Timo P. (latissimo)


Lesenswert?

die fehlermeldung, elf file does not exist kommt nicht mehr, wenn ich 
eine funktion auskommentiere. Diese funktion ist komischerweise 
fehlerfrei.

Kann es sein, dass WINAVR ab einer best. Codegröße zumzickt? In diesem 
Projekt habe ich nämlich bisher nur eine C-File, sonst nix....

Was meint ihr? Werde auf jeden Fall mal alles aufspalten in schöne 
main.h und diverse C-Files....

von holger (Gast)


Lesenswert?

>Diese funktion ist komischerweise
>fehlerfrei.

Zeig deinen Code!

>Was meint ihr? Werde auf jeden Fall mal alles aufspalten in schöne
>main.h und diverse C-Files....

Jo, erstmal alles auseinanderreißen und noch mehr Fehler einbauen ;)

von Karl H. (kbuchegg)


Lesenswert?

Timo P. schrieb:

> Kann es sein, dass WINAVR ab einer best. Codegröße zumzickt? In diesem
> Projekt habe ich nämlich bisher nur eine C-File, sonst nix....

Wenn du in deinem Projekt 'bisher nur 1 C-File hast', dann ist klar 
warum die Funktion lcd_clrscr() oder auch alle anderen lcd Funktionen 
nicht gefunden werden.
Die sind in lcd.c drinnen und dieses File muss klarerweise auch mit in 
das Projekt aufgenommen werden.

>
> Was meint ihr? Werde auf jeden Fall mal alles aufspalten in schöne
> main.h und diverse C-Files....

Grundsätzlich eine gute Idee, aber wenn du jetzt schon Schwierigkeiten 
hast, das alles auf die Reihe zu kriegen, solltest du vielleicht etwas 
warten, ehe du dir dein Projekt komplett zerstörst.

von Timo P. (latissimo)


Angehängte Dateien:

Lesenswert?

wenn ich verschiedene C-Files aus einer erzeuge, dann stehen einfach 
einige funktionen in anderen c-files, baue ich damit dann gleich Fehler 
ein?!? Verstehe ich nicht! Das musst du mir mal erklären!!!!!!!!!!

der code ist im Anhang!

vllt. ist ja doch nur die auskommentierte Funktion falsch!

calc_dewpoint() direkt vor main

von holger (Gast)


Lesenswert?

Für welchen Prozessor ist das Programm?
Vieleicht wird der Code einfach nur zu groß.
Bei dem ganzen float Gerechne wäre das kein Wunder.

von Timo P. (latissimo)


Lesenswert?

aus besagter Funktion habe ich folgende Zeilen einzeln auskommentiert:

    logEx=0.66077+7.5*t/(237.3+t)+(log10(h)-2);
  //dew_point = (logEx - 0.66077)*237.3/(0.66077+7.5-logEx);

erst die eine, dann die andere. Wenn eine der Zeilen auskomm. ist, dann 
kann ich den Code kompilieren, Wenn ich jedoch beide zeilen drin habe, 
dann kann ich nicht kompilieren, kein elf file :(

von Timo P. (latissimo)


Lesenswert?

MEGA 32!!

(code war ursprünglich für nen <AT89s53.h>)


AVR Memory Usage
----------------
Device: atmega32
Program:    6220 bytes (19.0% Full)
(.text + .data + .bootloader)

Data:        365 bytes (17.8% Full)
(.data + .bss + .noinit)

diese meldung bek. ich wenn ich calc_dewpoint() auskommentiere die fkt 
und deren Aufruf

von holger (Gast)


Lesenswert?

Mach mal ein #include <math.h>
unter #include "main.h"

Hast du mathlib (-lm) mit in den Linkeroptionen?

von Karl H. (kbuchegg)


Lesenswert?

Wer auch immer diesen Code geschrieben hat, man sollte ihn mit dem 
nassen Fetzen erschlagen!

1
typedef union 
2
{ unsigned int i;
3
  float f;
4
} value;
5
6
7
....
8
9
10
int main()
11
{ value humi_val,temp_val;
12
13
  ...
14
15
    { humi_val.f=(float)humi_val.i;                   //converts integer to float
16
      temp_val.f=(float)temp_val.i;                   //converts integer to float
17
18
    ...
19
}

Da ist der Compiler ganz einfach abgestürzt. Sollte eigentlich nicht 
sein, aber man könnte das an gcc als Bugreport weitergeben.

1
//----------------------------------------------------------------------------------
2
void main()
3
//----------------------------------------------------------------------------------
4
// sample program that shows how to use SHT11 functions
5
// 1. connection reset 
6
// 2. measure humidity [ticks](12 bit) and temperature [ticks](14 bit)
7
// 3. calculate humidity [%RH] and temperature [?C]
8
// 4. calculate dew point [?C]
9
// 5. print temperature, humidity, dew point  
10
11
{
12
  int   humi_val_i;
13
  int   temp_val_i;
14
15
  float humi_val,temp_val;
16
  double dew_point;
17
  unsigned char error,checksum;
18
  unsigned int i;
19
20
  uinit();
21
  s_connectionreset();
22
  while(1)
23
  { error=0;
24
    error+=s_measure((unsigned char*) &humi_val_i,&checksum,HUMI);  //measure humidity
25
    error+=s_measure((unsigned char*) &temp_val_i,&checksum,TEMP);  //measure temperature
26
    if(error!=0) s_connectionreset();                 //in case of an error: connection reset
27
    else
28
    {
29
    humi_val = humi_val_i;                   //converts integer to float
30
      temp_val = temp_val_i;                   //converts integer to float
31
      calc_sth11(&humi_val,&temp_val);            //calculate humidity, temperature
32
33
      dew_point=calc_dewpoint(humi_val,temp_val); //calculate dew point
34
      sprintf(s,"temp:%5.1fC humi:%5.1f%% dew point:%5.1fC\r\n",(double)temp_val,(double)humi_val,dew_point);
35
      uputs(s);
36
    }
37
    //----------wait approx. 0.8s to avoid heating up SHTxx------------------------------      
38
    for (i=0;i<40000;i++);     //(be sure that the compiler doesn't eliminate this line!)
39
    //-----------------------------------------------------------------------------------                       
40
  }
41
}


und die union value schmeisst du ganz raus.

Und wenn du schon dabei bist, dann korrigierst du auch noch das SBIT 
Makro. Die Warnungen des Compilers sind nicht ohne Grund.
1
#define SBIT( p, b )   ( ((struct EinzelBit*)(&p))->Bit##b )

von Timo P. (latissimo)


Lesenswert?

OH man danke für Antwort.

soll ich:

  dew_point=calc_dewpoint(humi_val,temp_val); //calculate dew point

noch durch:

  dew_point=calc_dewpoint(&humi_val,&temp_val); //calculate dew point

ersetzen??

von Karl H. (kbuchegg)


Lesenswert?

Timo P. schrieb:
> soll ich:
> noch durch:
> ersetzen??

Wenn es dir Spass macht.

Aber denk immer an die erste Grundregel der Optimierung:

* Don't do it

Gefolgt von der 2.ten Grundregel

* Don't do it .... yet



Bring erst mal das Bisherige zum Laufen und teste es, ehe du anfängst 
den Code zu verändern.

von Timo P. (latissimo)


Lesenswert?

ging nur um die Art zu programmieren

funktion mit ....(*...)
und dann aufruf mit

....(&...);

oder funktion mit ...(char ...)
und dann aufruf mit

....(...);

also ob ich pointer nehme oder direkt die ganzen variablen übergebe.

nach meinem wissensstand übergibt man mit einer ganzen variable ihren 
namen, ihren typ, ihren inhalt.

mit zeigern übergibt man doch nur den inhalt, indem man referenziert bzw 
dereferenziert, richtig??

von Karl H. (kbuchegg)


Lesenswert?

Timo P. schrieb:
> ging nur um die Art zu programmieren
>
> funktion mit ....(*...)
> und dann aufruf mit
>
> ....(&...);
>
> oder funktion mit ...(char ...)
> und dann aufruf mit
>
> ....(...);
>
> also ob ich pointer nehme oder direkt die ganzen variablen übergebe.
>
> nach meinem wissensstand übergibt man mit einer ganzen variable ihren
> namen, ihren typ, ihren inhalt.
>
> mit zeigern übergibt man doch nur den inhalt, indem man referenziert bzw
> dereferenziert, richtig??

Halte dich in C an die Regel

*************

Frage: Hat der Aufrufer eine Variable die er an die Funktion übergibt,
       und muss diese Funktion in der Lage sein, diese Variable beim
       Aufrufer zu ändern?

   Ja:   Übergib einen Zeiger
   Nein: Übergib den Wert der Variablen

Zusatzfrage: Wenn nur eine Variable an eine Funktion übergeben wird UND
   die Funktion diese Variable beim Aufrufer ändern können soll:
   Was spricht dagegen, der Funktion KEINEN Pointer zu übergeben sondern
   wie gehabt einen Wert, die Funktion berechnet einen neuen Wert und
   liefert das Ergebnis als Returnwert der Funktion.
   Der Aufrufer muss die Funktion dann so benutzen:  a = foo( a );
   Wenn nichts dagegen spricht, dann löse es über den Returnwert.

****************

Wenn du dieses Schema benutzt, wirst du in den meisten Fällen die 
richtige Entscheidung treffen.

NB: Arrays sind da aussen vor, da Arrays sowieso immer per Pointer auf 
das erste Element übergeben werden. Aber für alles andere kannst du 
dieses Schema benutzen. Einzige Ausnahmen: Strukturen, bei denen eine 
Übergabe per Wert ganz einfach eine teure Operation ist, weil das 
Erzeugen der Kopie sowohl Laufzeit als auch Speicher frisst. Benutze 
dann aber unbedingt einen const-Pointer, damit dir der Compiler 
innerhalb der Funktion auf die Finger klopft, wenn du unzulässigerweise 
unabsichtlich versuchst, den Wert eines Strukturmembers in der Funktion 
zu verändern.

Aber Grundidee ist es immer: Übergib einen Pointer nur dann, wenn du 
musst. Übergibst du per Wert, kann die Funktion in deinen Variablen 
nichts anstellen. Übergibst du aber einen Pointer, kann die Funktion 
beim Aufrufer Variablen verändern wie sie lustig ist. Bewährtes Ziel in 
der Programmierung ist es immer, Änderungen in Variablen so lokal wie 
möglich zu halten (daher wird auch in der Nicht-µC Programmierung das 
Dogma "keine globalen Variablen" ausgegeben), damit Seiteneffekte 
überschaubar bleiben.

von Timo P. (latissimo)


Lesenswert?

Aufruf:
s_measure((unsigned char*) &humi_val_i, &checksum , HUMI);
worauf bezieht sich hier der typecast(unsigned char *) ? Auf alle 
Parameter??


die funktion hat als parameter:
s_measure( unsigned char a*, unsigned char b*, unsigned char c)

also zwei pointer und eine var.

von Karl H. (kbuchegg)


Lesenswert?

Timo P. schrieb:
> Aufruf:
> s_measure((unsigned char*) &humi_val.i,&checksum,HUMI);
> worauf bezieht sich hier der typecast(unsigned char *) ?

Auf   &humi_val.i

also die Adresse von i in der union humi_val


Wobei der ganze Ansatz da schon in die Tonne müsste.
Wenn s_measure sowieso einen int haben will, warum nimmt sie dann nicht 
einfach einen Pointer auf int.


Wie gesagt: Den Programmierer sollte man mit dem nassen Fetzen 
erschlagen.

von Timo P. (latissimo)


Lesenswert?

hm ich hatte die zeile für den funktionsaufruf aus obigem beitrag hier 
reinkopiert, ich habe ihn vorhin geändert(meinen letzten beitrag)

es ist ..._i anstelle von .i, also das element einer union gibt es 
nicht.

von Timo P. (latissimo)


Lesenswert?

ist aus der :
Application Note
Sample Code
von sensirion selbst!
____________________________________________


double dew_point;
float humi_val,temp_val;

sprintf(s,"temp:%5.1f C humi:%5.1f dew point:%5.1fC\r\n",
temp_val,humi_val,dew_point);

Warning vom Compiler:

5.1f expects double ?!? Wieso das denn? f ist für float, oder muss ich 
mir da genauer überlgen, ob 5.1 überhaupt für f möglich ist??

von Karl H. (kbuchegg)


Lesenswert?

Timo P. schrieb:

> 5.1f expects double ?!? Wieso das denn? f ist für float, oder muss ich
> mir da genauer überlgen, ob 5.1 überhaupt für f möglich ist??

Der Code ist grundsätzlich ok, da float an dieser Stelle als double 
übergeben werden muss (weil sprintf eine variadische Funktion ist). Wird 
wahrscheinlich eine Performance Warnung sein.
Du kannst dich an dieser Stelle mit einem "Ist ok Compiler, machs 
einfach"-Cast aus der Äffäre ziehen.

von (prx) A. K. (prx)


Lesenswert?

Meine Version vom SHT11 Code: 
Beitrag "Sensirion SHT11 Code"

von Timo P (Gast)


Lesenswert?

extern int sprintf(char *__s, const char *__fmt, ...);

mehr finde ich nicht zu dieser funktion.

es ist z.b noch eine ansi.h eingebunden, diese finde ich nicht im 
compilerverzeichnis. Für die Verwendung von printf ( so habe ich es 
übers forum mal erfahren) kann man in den jeweiligen 
Projekteigenschaften verschiedene libarys einbinden, je nach wunsch für 
die Fließkommazahlen.

mich würde die sprintf-fkt. interessieren, ob sie wirklich ein double 
als parameter erwünscht

von Karl H. (kbuchegg)


Lesenswert?

Timo P schrieb:

> mich würde die sprintf-fkt. interessieren, ob sie wirklich ein double
> als parameter erwünscht

Hab ich es in diesem Thread schon mal erwähnt?
Wenn ja, egal, ich sage es nochmal:
Du brauchst unbedingt Literatur! Literatur, die dich systematisch durch 
alle die Fallstricke und all das Wissen manövriert, das du benötigst um 
C zu programmieren. Solnage du das nicht systematisch angehst, wird dein 
Wissen immer nur 'Halbwissen sein'. Egal wieviel du frägst.

Zurück zur Frage
sprintf ist eine variadische Funktion.
In diesem Fall gelten in C dieselben Regeln für die nicht im Protoyp 
spezifizierten Paramter, wie sie auch in der Vor-Prototyp-Zeit gegolten 
haben, der Compiler also keinen Protoyp einer Funktion kennt und 
trotzdem die Parameterübergabe in einer halbwegs sicheren Art und Weise 
über die Bühne gehen soll.

* alles was nicht näher spezifiert ist, ist ein int
  Das ist eine der Grundregeln in C.
  Wenn der Compiler eine Funktion nicht kennt, kennt er auch den
  Returntyp der Funktion nicht.
  Er nimmt dann an: Es ist ein int

* ein float wird immer als double übergeben

* alles was kleiner als int ist, wird als int übergeben

* für alles was größer als int ist, ist der Programmierer zuständig.

* speziell bei variadischen Funktionen:
  Es muss einen Mechanismus geben, mit dem die aufgerufene Funktion die
  Anzahl und die Datentypen der übergebenen Argumente feststellen kann.
  C hält sich da raus. Es ist Sache des Programmierers sich dafür
  etwas einfallen zu lassen. Im Falle der printf/scanf Funktionen
  übernimmt der Format-String diese Aufgabe. Die %-Kürzel werden von
  der Funktion ausgewertet um Anzahl und Datentyp der übergebenen
  Argumente festzustellen. Das ist das Einzige was printf/scanf über
  die Datentypen der Argumente weiß! Man sollte daher peinlich darauf
  achten, dass die %-Kürzel auch zu den Argumenten passen.

von Timo P. (latissimo)


Lesenswert?

Karl heinz Buchegger schrieb:

> * ein float wird immer als double übergeben
AHA!
>   Man sollte daher peinlich darauf
>   achten, dass die %-Kürzel auch zu den Argumenten passen.

"Peinlich-genau" das habe ich doch gemacht: 5.1f passt zu meinen 
variablen:



float humi_val,temp_val;

sprintf(s,"temp:%5.1f C humi:%5.1f dew point:%5.1fC\r\n",
temp_val,humi_val,dew_point);

von Karl H. (kbuchegg)


Lesenswert?

Timo P. schrieb:
> Karl heinz Buchegger schrieb:
>
>> * ein float wird immer als double übergeben
> AHA!
>>   Man sollte daher peinlich darauf
>>   achten, dass die %-Kürzel auch zu den Argumenten passen.
>
> "Peinlich-genau" das habe ich doch gemacht: 5.1f passt zu meinen
> variablen:

Ja, ich weiß.
Mir ist ehrlich gesagt auch nicht wirklich klar, warum es da eine 
Warnung gibt. Die Operation ist hier eindeutig definiert unter 
Ausschluss aller möglichen Missverständnisse.

Ich schätze daher, diese Warnung bedeutet mehr oder weniger:
"Du bist dir bewusst, dass dein float an dieser Stelle sowieso wie ein 
double behandelt wird. Wenn es also nur um hier geht, könntest du 
genausogut einen double nehmen"
Es könnte auch sein, dass die Warnung bedeutet:
"Da du hier von einem float ausgehst, musst du dir bewusst sein, dass 
einige der hinteren Nachkommastellen aus den Fingern gesaugt sind. Es 
macht zb keinen Sinn, hier 10 Nachkommastellen anzuzeigen da in einem 
float bei so um die 6 bis 7 Stellen Schluss ist"

Wie gesagt, an dieser Stelle kannst du den Compiler mit einem Cast 
ruhigstellen, indem du die Operation, die der Compiler sowieso macht, in 
diesem Cast ausdrückst.
1
  float humi_val,temp_val;
2
3
  sprintf( s,"temp:%5.1f C humi:%5.1f dew point:%5.1fC\r\n",
4
                  (double)temp_val,
5
                  (double)humi_val,
6
                  (double)dew_point);

damit dokumentierst du dann auch, dass du dir durchaus bewusst bist, 
dass hier implizit eine Konvertierung der float nach double erfolgt 
(erfolgen muss).

von Timo P. (latissimo)


Lesenswert?

Dann werd ich mich wohl damit zufrieden geben müssen.

Besten Dank für die ganze Hilfe!

von Timo P. (latissimo)


Lesenswert?

#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void)
{
61    if(send_XPort && protocol[i++] != '\' )
    {UCA0TXBUF = protocol[i++];}  // TX next character
    if (i == sizeof protocol - 1)            // TX over?
    {
      i = 0;                           // Nach Stringende
      send_XPort = 0;
      P3OUT &= ~(1<<2);
      IE2 &= ~UCA0TXIE;
      ready = 1;
    }
}

fehlermeldung:
61: missing closing quote und
61: expected a ")"

in meinem CCE kann ich sehen, dass die klammer zu blau geschrieben 
erscheint, also glaube ich, der interpretiert das als string, obwohl ich 
das abgefragte stringendezeichen wie es sich gehört in '' geschrieben 
habe....

Wo ist mein Fehler? Kann ich bei bestem Willen nicht sehen. Klammer zu 
ist gemacht, das ist nicht der Fehler!

von P. S. (Gast)


Lesenswert?

Du musst \ escapen: \\.

von Timo P. (latissimo)


Lesenswert?

ok dann war das mein fehler, so wie \n das n für newline ist ist \\ dann 
das \ als mein gewünschtes zeichen...

von P. S. (Gast)


Lesenswert?

Sowas sind Grundlagen die man in der Literatur findet, auf die dich Karl 
Heinz schon hingewiesen hat :-/

von Timo P (Gast)


Lesenswert?

compilierbar schon, aber ausgabe fehlt!!
1
void convert_temp(char * s)
2
{
3
  unsigned char t,k = 0;
4
  char temp[6];
5
  uputs("\r\n s = ");
6
  uputs(s);
7
  uputs("\r\n");
8
  for(t = 1; t <=4; t++)
9
  {
10
    uputs("s[t]ist: ");
11
    uputchar(s[t]);
12
    uputs("\r\n");    
13
    
14
    if(s[t] != ' ' && s[t] != 'T')
15
    {
16
      temp[k] = s[t];
17
      k++;
18
    }
19
  }
20
  temp[k] = '\0';
21
  strcpy(s,temp);
22
}
ausgabe:
s = T-123
s[t]ist:

von Alex (Gast)


Lesenswert?

........habe mich jetzt nicht durch alle Antworten gewühlt, vielleicht 
hat es schon einer geschrieben:

- DATA nie als Variablennamen verwenden, ist reserviert für den Compiler

Grüße,

Alex

von Timo P. (latissimo)


Lesenswert?

aufruf: Projekt1.exe -abc

#include <stdio.h>
#include <stdlib.h>
#include <stdafx.h>

int main(int argc, char *argv[])
{
  printf("*argv =**%s** argc(int)=%d",argv,argc);
  printf("\r\n\n\n\nhier einzelne ZeicheN:");
  printf("\n%c\r",argv[0]);
  printf("\n%c\r",argv[1]);
  printf("\n%c\r",argv[2]);
  printf("\n%c\r",argv[3]);
  printf("\n%c\r",argv[4]);
  getchar();
  return 0;
}

ausgabe ist als string was anderes als als einzelne Zeichen!
Beides sind wirres zeug, zb. ,8$>

von Timo P. (latissimo)


Lesenswert?

Im Übrigen ist die Ausgabe Compilerabhängig! Visual Studio C++ Projekt 
ist anders, als DevC++ als C-Projekt

von Karl H. (kbuchegg)


Lesenswert?

Timo P. schrieb:

>   printf("*argv =**%s** argc(int)=%d",argv,argc);

argv ist kein String.
argv ist ein Array von Pointern, wobei jeder Pointer auf einen String 
zeigt.

    argv
   +-------------+
   |    o-------------------------->"Projekt1.exe"
   +-------------+
   |    o---------------------+
   +-------------+            |
   |  NULL       |            +--->"-abc"
   +-------------+


>   printf("\r\n\n\n\nhier einzelne ZeicheN:");
>   printf("\n%c\r",argv[0]);

argv[0] ist ein Pointer, der auf den Anfang des ertsen Strings zeigt.
Normalerweise ist das der Name der EXE die gestartet wurde. Kann aber 
auch ein Leerstring sein oder auch der komplette Name des EXE inklusive 
Pfadangabe, von wo aus das EXE gestartet wurde.

>   printf("\n%c\r",argv[1]);

argv[1] ist ein Pointer auf dein erstes Argument. In deinem Fall ein 
Pointer auf den String "-abc"

>   printf("\n%c\r",argv[2]);

so wie du das EXE aufgerufen hast, ist argv[2] ein NULL Pointer

>   printf("\n%c\r",argv[3]);

Du hast kein Recht auf argv[3] zuzugreifen. argc wird bei dir 2 sein.

>   printf("\n%c\r",argv[4]);

Du hast kein Recht auf argv[4] zuzugreifen. argc wird bei dir 2 sein.

> Beides sind wirres zeug, zb. ,8$>

Sie sind deshalb wirr, weil du wirres Zeug programmiert hast.

von Karl H. (kbuchegg)


Lesenswert?

Alex schrieb:
> ........habe mich jetzt nicht durch alle Antworten gewühlt, vielleicht
> hat es schon einer geschrieben:
>
> - DATA nie als Variablennamen verwenden, ist reserviert für den Compiler

Seit wann?

von Timo P. (latissimo)


Lesenswert?

Karl heinz Buchegger schrieb:
> Sie sind deshalb wirr, weil du wirres Zeug programmiert hast.

Ich bin davon ausgegangen, dass argv[0] ein einzelnes Element vom typ 
char ist. Wäre dann folgende zeile wirklich "wirres Zeug"?

printf("\n%c\r",argv[0]);

von Timo P. (latissimo)


Lesenswert?

int main(int argc, char *argv[])
{
    for(int i = 0; i<argc; i++)
    {
            printf("\r\n\n argv[%d]:%s\r\n",i,argv[i]);

    }

    //system("PAUSE");
    //return EXIT_SUCCESS;
}

so funzt es jetzt!

Das ist dann kein Wirres Zeug mehr!

von Alex (Gast)


Lesenswert?

@ Karl Heinz Buchegger

Hallo!

Guter Punkt, ist wahrscheinlich Compiler/IDE abhängig!? Verwende selbst 
Keil uVision3 und der gibt mir folgende Info:

"The DATA statement assigns an address (in the range 00h-0FFh) to the 
specified symbol. The symbol may not be redefined"

Grüße,

Alex

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.