ЭЛЕКТРОНИКА Мультиплексор

kalobyte

★★★✩✩✩✩
1 Янв 2020
724
148
еще раз повторю, во всяких там мультиплексорах, дешифраторах и прочих я практически 0.
сегодня это уже вчерашний день
если тебе надо много кнопок, то используется матрица

1588852351194.png
причем что интересно матрица 2х2 (т.е. 4 кнопки) использует 4 провода контроллера, что не имееет смысла в таком включении, т.к. проще с точки зрения кода искорости включить каждую кнопку на свой вывод контроллера и подцепить через резисторы к питанию все 4 вывода
ноесли мы увеличим матрицу 3х2 и займем 5 проводов, то кнопок уже можно подцепить 6 штук :eek:
вот она - точка профита

 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,266
1,303
Москва
Сдвиговый штука интересная видимо. Но мне пока не очень понятная.
Но я продолжил некоторую возню с мультиплексором. Простота его использования меня подкупает.
Большой практической цели нет, но в качестве примера работы пойдет.


Пример:
Butt 7 click
Butt 7 down
Butt 7 pressed
Butt 4 down
Butt 4 pressed
Butt 7 pressed
Butt 0 down
Butt 0 pressed
Butt 4 pressed
Butt 7 pressed
Butt 0 click
Butt 4 pressed
Butt 7 pressed
Butt 4 pressed
Butt 7 click
Butt 4 click
Butt 7 down
Butt 7 pressed
...
В примере выделено определение, это время чаще которого мультиплксор не будет опрашиваться.
Если не сделать, будет 20 мс.
Нажать на кнопку , что бы программа не отреагировала мне удавалось при 50 мс. при 30 уже нет. Тут многое зависит от кнопок.
Пример:
#define mult_time_per 10
#include "mult.h"

Multi_button m_But(10, 11, 12, 2);

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

void loop() {
  m_But.Tick();
  if (m_But.isChange)
    for (int i = 0; i < 8; i++)
    {
      if  (m_But.isClick(i)) Serial.println("Butt " + String(i) + " click");
      if  (m_But.isDown(i)) Serial.println("Butt " + String(i) + " down");
      if  (m_But.isPressed(i)) Serial.println("Butt " + String(i) + " pressed");
    }
}
}

Сама мини - библиотечка, если так можно сказать. Написана исключительно ради примера работы.
При нажатии отпускании кнопок (можно подключать не только кнопки) выставляется флаг isChange , разово, в сл. цикле он уберется.
Если были какие то изменения можно сделать проверку на то, что менялось.

mult.h:
#ifndef mult_time_per
#define mult_time_per 20
#endif

class Multi_button
{
  private:
    byte _old_pin_state;

    uint32_t last_tick_time = 0;
    byte _S0_pin;
    byte _S1_pin;
    byte _S2_pin;
    byte _IN_pin;
    byte _pin_state;
  public:

    Multi_button(byte s0, byte s1, byte s2, byte In_p)
    {
      _S0_pin = s0;
      _S1_pin = s1;
      _S2_pin = s2;
      _IN_pin = In_p;

      pinMode(_S0_pin, OUTPUT);
      pinMode(_S1_pin, OUTPUT);
      pinMode(_S2_pin, OUTPUT);
      pinMode(_IN_pin , INPUT);

    }
    bool isChange;

    bool isClick(byte N)
    {
      return (bitRead(_pin_state, N) != bitRead(_old_pin_state, N)) && bitRead(_old_pin_state, N);
    }

    bool isDown(byte N)
    {
      return (bitRead(_pin_state, N) != bitRead(_old_pin_state, N)) && bitRead(_pin_state, N);
    }

    bool isPressed(byte N)
    {
      return bitRead(_pin_state, N);
    }
    void Tick()
    {
      isChange = false;
      if (millis() - last_tick_time < mult_time_per) return;
      _old_pin_state = _pin_state;
      for (int i = 0; i < 8; i++)
      {
        digitalWrite(_S0_pin, (bool)(i & 1));
        digitalWrite(_S1_pin, (bool)(i & 2));
        digitalWrite(_S2_pin, (bool)(i & 4));

        bitWrite(_pin_state, i, digitalRead(_IN_pin));
      }
      isChange = _old_pin_state != _pin_state;
      last_tick_time = millis();
    }
};
 
Изменено:
  • Лойс +1
Реакции: kostyamat

Старик Похабыч

★★★★★★★
14 Авг 2019
4,266
1,303
Москва
В основном для наглядности.
Я еще думал переделывать под прямой доступ к регистрам, но пока оставил так. К регистрам смысл если все входы идут на один регистр. Там прям удобно за 1 раз все устанавливать, маску одну описать, но т.к. это "типа библиотека" надо предусматривать разные варианты... уже усложнение.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,266
1,303
Москва
Универсальность всегда много жрет :)
Но я там в начале написал , что практической цели нет, поэтому тьфу на эти 4 байта :D И это при том, что на 168 нано гоняю тест
Но спасибо! На самом деле не 4, а 20 байт программного кода


УПД.
А не сработало с указателями. 1 раз сработали нажатия на все кнопки по очереди и все. молчание ягнят.
 
Изменено:

Старик Похабыч

★★★★★★★
14 Авг 2019
4,266
1,303
Москва
Итак теперь тесты на стандартный ввод вывод при помощи универсальных функций и тест на использование портов.
Подключение то же, 2 порт на вход, 10, 11 и 12 на выход - задают кнопку.
1 ая строка задает использование портов непосредственно или через стандартные процедуры ввода/вывода

Код для теста:
//#define PORT 1
void setup() {
  Serial.begin(115200);
#ifdef PORT
  DDRB = DDRB | B11100;
  DDRD = DDRD & B11111011;
#else
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(2, INPUT);
#endif
}

void loop() {
  byte b = 0;
  for (int i = 0; i < 8; i++)
  {
#ifdef PORT
    PORTB = i << 2;
    b = (b << 1) | (PIND & B100) >> 2;
#else
    digitalWrite(10,(bool)(i&1));
    digitalWrite(11,(bool)(i&2));
    digitalWrite(12,(bool)(i&4));
    b = (b << 1) | digitalRead(2);
#endif
  }
  //Serial.println(b,BIN);
  ShowFPS();
}
//========================================================================================================================//
void ShowFPS()
{
  static uint32_t tm_m = 0;
  static uint32_t cnt_m = 0;
  cnt_m++;
  if ((millis() - tm_m) > 1000)
  {
    Serial.print("loop per sec: "); Serial.println(cnt_m);
    cnt_m = 0;
    tm_m = millis();
  }
}
Стандартные процедуры:
input: loop per sec: 6403
input: loop per sec: 6398
input: loop per sec: 6392
input: loop per sec: 6399
input: loop per sec: 6392
input: loop per sec: 6398
Использование памяти 2352 байт, 218 байт


прямое чтение портов:
ports: loop per sec: 154647
ports: loop per sec: 154544
ports: loop per sec: 154386
ports: loop per sec: 154545
ports: loop per sec: 154386
ports: loop per sec: 154544
ports: loop per sec: 154386
Использование памяти 1856 байт, 218 байт