低级移位寄存器 class 使用 Arduino Zero 的端口操作

Low-level bit shift register class using port manipulation for Arduino Zero

我目前正在尝试为 Arduino Zero(基于 SAMD21 Cortex M0)编写低级移位寄存器 (74HC595)。

我已经完成了更高级别的 class 看起来像这样:

BitRegister.h

#ifndef BitRegister_h
#define BitRegister_h

#include "Arduino.h"

class BitRegister
{
  public:
    BitRegister(byte dataPin, byte clockPin, byte latchPin, uint8_t registerSize = 1);
    
    void sendData(uint8_t led);
    void shiftOut2(uint8_t bitOrder, uint8_t val);

  private:
    byte m_dataPin;
    byte m_clockPin;
    byte m_latchPin;
    uint8_t m_registerSize; //allows register's cascade
};

#endif

BitRegister.cpp

#include "BitRegister.h"

//**************************************************************
  
BitRegister::BitRegister(byte dataPin, 
                        byte clockPin, 
                        byte latchPin,
                        uint8_t registerSize)
:   m_dataPin(dataPin),
    m_clockPin(clockPin),
    m_latchPin(latchPin),
    m_registerSize(registerSize) //Number of register (if cascade)
{
  pinMode(m_dataPin, OUTPUT);
  pinMode(m_clockPin, OUTPUT);
  pinMode(m_latchPin, OUTPUT);
}

//************************************************************** 

void BitRegister::sendData(uint8_t led)
{
  led -= 1; //first LED is number 1

  digitalWrite(m_latchPin, LOW);
  for(int i = 1; i < m_registerSize + 1; i++){
    int registerNumber = m_registerSize - i; //The number of the register we're working on in the loop
    shiftOut(m_dataPin, m_clockPin, MSBFIRST, ~( 1 << (led - registerNumber*8) ) & 0xFF);
  }

  digitalWrite(m_latchPin, HIGH);
}

void BitRegister::shiftOut2(uint8_t bitOrder, uint8_t val)
{
    uint8_t i;

    for (i = 0; i < 8; i++)  {
        if (bitOrder == LSBFIRST)
            digitalWrite(m_dataPin, !!(val & (1 << i)));
        else    
            digitalWrite(m_dataPin, !!(val & (1 << (7 - i))));

        digitalWrite(m_clockPin, HIGH);
        digitalWrite(m_clockPin, LOW);        
    }
} 

问题是我必须在级联蚂蚁中与许多寄存器一起使用它 shiftOut2 方法(基于 Arduino 的 shiftOut 方法)真的很慢(我认为由于多个 digitalWrite).

所以基于此SAMD21 Cortex M0 tutorial and on the Arduino Zero Pinout Diagram (below), I tried to create a lower-level of my bit shift register class.

我目前面临的问题是我无法重写我的 shiftOut2 方法的全部内容,因此对于我的测试,我必须直接在方法主体中硬写端口号。

我将我的寄存器连接到 Arduino 的引脚 10、11 和 12,它们是 SAMD21 端口 18、16 和 19。

我的 class 代码如下:

LowBitRegister.hBitRegister.h 相同(class 名称和 class 构造函数名称除外)。

低BitRegister.cpp

#include "LowBitRegister.h"

//**************************************************************  

LowBitRegister::LowBitRegister(byte dataPin, 
                        byte clockPin, 
                        byte latchPin,
                        uint8_t registerSize)
:   m_dataPin(dataPin),
    m_clockPin(clockPin),
    m_latchPin(latchPin),
    m_registerSize(registerSize) //Number of register (if cascade)
{
  REG_PORT_DIR0 |= (1 << 18) | (1 << 19) | (1 << 16); //Set dataPin, clockPin and latchPin to OUTPUT
}

//************************************************************** 

