制作一个由Arduino上的多个端口组成的“虚拟端口”

时间:2019-02-18 19:18:48

标签: arduino port microcontroller arduino-c++

我开始在Arduino上使用端口,而不是手动将每个引脚设置为低电平或高电平。 这非常有用,而且速度更快。我在一个项目中,我需要至少一个完整的端口(8位)和至少一个串行端口。

我想使用Arduino UNO,但它只有一个完整的端口,即端口D。  PD0和PD1用于串行通信。这意味着我不能使用端口D。

我想知道我是否有可能将多个端口合并为一个“虚拟端口”。最后,我想要这样的东西:

PORTX = 0b11111111; // the first 2 bits are PB0/PB1 and bit 3-8 are PD3-PD8

这有可能吗?

1 个答案:

答案 0 :(得分:1)

我会说“是”是可能的,但是可能不是您想要的那样(或者也许我只是不知道怎么做^^)

首先,PORTS是Atmel的宏。您的Arduino-Uno基于AtMega328p,因此将AVR工具链与所有PORTS一起使用。 如果您要在没有arduino-bootloader和所有精美的arduino-library-stuff的情况下对微控制器进行编程,则可以用这种方式来寻址所有GPIO。

如果您查看Atmel-AVR工具链的代码(arduino位于其顶部),您会看到PORTS是在iom328p.h中定义的,并且仅仅是地址微控制器内部的内部IO寄存器。

因此,仅声明一个虚拟端口并不是那么容易(也许使用一种类似于std::mmap()的内存映射,但是我从未尝试过)。

无论如何,您都是程序员,所以几乎所有的东西都有解决方案;) 我个人建议创建您自己的Port-Class:

  • 该课程将您需要的Pins作为成员保存,并且您有一个二传手,它会根据您传递给它的号码来覆盖您的Member-Pins
  • (此代码并非“完美”的解决方案,只是向方向的快速提示)

对于这种方法,我建议您留在arduino库中。如果使用普通的PORTS进行操作,则可能会使某些地方混乱。因此,例如,如果您初始化自己的SerialPort,然后再执行类似PORTD |= (1<<PD0)的操作,则您将无法接收任何数据,也不知道为什么。

class MyPort
{
private:
  uint8_t m_pin[8];
public:
  MyPort(uint8_t pins[8])
  {
    for(int i=0; i<8; ++i)
    {
      m_pin[i] = pins[i];       //copy from constructor-argument into member-variable
      pinMode(pins[i], OUTPUT); //setting pin as OUTPUT
    }
  }

  void operator =(uint8_t val)
  {
    for(int i=0; i<8; ++i)
    {
      digitalWrite(m_pin[i], (val >> i)&1);
    }
  }
};

//            B0,B1,D2,D3,D4,D5,D6,D7
//             v  v  v  v  v  v  v  v
uint8_t pins[]{8, 9, 2, 3, 4, 5, 6, 7};
MyPort PORTX(pins);

void setup()
{
  PORTX = 0b11001100;
}

void loop()
{
  // put your main code here, to run repeatedly:
}

请注意,如果您也想在自己的端口上按位寻址,则也必须覆盖其他运算符