mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik folgender code nicht compilierbar


Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fehlermeldung: c:65: error: lvalue required as left operand of 
assignment

typedef union 
{ unsigned int i;
  float f;
} value;

char s_write_byte(unsigned char value)
//----------------------------------------------------------------------------------
// writes a byte on the Sensibus and checks the acknowledge 
{ 
  unsigned char i,error=0;  
  for (i=0x80;i>0;i/=2)             //shift bit for masking
  { 
65   if (i & value) DATA=1;          //masking value with i , write to 
     else DATA=0;  

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Timo P. (latissimo)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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)

Autor: Stefan B. (stefan) Benutzerseite
Datum:

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

Nö. Bitmanipulation

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

Bewertung
0 lesenswert
nicht 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
  DATA = 1;

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

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

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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 :(

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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?

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

Bewertung
0 lesenswert
nicht 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.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht 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)

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht 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
#define SBIT( wo, bit )    (wo) |= ( 1 << (bit) )
#define CBIT( wo, bit )    (wo) &= ~( 1 << (bit) )

char s_write_byte(unsigned char value)
//----------------------------------------------------------------------------------
// writes a byte on the Sensibus and checks the acknowledge 
{ 
  unsigned char i,error=0;  
  for (i=0x80;i>0;i/=2)             //shift bit for masking
  { 
    if (i & value)
      SBIT( DATA_PORT, DATA_BIT );
    else
      CBIT( DATA_PORT, DATA_BIT );
  }
}

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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;

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

Bewertung
0 lesenswert
nicht 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.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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

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

Bewertung
0 lesenswert
nicht 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.
struct EinzelBit
{
  uint8_t Bit0 : 1;
  uint8_t Bit1 : 1;
  uint8_t Bit2 : 1;
  uint8_t Bit3 : 1;
  uint8_t Bit4 : 1;
  uint8_t Bit5 : 1;
  uint8_t Bit6 : 1;
  uint8_t Bit7 : 1;
};

#define SBIT( p, b )   ( ((struct EinzelBit*)(p))->Bit##b )

#define DATA  SBIT( PORTA, 1 )

int main()
{
  DATA = 1;
}

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ungefähr so:
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.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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?!?

Autor: A. K. (prx)
Datum:

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

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Ungefähr so:
>
> static __inline void nop(void) { __asm__ volatile ("nop"); }
> 
>

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...

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Timo P. schrieb:

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

Dann muss er aber vorher schon gemeckert haben.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht 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
static __inline void nop(void) { __asm__ volatile ("nop"); }

int main(void)
{
        nop();
}
frisst wohl jeder GCC anstandslos, egal für welche Maschine.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Winavr mit Astudio habe ich...

geht jedenfalls nicht. :(

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
AVR Studio    4.14.589
GUI Version    4, 14, 0, 589


und WINAVR 20080610


bei mir gehts nicht :(

Autor: A. K. (prx)
Datum:

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

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit AVRStudio 4.15.623 und WinAVR-20081205 läuft es...

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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 ....++;?

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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
static __inline void nop(void) { __asm__ volatile ("nop"); }

int main(void)
{
        nop();
}

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)

Autor: Thomas W. (wagneth)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Johann

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

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

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

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

Bewertung
0 lesenswert
nicht 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.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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....

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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....

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;)

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

Bewertung
0 lesenswert
nicht 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.

Autor: Timo P. (latissimo)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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 :(

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach mal ein #include <math.h>
unter #include "main.h"

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

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

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

typedef union 
{ unsigned int i;
  float f;
} value;


....


int main()
{ value humi_val,temp_val;

  ...

    { humi_val.f=(float)humi_val.i;                   //converts integer to float
      temp_val.f=(float)temp_val.i;                   //converts integer to float

    ...
}

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

//----------------------------------------------------------------------------------
void main()
//----------------------------------------------------------------------------------
// sample program that shows how to use SHT11 functions
// 1. connection reset 
// 2. measure humidity [ticks](12 bit) and temperature [ticks](14 bit)
// 3. calculate humidity [%RH] and temperature [?C]
// 4. calculate dew point [?C]
// 5. print temperature, humidity, dew point  

{
  int   humi_val_i;
  int   temp_val_i;

  float humi_val,temp_val;
  double dew_point;
  unsigned char error,checksum;
  unsigned int i;

  uinit();
  s_connectionreset();
  while(1)
  { error=0;
    error+=s_measure((unsigned char*) &humi_val_i,&checksum,HUMI);  //measure humidity
    error+=s_measure((unsigned char*) &temp_val_i,&checksum,TEMP);  //measure temperature
    if(error!=0) s_connectionreset();                 //in case of an error: connection reset
    else
    {
    humi_val = humi_val_i;                   //converts integer to float
      temp_val = temp_val_i;                   //converts integer to float
      calc_sth11(&humi_val,&temp_val);            //calculate humidity, temperature

      dew_point=calc_dewpoint(humi_val,temp_val); //calculate dew point
      sprintf(s,"temp:%5.1fC humi:%5.1f%% dew point:%5.1fC\r\n",(double)temp_val,(double)humi_val,dew_point);
      uputs(s);
    }
    //----------wait approx. 0.8s to avoid heating up SHTxx------------------------------      
    for (i=0;i<40000;i++);     //(be sure that the compiler doesn't eliminate this line!)
    //-----------------------------------------------------------------------------------                       
  }
} 


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.
#define SBIT( p, b )   ( ((struct EinzelBit*)(&p))->Bit##b )

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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??

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

Bewertung
0 lesenswert
nicht 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.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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??

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

Bewertung
0 lesenswert
nicht 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.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht 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.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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??

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

Bewertung
0 lesenswert
nicht 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.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meine Version vom SHT11 Code: 
Beitrag "Sensirion SHT11 Code"

Autor: Timo P (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

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

Bewertung
0 lesenswert
nicht 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.

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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);

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

Bewertung
0 lesenswert
nicht 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.
  float humi_val,temp_val;

  sprintf( s,"temp:%5.1f C humi:%5.1f dew point:%5.1fC\r\n",
                  (double)temp_val,
                  (double)humi_val,
                  (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).

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann werd ich mich wohl damit zufrieden geben müssen.

Besten Dank für die ganze Hilfe!

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst \ escapen: \\.

Autor: Timo P. (latissimo)
Datum:

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

Autor: P. S. (Gast)
Datum:

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

Autor: Timo P (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
compilierbar schon, aber ausgabe fehlt!!
void convert_temp(char * s)
{
  unsigned char t,k = 0;
  char temp[6];
  uputs("\r\n s = ");
  uputs(s);
  uputs("\r\n");
  for(t = 1; t <=4; t++)
  {
    uputs("s[t]ist: ");
    uputchar(s[t]);
    uputs("\r\n");    
    
    if(s[t] != ' ' && s[t] != 'T')
    {
      temp[k] = s[t];
      k++;
    }
  }
  temp[k] = '\0';
  strcpy(s,temp);
}
ausgabe:
s = T-123
s[t]ist:

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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$>

Autor: Timo P. (latissimo)
Datum:

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

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

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht 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?

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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]);

Autor: Timo P. (latissimo)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

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.