void LowBitRegister::sendData(uint8_t led)
{
  led -= 1; //first LED is number 1
  
  REG_PORT_OUT0 &= ~(1 << 16); //Set latchPin to LOW
  
  for(int i = 1; i < m_registerSize + 1; i++){
    int registerNumber = m_registerSize - i; //The number of the register we're working on in the loop
    shiftOut2(MSBFIRST, ~( 1 << (led - registerNumber*8) ) & 0xFF);
  }
  
  REG_PORT_OUT0 |= (1 << 16); //Set latchPin to HIGH
}

void LowBitRegister::shiftOut2(uint8_t bitOrder, uint8_t val)
{
  uint8_t i;

  for (i = 0; i < 8; i++)  {
    if (bitOrder == LSBFIRST)
      digitalWrite(m_dataPin, !!(val & (1 << i)));
    else    
      digitalWrite(m_dataPin, !!(val & (1 << (7 - i))));

    REG_PORT_OUT0 |= (1 << 19); //Set clockPin to HIGH
    REG_PORT_OUT0 &= ~(1 << 19); //Set clockPin to LOW     
  }
}

如您所见,我唯一无法重写的部分是:

digitalWrite(m_dataPin, !!(val & (1 << i)));

digitalWrite(m_dataPin, !!(val & (1 << (7 - i))));

如果你有解决我问题的想法,我会很乐意阅读它。

谢谢!

我终于找到了解决方案(但如果您看到我感兴趣的任何优化):

LowBitRegister.h

#ifndef LowBitRegister_h
#define LowBitRegister_h

#include "Arduino.h"


class LowBitRegister
{
  public:
    LowBitRegister(byte dataPin, byte clockPin, byte latchPin, uint8_t registerSize = 1); //Multiple registers cascade
    
    void sendData(uint8_t led);
    void lowShiftOut(uint8_t bitOrder, uint8_t val);

  private:
    byte m_dataPin;
    byte m_clockPin;
    byte m_latchPin;
    uint8_t m_registerSize;
};

#endif

LowBitRegister.cpp

#include "LowBitRegister.h"

//**************************************************************  

LowBitRegister::LowBitRegister(byte dataPin, 
                        byte clockPin, 
                        byte latchPin,
                        uint8_t registerSize)
:   m_dataPin(dataPin),
    m_clockPin(clockPin),
    m_latchPin(latchPin),
    m_registerSize(registerSize) //Number of register (if cascade)
{
  REG_PORT_DIR0 |= (1 << m_dataPin) | (1 << m_clockPin) | (1 << m_latchPin); //Set dataPin, clockPin and latchPin to OUTPUT
}

//************************************************************** 

void LowBitRegister::sendData(uint8_t led)
{
  led -= 1; //first LED is number 1
  
  REG_PORT_OUT0 &= ~(1 << m_latchPin); //Set latchPin to LOW
  
  for(int i = 1; i < m_registerSize + 1; i++){
    int registerNumber = m_registerSize - i; //The number of the register we're working on in the loop
    lowShiftOut(MSBFIRST, ~( 1 << (led - registerNumber*8) ) & 0xFF);
  }
  
  REG_PORT_OUT0 |= (1 << m_latchPin); //Set latchPin to HIGH
}

void LowBitRegister::lowShiftOut(uint8_t bitOrder, uint8_t val)
{
  uint8_t i;

  for (i = 0; i < 8; i++) {
    if (bitOrder == LSBFIRST){
      if(val & (1 << i))
        REG_PORT_OUT0 |= (1 << m_dataPin);
      else
        REG_PORT_OUT0 &= ~(1 << m_dataPin);
    }
    else {
      if (val & (1 << (7 - i)))
        REG_PORT_OUT0 |= (1 << m_dataPin);
      else
        REG_PORT_OUT0 &= ~(1 << m_dataPin);
    }
    REG_PORT_OUT0 |= (1 << m_clockPin); //Set clockPin to HIGH
    REG_PORT_OUT0 &= ~(1 << m_clockPin); //Set clockPin to LOW     
  }
}