c++ - 使用Raspberry PI GPIO-我是否需要虚拟/抽象/接口(interface)类?

标签 c++ class raspberry-pi gpio

介绍
我正在使用Raspberry PI GPIO做一些工作。直到现在,我仍然像在C语言中那样编写代码,使用函数将代码段组合在一起。
我的工作已经到了令我满意的地步,但是现在事情开始变得困惑了,所以我想朝着面向对象的方向发展。
问题
这是我面临的问题。
目前,我有一个代表我的“设备”的类。 (我构建的硬件已连接到GPIO端口。)该硬件有2个不同的部分。一个部分是“输入”部分,另一部分是“输出”部分。
为了帮助您更好地理解这一点,“输入”部分是一个ADC。 (模数转换器。)这是一种将模拟信号转换为10位二进制表示形式的设备。 (以防您不熟悉电子产品。)
“输出”部分只是一个晶体管,用于开关一组LED。
我想有一个代表ADC板的类和代表LED板的类,因为它们是两个概念上不同的设备,因为它们没有以任何方式“链接”。
这会引起问题,因为在设置其模式之前,必须将GPIO引脚设置为某些值。值表示“高”或“低”,1或0。模式表示“输入”或“输出”。这听起来很奇怪,但是从根本上讲,如果在加电之前未将控制线设置为正确的LOGIC HIGH和LOGIC LOW值,则ADC将变得不同步。 (这是一个非常奇怪的设备,即使已连接到电源,它也不会通电,直到它被告知为止。(VCC或VDD 5.0V)其中一条控制线发送信号来为该设备加电。
为了执行上述操作,请考虑GPIO引脚最初处于INPUT模式。为了“使ADC正常工作”,我们首先设置数据值(HIGH/LOW),然后再将这些数据值更改为OUTPUT模式。这样,当模式从INPUT更改为OUTPUT时,将显示正确值的数据,而不会破坏ADC。
我最初的想法是为ADC建立一个构造函数,该构造函数首先设置输出数据的值,然后将require引脚从INPUT模式更改为OUTPUT模式。但这迫使我们在LED板类之前构造ADC板类。
这可以通过两个构造函数执行相同的代码来设置输出模式来解决,但这似乎不是一个好主意,因为我们两次调用2位代码-这不是一个非常好的解决方案。
另一个解决方案是拥有一个将输入和输出设备组合在一起的GPIOPort类,但这也不是很优雅,如果要添加第二个相同的LED板,则很难进行修改。 (例如。)
我想我想要什么,但我不确定...
我想我想要的是另一个代表GPIOPort本身的类。 (我猜是一种抽象的想法?)然后,我想我也希望“一个类中的一个类”代表ADC板,并且“一个类中的一个类”代表LED板。我不记得这种技术叫什么,但是通常“外部类”就像一个 shell ,带有指向“内部类”类型的对象的指针,以及一个create方法和destroy方法。外部类在create方法中执行类似于pointer = new type;的操作,在destroy方法中执行类似delete pointer的操作。这允许在需要时调用构造函数,并在需要时调用类析构函数。
这样做的重点是GPIOPort类构造函数可以处理这些对象的创建顺序,这将隐藏main()中的所有内容。在main内部,程序员只需要执行GPIOPort myGPIOPort;之类的操作即可处理所需的一切,因此您不必在main()中包含20行代码来设置输出引脚的数据,这是唯一的其他解决方案。 (以上我没有提到。)
问题
所以我的第一个问题是这种技术被称为什么?我以为它被称为包装器类,但是我的理解是包装器类用于将诸如doubleint之类的基本类型用作对象。 (并添加clear()reset()之类的方法或类似的方法。)这是我实际上要执行的操作,还是有更好的方法? (我想这归结为“如何解决我的问题”。)
我的第二个问题是,据我所记得,我必须将某些方法(析构函数?)虚拟化,但是我不记得为什么。 (或者也许我不知道,我只是感到困惑。)
我的第三个问题是,有什么例子可以用来帮助我自己理解它,或者可以去哪里增进我的理解。 (资源。)
谢谢,显然这是一个很长的问题。我试图提供尽可能多的信息以帮助解释这种情况。如果您想澄清一下,那么我会尽力改善我所说的话。
编辑:有关设备的更多信息
在将其模式从输入更改为输出之前,必须将数据发送到GPIO引脚。
GPIO引脚看起来像全零,因为引脚上有下拉电阻,它们仍被设置为输入。更改其模式后,才会显示已发送的数据。
然后将引脚设置为输出模式。 (或者仍然有一些。)现在,已发送的数据出现在引脚上。
如果在发送数据之前将引脚设置为输出模式,则我们不能阻止ADC上电,因为控制ADC上电的数据引脚可能设置为HIGH。可以将其设置为LOW,但是无法告知其状态是不确定的,直到我们将设置模式为输出之前告诉GPIO我们想要什么值。幸运的是,我们可以保证所有引脚都处于输入模式。

最佳答案

一些定义:

  • 设备:附加到GPIO(输入和输出)
  • 的整个设备
  • LEDBoard:设备
  • 的输出部分
  • ADCBoard:设备
  • 的输入部分

    我强烈建议而不是使用单例。有一天,您可能会将第二个设备连接到其他GPIO引脚,这将给您带来麻烦。

    如果为LEDBoard和ADCBoard创建单独的类,则必须询问:
    “创建LEDBoard/ADCBoard我需要什么?”
    好吧...您需要一个设备!

    所以我的设计如下:
    struct DeviceDescriptor
    {
      int portNumber;
      // add additional variables to identify the device
    }
    
    class Device
    {
      Device(DeviceDescriptor descriptor)
      {
        //Insert your initialization...
        //You can maintain a static vector of already opened Devices to throw an
        //error if an allready opened device is reopened
      }
      ~Device()
      {
        //Deinit device
      }
    
      // A device should not be copyable
      Device(const& Device) = delete;
      //TODO do the same for copy assignment
      //TODO implement move ctr and move assignment operator
    
      //TODO add needed mamber variables
    }
    
    class LEDBoard
    {
      LEDBoard(std::shared_ptr<Device> device) : m_device(device)
      {
        //Do init stuff
      }
    
      //Your functions
    
      private:
      std::shared_ptr<Device> m_device;
    }
    
     //ADCBoard is analog to LEDBoard
    

    您可以使用以下类:
    int main(void)
    {
       auto device = std::make_shared<Device>(DeviceDescriptor());
       LEDBoard led1(device);
       ADCBoard adc1(device);
       //Your stuff...
    }
    

    好处:
  • 您可以有多个设备
  • 可以轻松添加更多LEDBoard
  • 通过使用shared_ptr,当最后一个LEDBoard/ADCBoard被销毁时,设备对象将被销毁

  • 关于c++ - 使用Raspberry PI GPIO-我是否需要虚拟/抽象/接口(interface)类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24757939/

    相关文章:

    mysql - 树莓派无法安装mysql

    c++ - pbs_server、E5-2620v4 和一般保护

    c++ - 将 STL 容器从 Flex 传递到 Bison

    java - 当类中实际上有一个 main 方法时,没有 main 方法

    c# - 单例类可以是静态的吗?

    python - .pyc 平台独立吗?

    c++ - 在 Gaia 支持下构建音频分析库 Essentia 失败

    c++ - 为什么首选 uint32_t 而不是 uint_fast32_t?

    c++ - vector 存储对象

    java - 树莓派上的数据库