在这种情况下如何避免全局变量(嵌入式 C)

How to avoid globals in this case (embedded C)

我仍在学习用于微处理器的 C。一开始我使用了很多全局变量。现在我尽量避免它,但对我来说并不总是很清楚如何做到这一点。

比如电池监视器,在本例中有4个函数需要读取或修改一个变量。 我有这些功能都使用变量 LowVoltage。

void Check_Voltage(){
  checks current voltage against LowVoltage
}

void Menu_Voltage(){
  a menu on the LCD screen to set the value of LowVoltage
}

void Save_LowVoltage(){
 runs after the settings menu is finished to save LowVoltage to EEPROM
}

void Load_LowVoltage(){
 reads EEPROM and sets LowVoltage at startup 
}

如何在不使 LowVoltage 全局化的情况下完成这项工作? 我需要创建另一个函数来读取或写入 LowVoltage 吗? 像这样:

unsigned int Low_Voltage(short Get, unsigned int Value){
  static unsigned int LowVoltage;

  if(Get) return LowVoltage;
  else LowVoltage= Value;
}

或者有更好的方法吗?我想一定有 :) 我最近一直在阅读结构,但老实说我并不完全理解它们,我什至不确定在这种情况下它是否对我有帮助?

在函数之间共享一个变量有几种选择:

  • 在静态内存中分配您的变量 - 这几乎就是您的代码所做的。您的两个选择是函数静态、翻译单元静态和全局
  • 将指针作为函数参数传递给变量 - 这个选择需要以某种形式传递指针
  • 使用具有巧妙初始化的线程本地存储 - 当您使用微控制器时通常无法使用此选项;我在这里列出它是为了完整性。

对于您的情况,我认为使用翻译单元静态变量比较合适。将四个函数的实现放在一个C文件中,并在顶部声明LowVoltage为静态变量:

static unsigned int LowVoltage;

这种简单而高效的封装机制为您提供了拥有全局变量的所有好处,而没有拥有全局变量的缺点:

  • C模块里面的所有函数"see"这个变量,可以自由操作
  • C 模块之外的其他函数无法访问此变量。他们可以声明自己的 LowVoltage 变量,赋予它完全不同的含义。

我能想到的两种解决方案

  1. 像这样制作函数签名

    unsigned int Load_LowVoltage(unsigned int lowVoltage);
    

    然后传递 LowVoltage 并为其分配 return 值,就像这样

    LowVoltage = Load_LowVoltage(LowVoltage);
    
  2. 在函数内部修改LowVoltage,像这样传递一个指向你原来的LowVoltage的指针

    void LowVoltage(unsigned int *lowVoltage)
     {
        *lowVoltage = modifiedValue;
     }
    

    那你就可以这样使用了

    Load_LowVoltage(&LowVoltage);
    

我认为第二种解决方案更简洁,并且由于您处于资源有限的环境中,因此从这个意义上讲它也更好。但它们都易于实施并且效果一样好。

您可以创建一个包含所有电池参数的结构,例如:

typedef struct {
  int low_voltage; 
  int voltage;
  int capacity;
  int temperature;
  ...
} BatteryData

在程序开始时为其分配内存并将成员初始化为一些起始值:

BatteryData *battery = malloc(sizeof(BatteryData));
battery->low_voltage = 0;
...

然后将指向整个结构的指针传递给设置或读取单个值的函数,例如:

void Load_LowVoltage(BatteryData *battery){
 //reads EEPROM and sets LowVoltage at startup 
 int eeprom_val = get_low_voltage_from_eeprom();
 battery->low_voltage = eeprom_val;
}

在不需要时释放结构:

free(battery);