Как расширить этот код для более четырех сдвиговых регистров 74hc165? Работает максимум с 4 сдвиговыми регистрами 74hc165 одновременно

#define NUMBER_OF_SHIFT_CHIPS   4
#define DATA_WIDTH   NUMBER_OF_SHIFT_CHIPS * 8

int LoadPin    = 9;
int EnablePin  = 8;
int DataPin    = 11;
int ClockPin   = 12;

unsigned long pinValues;
unsigned long oldPinValues;

void setup()
{
  Serial.begin(9600);

  pinMode(LoadPin, OUTPUT);
  pinMode(EnablePin, OUTPUT);
  pinMode(ClockPin, OUTPUT);
  pinMode(DataPin, INPUT);

  digitalWrite(ClockPin, LOW);
  digitalWrite(LoadPin, HIGH);

  pinValues = read_shift_regs();
  print_byte();
  oldPinValues = pinValues;
}

void loop()
{
  pinValues = read_shift_regs();
  if (pinValues != oldPinValues)
  {
    print_byte();
    oldPinValues = pinValues;
  }
}

unsigned long read_shift_regs()
{
  long bitVal;
  unsigned long bytesVal = 0;

  digitalWrite(EnablePin, HIGH);
  digitalWrite(LoadPin, LOW);
  delayMicroseconds(5);
  digitalWrite(LoadPin, HIGH);
  digitalWrite(EnablePin, LOW);

  for (int i = 0; i < DATA_WIDTH; i++)
  {
    bitVal = digitalRead(DataPin);
    bytesVal |= (bitVal << ((DATA_WIDTH - 1) - i));

    digitalWrite(ClockPin, HIGH);
    delayMicroseconds(5);
    digitalWrite(ClockPin, LOW);
  }

  return (bytesVal);
}

void print_byte() {
  byte i;
  Serial.println("*Shift Register Values:*\r\n");

  for (byte i = 0; i <= DATA_WIDTH - 1; i++)
  {
    Serial.print(pinValues >> i & 1, BIN);

    Serial.print("  ");

  }
  Serial.print("\n");
  Serial.println(); Serial.println();
}

, 👍0

Обсуждение

Добро пожаловать в Arduino: SE. Откуда вы взяли эту версию кода?, @sempaiscuba

возможно, это не проблема с кодом, @jsotola

А что происходит, когда вы используете более 4 (последовательно соединяя больше регистров сдвига и устанавливая соответственно NUMBER_OF_SHIFT_CHIPS)? Каково фактическое описание проблемы? Что вы ожидали, что произойдет, и что произошло на самом деле? Каков был последовательный выход и ожидаемый последовательный выход?, @chrisl

Похоже, что ваша функция read_shift_regs () возвращает значение unsigned long, которое состоит из 32 бит. Каждый регистр сдвига считывает обратно 8 бит, так что с помощью 4 из этих регистров сдвига вы заполните все биты 32-битной длины без знака. Если вы попытаетесь прочитать более 4 регистров, вы потеряете ранее прочитанные биты. Решение состоит в том, чтобы создать функцию, которая может возвращать более 32 бит., @StarCat

Я бы просто добавил еще одну цепочку сдвиговых регистров. Схема поможет лучше понять, что вы делаете., @Gil

После того, как я поставил 'NUMBER_OF_SHIFT_CHIPS' равным 5, 1-й регистр сдвига не работает, но начинает работать 5-й. Также, когда я ставлю 'NUMBER_OF_SHIFT_CHIPS' равным 6, то 1-й и 2-й сдвиговые регистры не работают, но остальные четыре сдвиговых регистра начинают работать. Итак, я думаю, что @StarCat прав. Что нужно изменить в этом коде?, @Abhishek

Вам нужно понять код, чтобы подумать о решении. Есть несколько возможных решений, но вы должны попробовать те, которые вы понимаете. Вы можете начать с размышления о том, как "организовать" более 32 бит. Как вы обнаружили, unsigned long не может этого сделать, возможно, подойдет массив unsigned char или uint8_t. -- Обычно мы не даем рекомендаций, потому что это приводит к дискуссиям, основанным на мнениях, которые не одобряются., @the busybee


1 ответ


3

