C auf PIC16F1937 komisches Verhalten oder auch nicht!?



  • Hallo Leute,

    es handelt sich hier um embedded Programmierung, evtl. liegt das Verhalten an der Hardware bzw. Compiler, aber:

    Ich habe folgende adc.h

    static BYTE channelID = 0;
    
    typedef struct ADC_Result
    {
        BYTE channel; //ADCON0
        UINT value;
    
    } sADC_Result;
    
    #define ChannelCount 2
    
    static sADC_Result adc_Channels[2] = 
    { 
            { 0x7D, 0x0004},    //0 11111 01 Battery measurement
            { 0x21, 0x0003}     //0 00101 01
    };
    

    und eine adc.c mit folgender funktion;

    UINT adc_Get(BYTE channel)
    {
        return adc_Channels[channel].value;
    }
    

    nun habe ich meine main.c, darin will ich nun die adc_Channels lesen,
    allerding liefert mir das program eine 0 wenn ich in der main.c direkt

    value = adc_Channels[channel].value;
    

    ich muss also die funktion "adc_Get" aus der adc.c verwenden damit mir ein korrekter wert gelierfert wird.. aber warum?

    Das adc_Channels Array ist ja in der adc.h statisch deklariert, wechle in der adc.c und der main.c included is? worran liegt das???!?! Die Variabe müsse doch in beiden C modulen gültig sein?

    Danke



  • Das liegt daran, dass du Grundlagen nicht verstanden hast. (Ja, entgegen landläufiger Meinung gelten C-Grundlagen auch bei Embedded-C).

    Du hast in *.h etwas definiert (nicht wie du meinst deklariert), das ist das Grundübel deines Programmdesigns.
    Im Wesentlichen scheiterst du also an mehreren Dingen
    - Definitionen in Header-Dateien
    - globale Variablen (du hast nicht verstanden, wozu Get/Set gut sind, nämlich genau um den Zugriff zu kapseln)
    - suboptimale Aufteilung der struct-Elemente (Größte zuerst)

    Verzichte auf globale Variablen, und dein Problem löst sich von selbst.



  • Wenn du in main. und adc.c jeweils ein #include "adc.h" hast, dann hast du auch zweimal adc_Channels
    Und weil die static sind, bleiben die auch verschieden. Sonst könnte der Linker sie zusammen fassen.



  • @DirkB: Danke ,genau das war mir nich bewusst;)

    @Wutz: Danke für deine Ausführungen:) Ich habe nun das Array in der adc.c deklariert:) Greife via getter zu:)

    1. Wieso die größeren datentypen im struct zuerst? Padding?
    2. Sind varablen welche in net c-file ausserhalb funktionen deklariert sind nich gobal?


  • Mod

    Ich mache ja normalerweise keine Rechtschreibflames, aber wenn es derartige Ausmaße annimmt, mache ich eine Ausnahme: Kannst du mal in lesbarem Deutsch schreiben? Da kriegt man ja Kopfschmerzen, wenn jemand so schreibt wie er spricht. Ich antworte jedenfalls aus Prinzip nicht, wenn man einen Satz 3x lesen muss, um ihn zu verstehen.



  • Du verwechselst immer noch deklarieren und definieren.
    1. ja
    2. ja, nein, vielleicht. Deine sind static . Das Wort steht da. Du musst wissen warum du das hingeschrieben hast und auch, was das bedeutet.

    Embedded ist etwas spezieller.
    Ob du das jetzt mit Getter/Setter machen willst und ob du auf globale Variablen verzichtest, musst du sehen.

    In jedem Fall musst du wissen, was du schreibst. Das gilt für jedes einzelne Zeichen.



  • Hallo Leute bzw. Dirk,

    danke für eure Beiträge, hab mich deshalb auch in die Richtung noch etwas eingelesen!

    Was ich aber noch nich ganz verstanden habe, ist der Unterschied zwischen

    einer "statischen" und nicht statischen globalen Variablen innerhalb eines Modules!?

    Konnte mehr oder weniger entnehmen, dass eine nicht-statische Variable von außen zugreifbar ist, aber was bedeutet das von "außen" in dem Kontext!

    Wenn ich foo.h die entspreche foo.c habe, und ich habe in foo.c eine Variable ohne static deklariert. Habe die foo.h in der main.c includiert, kann ich ja von da aus NICHT auf die variable in der foo.c zugreifen!? oder ist das anders gemeint?

    Grüße



  • NullBockException schrieb:

    Wenn ich foo.h die entspreche foo.c habe, und ich habe in foo.c eine Variable ohne static deklariert. Habe die foo.h in der main.c includiert, kann ich ja von da aus NICHT auf die variable in der foo.c zugreifen!?

    Doch, kannst Du. Du musst die Variable nur deklarieren (Z. 4 in main.c )

    // main.c
    #include "foo.h"
    
    extern const char *s;
    
    int main(void) {
      func();
      s = "Hallo Welt!";
      func();
    }
    
    // foo.h
    #ifndef FOO_H
    #define FOO_H
    void func(void);
    #endif
    
    // foo.c
    #include <stdio.h>
    
    //static const char* s = "Hello, World!";
    const char *s = "Hello, World!";
    
    void func(void) { puts(s); }
    


  • Ahhhh Klick .... optimal.. Danke:)

    d.h. im Module foo.c selbst macht es aber keine Unterschied ob ich ne Variable static ist oder nich, nur wenn ich eben von außen zugreifen will.. Richtig?


  • Mod

    NullBockException schrieb:

    d.h. im Module foo.c selbst macht es aber keine Unterschied ob ich ne Variable static ist oder nich, nur wenn ich eben von außen zugreifen will.. Richtig?

    Du (und vor allem der Compiler!) weiß dann unter Garantie, dass sich der Wert nur durch Vorgänge innerhalb von foo.c ändern kann. Das macht es aber auch nicht viel besser, die wesentlichen Nachteile der globalen Variablen werden dadurch nur unwesentlich abgeschwächt.



  • @SeppJ : Danke für den Hinweis:)

    Ich hab jetzt bisschen refactoring betrieben und (wo es möglich war) auf globale variablen innheralb der c-files verzichtet und keinem mehr in den h-files 🙂

    Nun habe ich noch ein weiteres Anliegen:)

    Ich möchte eine Delay Funktion implementiren, welche Asyncron zu den anderen Modulen (kooperativen Multitasking) läuft!

    Nun habe ich da eine unsigned int (16Bit) counter , welche ich ständig im timer interrupt hochzähle.

    wenn ich nun in meiner Delayfunktion den alten wert merke, und den neuen davon abziehe müsste doch IMMER ein positiver wert raukomemn auch wenn der Alte und der neue Wert vor und nach dem überlaufe bzw. - zu + spirngen.

    Bedinung: Aufruf Interval der Delay funktion liegt unter einem unsigned int überlauf!

    Oder hab ich nen Denkfehler.. Überlauf doch beachten?

    Pseudo:

    unsigned int counter;
    unsigned int old;
    typedef unsigned char BOOL;

    void timer_interrupt(void)
    {
    ++counter;
    }

    BOOL Delay()
    {
    int diff= (int)(old - counter);
    if(diff>=1000)
    {
    return 1;
    }
    return 0;
    }

    void main()
    {
    while(1)
    {
    if(Delay())
    {
    //Klingeling
    }
    }
    }}


  • Mod

    Es würde ja funktionieren, wenn du wirklich mit unsigned int rechnen würdest. Aber aus mir völlig unverständlichen Gründen packst du das Ergebnis in einen (signed) int. Wundert dich dann, dass du negative Werte bekommst?

    Willst du wirklich globale Variablen in einer Multithreaded-Umgebung benutzen? Wenn das vorher schon nicht empfehlenswert war, so ist das bei mehreren Threads erst recht super-tödlich. Falls dein Programm mehr als nur ein Beispiel ist, machst du auch prompt alles falsch.



  • Sorry mit code Tags

    unsigned int counter;
    unsigned int old;
    typedef unsigned char BOOL;
    
    void timer_interrupt(void)
    {
    ++counter;
    }
    
    BOOL Delay()
    {
    int diff= (int)(old - counter);
    if(diff>=1000)
    {
    return 1;
    }
    return 0;
    }
    
    void main()
    {
    while(1)
    {
    if(Delay())
    {
    //Klingeling
    }
    }
    }}
    


  • Es handelt sich ja um kooperativen Multitasking, ich hätte in dem fall nur die counter variable global, was is das schlimm?

    achso stimmt , aber wenn ich eine postiven unsigend int auf int caste kommt ja das gleiche Ergbniss , soweit die zahl unter 32767 ist!?

    ja ok wenn ich sowas mache

    nt diff= (unsigned int)(old - counter);
    

  • Mod

    1. Lass die dummen Casts weg. Was denkst du, was die machen sollen? Fakt ist, sie machen überhaupt gar nichts!
    2. Habe ich gesagt "packst du das Ergebnis in einen (signed) int". Das machst du immer noch. Natürlich passiert immer noch das gleiche.



  • Ok Danke Sepp,

    ich schau mir das nochmal an 😃

    Aber trotzdem nochmal zu meiner globalen counter Variable! Welche als static in der in der delayTimer.c befindet. Wie kann ich das "nicht-global" lösen?

    Bin für jegliche Tipps und Einwände offen 🤡 .. oder wie würdest du so einen delay Methode implementieren?

    Grüßle



  • NullBockException schrieb:

    Sorry mit code Tags

    So ist das genauso unlesbar.
    Du solltest dich für einen Einrückungsstil entscheiden.


Anmelden zum Antworten