Чтение из 74HC165

Код программы
#define DATA_PIN    10  // пин данных
#define LATCH_PIN   11  // пин защелки
#define CLOCK_PIN   12  // пин тактов синхронизации

void setup() {
  pinMode(DATA_PIN, INPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(LATCH_PIN, OUTPUT);
  digitalWrite(LATCH_PIN, HIGH);
  Serial.begin(9600);
}

byte readByte() {
  byte byteR = 0;
  digitalWrite(LATCH_PIN, LOW);
  digitalWrite(LATCH_PIN, HIGH);
  for (int i = 7; i >= 0; i--) {
    if (digitalRead(DATA_PIN)) bitSet(byteR, i);
    digitalWrite(CLOCK_PIN, HIGH); 
    digitalWrite(CLOCK_PIN, LOW);
  }
  return byteR;
}

void loop() {
  Serial.println(in_165_shift(), BIN);
  Serial.println(readByte(), BIN);
  delay(1000);
}

byte in_165_shift() {
  digitalWrite(LATCH_PIN, LOW); 
  digitalWrite(LATCH_PIN, HIGH);
  return shiftIn(DATA_PIN, CLOCK_PIN, LSBFIRST ); 
}

В каких-то примерах используются три пина ардуино, в каких-то четыре.
Функция byte readByte() читает - 10000001
Функция byte in_165_shift() читает- 1000000
Как правильно?

Установите на вход “несимметричное” значение, например 193,
чтобы убедиться в правильности чтения, младший бит должен первым быть

2 лайка

@Irinka, я не большой специалист в этой микросхеме, но думаю, что заводить пин 15 на землю - очень плохая идея. Он нужен, чтобы не было ложных сдвигов.

У меня отлично работает вот такой

скетч
static constexpr uint8_t pinINH = 4;
static constexpr uint8_t pinCLK = 5;
static constexpr uint8_t pinSHLD = 6;
static constexpr uint8_t pinSO = 7;

inline void clkHIGH(void) { digitalWrite(pinCLK, HIGH); }
inline void shldLOW(void) { digitalWrite(pinSHLD, LOW); }
inline void shldHIGH(void) { digitalWrite(pinSHLD, HIGH); }
inline void inhLOW(void) { digitalWrite(pinINH, LOW); }
inline void inhHIGH(void) { digitalWrite(pinINH, HIGH); }
inline void shldTICK(void) { shldLOW(); shldHIGH(); }

uint8_t readData(void) {
   shldTICK();
   clkHIGH();
   inhLOW();
   const uint8_t result = shiftIn(pinSO, pinCLK, MSBFIRST);
   inhHIGH();
   return result;
}

void setup(void) {
   pinMode(pinINH, OUTPUT);
   inhHIGH();
   pinMode(pinCLK, OUTPUT);
   pinMode(pinSHLD, OUTPUT);
   shldHIGH();
   pinMode(pinSO, INPUT);
   
   Serial.begin(9600);
   Serial.println("Let's go on!");
}


void loop(void) {
   static uint8_t oldValue = 0;
   const uint8_t value = readData();
   if (value != oldValue) {
      Serial.print((value < 16) ? "0x0" : "0x");
      Serial.println(value, HEX);
      oldValue = value;
   }
}

При вот такой

схеме

Всё показывает, при включении/выключении того или иного тумблера адекватно новое значение выводит.

А если убрать всю работу с INH и притянуть его к земле - тут же начинает лишний бит читать, попробуйте.

1 лайк

Спасибо. Всё таки 4 пина)

В теме Класс для чтения резисторной клавиатуры Вы сказали что:

constexpr

Указание компилятору, что все вычисления, которые там написаны, он должен выполнить сам, а в код вставить только готовый результат.

static constexpr uint8_t pinINH = 4;

А здесь же мы ничего не считаем, заранее знаем номер пина.
И почему static constexpr ?

а зачем в 15 строке, клок в HIGH выставляется?

что-то мне подсказывает если при inh=0 инвертировать такты то лишний бит пропадет
upd, был не прав - посмотрел на дш без очков, в очках все по-другому :wink:

На всякий случай , всё же проверьте, Ваша функция
readByte(), возможно, будет работать и на 3-х пинах, в Proteus глянул, всё норм. Микросхемы , чтобы проверить в железе - увы , нет

P.S. Если что, я ещё более

лишь Proteus и datasheet)))

А не приладить ли сюда SPI? Так-то как раз его задача. Хоть аппаратный, хоть программный.

От SPI есть одно неприятное отличие: отсутствие CS.

Главная разница между:

#define A 11
// и
constexpr uint8_t А = 11;

в том, что во втором случае явно указан тип данных, а в первом - нет. это может сыграть свою роль, например, при вызове перегруженной функции. Да и просто, мне комфортнее, когда я знаю все типы

ХЗ. Но если этого не делать, то самый младший бит всегда ноль, попробуйте. Там в ДШ есть загадочная ремарка, которую я не понимаю:

Вполне возможно. Если будете пробовать, скажите, пожалуйста.

Так по сути shiftIn и есть SPI, а если честный SPI присобачивать, то там придётся акромя MISO, ещё и MOSI задействовать, ему же надо что-то слать, чтобы ответ получить. Он же тоже сдвиговый регистр.

INH за него.

Да ну бросьте. Ну будет он выдавать в “воздух” и что с того. SPI же не всегда двунаправленный нужен.

Да, ничего, просто пин на ровном месте занят. Если это ничему не мешает, то почему бы и нет?

А почему static,а не const?

constexpr уже предполагает const. Можно ещё и const приписать, ошибкой не будет, но это “масляное масло”. А static для глобальной переменной означает, что “не видно из других файлов”. В данном случае это без разницы, но тут привычка работает: “нужно, чтобы было видно? нет? пиши static

4 лайка

Спасибо. С Наступающим новым годом)

Сейчас проверила

#include "setting_pins.h"

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

void loop() {
  Serial.println(num);
}

setting_pins.h"

static constexpr uint8_t num = 3; 

Монитор порта печатает 3

Я что-то не так поняла про другие файлы?)

Полагаю, что имелись в виду “другие compilation unit”. Header-файл включаемый, при компиляции он образует единое целое с .cpp/.ino

А вот ежели взять a.cpp и b.cpp, в первый поместить static global variable, то из второго его низачто не увидеть.

2 лайка

Спасибо

@Irinka , пора заготовки к салатам делать.
Моя всегда так делает (и сегодня тоже).
Завтра только из холодильника достать и «замесить» нужно будет :smiley:

Лайхаки от старпёров (Хотя лично я ещё очень молод в душе, а супруга моя - никогда и не старела!).

1 лайк