Как упоминал StarCat в комментариях, вы возвращаете прочитанное значение как значение без знака long, которое может содержать ровно 4 байта. При попытке записать в него больше с помощью вашего текущего кода вы потеряете предыдущие данные. Итак, вам нужна структура данных, способная вместить все данные, которые вы хотите прочитать.

Я предлагаю вам сделать это подобно функции shiftIn() фреймворка Arduino: используйте DATA_WIDTH из 8 бит (1 байт) и заключите цикл чтения в другой цикл for , где вы перебираете NUMBER_OF_SHIFT_CHIPS, получая ровно один байт от каждого чипа и помещая его в массив byte (он же uint8_t). Есть несколько способов сделать это, но я опишу только один, не обязательно лучший для вашей ситуации.

Сначала объявите массив байт в глобальной области видимости. Он должен быть размером в байт NUMBER_OF_SHIFT_CHIPS. Мы инициализируем данные равными нулю:

byte shift_data[NUMBER_OF_SHIFT_CHIPS] = {0};

Установите DATA_WIDTH равным 8 битам:

#define DATA_WIDTH   8

Теперь загляните в read_shift_regs(). Заключите цикл for в другой цикл for, повторяющий NUMBER_OF_SHIFT_CHIPS, и используйте этот индекс для записи данных в соответствующий байт в shift_data (используя shift_data[j] с соответствующим индексом j). Когда мы пишем глобальный массив, нам не нужно ничего возвращать, поэтому вы можете сделать функцию недействительной (если только вы не хотите вернуть какую-то другую информацию).

void read_shift_regs()
{
  long bitVal;

  digitalWrite(EnablePin, HIGH);
  digitalWrite(LoadPin, LOW);
  delayMicroseconds(5);
  digitalWrite(LoadPin, HIGH);
  digitalWrite(EnablePin, LOW);
  for(int j = 0; j < NUMBER_OF_SHIFT_CHIPS; j++){
    for (int i = 0; i < DATA_WIDTH; i++)
    {
      bitVal = digitalRead(DataPin);
      shift_data[j] |= (bitVal << ((DATA_WIDTH - 1) - i));

      digitalWrite(ClockPin, HIGH);
      delayMicroseconds(5);
      digitalWrite(ClockPin, LOW);
    }
  }
}

Затем измените все строки на

pinValues = read_shift_regs();

для чтения функции read_shift_regs();

И, наконец, чтобы действительно использовать прочитанные значения, теперь вам нужно получить доступ к полному массиву, а не к одной переменной. Я оставляю это на ваше усмотрение. По сути, это снова просто перебор всех элементов массива.

Примечание:

  • Я никоим образом не тестировал приведенный выше код. Это больше связано с объяснением принципа.
  • Можно также обрабатывать массив с параметрами, но если вы не знаете, как использовать массивы в качестве параметров, то это может привести к множеству других ошибок. Так что я этого не предлагал.
,

использование функции void перед read_shift_regs() выдает ошибку "значение void не игнорируется, как должно быть". Какой тип данных я должен использовать здесь и почему? Кроме того, для печати выходных данных я использую цикл for для возврата shift_data[j], но выходные данные не меняются. P.S: Возможно, я здесь ошибаюсь, потому что я новичок в кодировании arduino., @Abhishek

Если вы посмотрите на мою реализацию функции, вы увидите, что я не использую return. Функции не нужно ничего возвращать, потому что данные уже глобально доступны в массиве. И вы получаете эту ошибку, потому что у вас, вероятно, все еще есть pinValues = read_shift_regs (); где-то. Как я и указывал, вам нужно удалить все перед вызовом функции в этой строке (так что никакого назначения с помощью = ), @chrisl

Что вы подразумеваете под "использовать цикл for для возврата shift_data[i]"? Вы можете вернуться только один раз, а не несколько раз, @chrisl

Если вы посмотрите на приведенный выше код в цикле void, я установил if(pinValues!=oldpinValues), то выходные байты печатаются для полной матрицы 8 x 8. Я не могу получить результат здесь. Можете ли вы предложить способ считывания значений таким образом, чтобы я мог видеть их на последовательном мониторе? Таким образом, я могу использовать его в качестве эталона для вывода на печать., @Abhishek