2016-08-01 47 views
1

私は、ある関数(例えば、mylib.c)で宣言されている変数を 'extern'を使ってmain関数で使う必要があるプロジェクトに取り組んでいます。複数のインクルードを避けるために、すべてのヘッダーにガードワードが含まれています。 変数はmylib.hで定義されている構造体で、メンバーは浮動小数点数と整数のみです。これはmain関数の先頭で初期化されます。STM32上のCでのグローバル変数

メインのループに入り、何らかの作業をした後、関係のないメンバーの中にはランダムな値があります。

したがって、mainの宣言からexternを削除し、代わりにmylib.cの宣言に配置しました。そしてそれは働いた。

Sim808.h

#ifndef _SIM808_H 
#define _SIM808_H 
typedef struct{ 
uint8_t GPRS_Active; 

float gsm_latitude; 
float gsm_longitude; 
}SIM808; 
void sendCmd(const char cmd[]); 
void sim808_init(void); 
void parse_gsm_location(uint8_t* line); 
#endif 

Sim808.c

#include "sim808.h" 
SIM808 sim808; 
void parse_gsm_location(uint8_t* line) 
{ 
uint8_t commas=0,index=0; 
uint16_t err; 
if((err=atoi((const char*)line+12))!=0) 
{ 
    printf("No coordinates received\n"); 
    if(err==404 || err==601) 
     sim808.GPRS_Active=0; 

    return; 
} 
while (line[index]!= '\0' && index <50) 
    { 
    if(line[index]==',') 
    { 
     commas++; 
     switch (commas) 
     { 
      case 1: 
       sim808.gsm_longitude=atof((const char*)(line+index+1)); 
       printf("Long:%f\n",sim808.gsm_longitude); 
      break; 
      case 2: 
       sim808.gsm_latitude=atof((const char*)(line +index+1)); 
       printf("Longitude%f  Latitude%f\n",sim808.gsm_longitude,sim808.gsm_latitude); 
      break; 
      case 3: 
       sscanf((const char*)(line+index+1),"%4d/%2d/%2d", (int*)&sim808.gsmDate.year,(int*)&sim808.gsmDate.month, 
        (int*)&sim808.gsmDate.day); 
      break; 
      case 4: 
       sscanf((const char*)(line+index+1),"%2d/%2d/%2d", 
        (int*)&sim808.gsmTime.hours,(int*)&sim808.gsmTime.minutes,(int*)&sim808.gsmTime.seconds); 
      break; 
     } 
    } 
     index++; 
    } 
} 

main.cの

#include "sim808.h" 
extern SIM808 sim808; 

int main(void) 
{ 
    uint8_t response[150]; 
//init functions 
while(1) 
{ 
    if(sim808.GPRS_Active==1) 
    { 
     sendCmd("AT+CIPGSMLOC=1,1\r\n"); 
     HAL_UART_Receive(&huart4,response,2,60000);//max response time is 1 min 
     HAL_UART_Receive(&huart4,response,150,1000);//we dont need first 2 chars 
     parse_gsm_location(response); 
     memset((void*)response,0,150); 
    } 
    else 
     sim808_init(); 
    } 
} 

あなたが見ることができるように、メンバーGPRS_Activeは私の中に1または0を受け取ることができますコード。 printfを使用すると、最初の反復後に242になりました。 誰かが説明できますか?これはコンパイラのバグですか?おかげさまで

+3

あなたが提示したデータが不足していることから、私のクリスタルボールは、コンパイラのバグであることが無限に小さいという確率で、コードに問題があると推測しています。本当の答えを得るには、[MCVE](http://stackoverflow.com/help/mcve) –

+0

を投稿してください。 – rost0031

答えて

2

コンパイラの問題である可能性は非常に低いです。おそらく、変数がコードの一部で変更されている可能性があります。それらが最大のスコープを持つようにグローバル変数を使用しないようにしてください。

同じ名前のローカル変数のどこかを使用していますか?
マップファイルまたはデバッガが配置されている場所を確認しましたか?

この問題を追跡するのに役立つように、特定のアドレスのデータが変更された場合は、デバッガフィーチャデータウォッチを使用できます。

+0

答えをありがとう。後でコードを追加して、何が起こっているのかを確認できます。しかし、私はすべてをダブルチェックしました。変数名はユニークです。 –

+0

@ John Wick変数は "extern VarType varName;"と宣言する必要があります。ヘッダーにしかし、この説明から、おそらく配列のインデックスやポインタの問題があります。変数を移動すると、あなたが探していない場所に移動することによって問題が隠されている可能性があります。これは災害のためのレシピ、または少なくとも数時間の欲求不満のレシピです。 – Flip

0

グローバル変数を使用する場合、複数のインクルードの問題を避けるために、それらを.hファイルに宣言しません。もちろん、.hでそれらを宣言するいくつかのトリックを見つけることができますが、それは事態をとても複雑にすると思います。 mylib.cで

::これを試してみてください、あなたはまだ問題がある場合はmain.cので

int myGlobalVariable; 

extern int myGlobalVariable; 

int main(void) 
{ 
    myGlobalVariable = 5; 
} 

、あなたのスタックのサイズを大きくしてみてください。スタックのサイズが十分でない場合は、他のデータによって上書きされる可能性があります。

いずれかのコードでmemsetまたはmemcpyを使用する場合は、lengthパラメータが正しいことを確認してください。 memsetとmemcpyは非常に危険で、あなたが本当に望んでいないメモリのどこかに簡単に書き込むことができます。

+0

ありがとうございました。変数を宣言したときに、問題が発生しました。何が解決されましたか(それは?)、それは "int myGlobalVariable;" main.cと "extern int myGlobalVariable;" mylib.c –