Как расширить этот код для более четырех сдвиговых регистров 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();
}
@Abhishek, 👍0
Обсуждение1 ответ
Как упоминал 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
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Добро пожаловать в 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