Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 将对象创建移动到arduino的setup()函数_C_Arduino - Fatal编程技术网

C 将对象创建移动到arduino的setup()函数

C 将对象创建移动到arduino的setup()函数,c,arduino,C,Arduino,我创建了一个类来处理向led矩阵(max7219)发送数据 这就是我创建LedControl类实例所做的 LedControl lc=LedControl(11, 13, 12);// data, clock, latch; void setup() { ... } 现在,我正在尝试将计时器中断添加到我的类中。但是我发现我无法在初始值设定项中设置适当的注册表(LedControl::LedControl())。如果我将此代码移动到设置,则所有代码都能正常工作。我的猜测是,Arduin

我创建了一个类来处理向led矩阵(max7219)发送数据

这就是我创建LedControl类实例所做的

LedControl lc=LedControl(11, 13, 12);// data, clock, latch;

void setup() 
{
   ...
}
现在,我正在尝试将计时器中断添加到我的类中。但是我发现我无法在初始值设定项中设置适当的注册表(
LedControl::LedControl()
)。如果我将此代码移动到
设置
,则所有代码都能正常工作。我的猜测是,Arduino引导加载程序在调用
setup()
之前,但在我的对象初始化之后,对PWM使用
timer1
覆盖这些注册表

所以我的想法是将对象创建移动到设置函数,如下所示

// FAIL
LedControl lc;

void setup() 
{
   lc=LedControl(11, 13, 12);// data, clock, latch;
   ...
}
但是,我得到了一个错误,调用'LedControl::LedControl()'时没有匹配的函数。

我尝试使用指针(
LedControl*lc;
lc=&LedControl(11,13,12);
),但据我所知,这意味着我必须到处编写
(*lc).someFunction()
,而不是
lc.someFunction()
。甚至比将注册表设置代码移动到setup()还要不优雅

所以我的问题是。如何在
setup()
函数中创建对象,但仍然有一个全局变量指向它?

您的第一个错误“不匹配…”是因为您没有默认构造函数。你可以让这种方法发挥作用

向类中添加一个无参数(也称为默认构造函数),如下所示:

class LedControl {
  LedControl();
  LedControl(uint8_t pin1, uint8_t pin2, uint8_t pin3);

private:
  uint8_t pin1;
  uint8_t pin2;
  uint8_t pin3;
};

LedControl::LedControl() : pin1(0), pin2(0), pin3(0) {
  // this constructor leaves the class unusable
}

LedControl::Ledcontrol(uint8_t p1, uint8_t p2, uint8_t p3) 
  : pin1(p1), pin2(p2), pin3(p3)
{
  // this object is ready to use    
}
LedControl::LedControl(uint8_t p1, uint8_t p2, uint8_t p3) 
  : pin1(p1), pin2(p2), pin3(p3)
{
  pinMode(pin1, INPUT);
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
  return;
}
在这个类中,您的方法将起作用,但不是最佳方法。这条线做了太多的工作:

void setup() {
  lc = LedControl(11, 13, 12);// data, clock, latch;
}
这行代码涉及编译器为您创建一些代码:

  • 首先,使用参数11、13、12在堆栈上构造该类的另一个实例
  • 然后应用=操作符将数据从堆栈对象复制到全局对象
  • 当setup()退出时,堆栈对象被刷新
因为临时对象在堆栈上,所以您的程序没有使用太多内存,但是您的代码大小更大,因为它需要额外的操作来构造临时对象,然后从临时对象复制到永久对象

请注意,编译器正在为您创建一个=运算符,以填充该行的函数

  lc = LedControl(11, 13, 12);
这可能有效,也可能无效,这取决于构造函数中的内容。编译器只能假定您需要一个简单的=运算符。基本赋值运算符所要做的就是将所有数据成员从=右侧的实例复制到左侧的实例。编译器constructed=将不包含任何代码

如果您的构造函数执行了任何重要的操作(除了保存参数),那么编译器构造的(猜测的)赋值运算符可能无法按预期工作。对于您的情况,构造函数可能会设置pin模式,如下所示:

class LedControl {
  LedControl();
  LedControl(uint8_t pin1, uint8_t pin2, uint8_t pin3);

private:
  uint8_t pin1;
  uint8_t pin2;
  uint8_t pin3;
};

LedControl::LedControl() : pin1(0), pin2(0), pin3(0) {
  // this constructor leaves the class unusable
}

LedControl::Ledcontrol(uint8_t p1, uint8_t p2, uint8_t p3) 
  : pin1(p1), pin2(p2), pin3(p3)
{
  // this object is ready to use    
}
LedControl::LedControl(uint8_t p1, uint8_t p2, uint8_t p3) 
  : pin1(p1), pin2(p2), pin3(p3)
{
  pinMode(pin1, INPUT);
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
  return;
}
这种情况发生在功能上,但只是偶然的。pinMode()调用是在临时对象构造并从该对象而不是全局lc调用时进行的。因为pinMode()是全局的,所以本例将实现正确的目标,但可能不是预期的方式。对于更复杂的操作,如注册中断处理程序,您需要创建自己的赋值运算符:

LedControl& operator= (const LedControl & other);
在该方法中,您可以确保全局lc的状态是您所需要的。一个更容易/更安全的方法是根本不处理这个问题

您可能在其他库中看到过一种简单而有效的方法,即向分配管脚的类添加一个方法:

class LedControl {
  void attach(uint8_t pin1, uint8_t pin2, uint8_t pin3);
};

void LedControl::attach(uint8_t pin1, uint8_t pin2, uint8_t pin3) {
  this.pin1 = pin1;
  this.pin2 = pin2;
  this.pin3 = pin3;
  // do other setup type operations
  return;
}

现在你的程序,构造空白对象,并在SETUP()中分配PIX:


这不涉及临时对象构造,也不涉及赋值运算符。关于设计,有些人可能会公正地评论说,用户可能忘记调用attach(),而使全局lc对象不可用。对于桌面应用程序,您可以添加一些代码以防止出现这种故障情况。对于嵌入式应用程序来说,这是一个您可以接受的风险,它由代码大小或内存节省的收益来平衡。

我刚刚遇到了同样的问题。我想创建一个全局调试端口对象,但无法将其创建为全局实例,因为调用setup()后端口将无法工作。我有相同的假设,arduino代码在我的构造函数(全局对象)之后和setup()之前执行一些设置工作

我发现它是最简单的解决方案,将我的对象声明为指针并在安装程序中初始化它。在您的情况下,它将是:

LedControl* lc;

void setup() 
{ 
   lc = new LedControl(11, 13, 12);// data, clock, latch;
}

void loop()
{
   lc->doSomething();
}
因此不需要额外的构造函数或操作符。
由于对象一直使用到断电,因此在这种情况下不需要删除。

Wauw。很好的解释,虽然我仍然不能100%理解。我肯定会使用attach方法。非常感谢你。