Найти в Дзене
Shema_Tehnik

Собираем тестер логических микросхем на Arduino

Мне понадобился тестер логических микросхем и решил сделать на базе Arduino. Он не только полезен в хозяйстве электронщика, но и помогает глубоко понять принцип работы цифровой логики (серий К155, К176, К561 и их зарубежные аналоги). Принцип работы прост: Arduino подает комбинации сигналов (0 и 1) на входные пины микросхемы и считывает результат с выходных пинов, сверяя их с «таблицей истинности». Большинство логических микросхем имеют 14 или 16 ног. На пине D13 у нас стоит на плате светодиод, его нужно выпаять, чтобы он нам через резистор на землю помехи не давал. --- РАСПИНОВКА ЭНКОДЕРА --- ENC_CLK - 13 ENC_DT   - A1 ENC_SW   - A6 --- РАСПИНОВКА OLED --- Пины (SDA) - A4 Пины (SCL) - A5 Подавать питание будем программно, вы сможете проверять любые микросхемы (даже те, у которых питание посередине), а также защитить чип: ток будет подаваться только в момент теста. Чтобы Arduino могла сама подавать «питание» и «землю» на любые ножки, мы будем использовать цифровые пины в реж
Оглавление

Мне понадобился тестер логических микросхем и решил сделать на базе Arduino. Он не только полезен в хозяйстве электронщика, но и помогает глубоко понять принцип работы цифровой логики (серий К155, К176, К561 и их зарубежные аналоги).

Принцип работы прост: Arduino подает комбинации сигналов (0 и 1) на входные пины микросхемы и считывает результат с выходных пинов, сверяя их с «таблицей истинности».

Внимание! Этот проект в стадии разработки и я думаю, что мы этот проект сделаем до конца!

1. Что понадобится для сборки

  • Arduino Nano
  • OLED - дисплей (I2C)
  • Энкодер со встроенной кнопкой
  • Макетная плата
  • Соединительные провода

2. Схема подключения

Большинство логических микросхем имеют 14 или 16 ног.

На пине D13 у нас стоит на плате светодиод, его нужно выпаять, чтобы он нам через резистор на землю помехи не давал.

--- РАСПИНОВКА ЭНКОДЕРА ---

ENC_CLK - 13

ENC_DT   - A1

ENC_SW   - A6

--- РАСПИНОВКА OLED ---

Пины (SDA) - A4

Пины (SCL) - A5

Подавать питание будем программно, вы сможете проверять любые микросхемы (даже те, у которых питание посередине), а также защитить чип: ток будет подаваться только в момент теста.

Чтобы Arduino могла сама подавать «питание» и «землю» на любые ножки, мы будем использовать цифровые пины в режимах OUTPUT HIGH (для VCC) и LOW (для GND).

Схема подключения контактов ZIF-панели

Теперь нам нужно задействовать все 16 контактов ZIF-панели. Поскольку у Nano не хватает цифровых пинов для 16 линий + OLED + энкодер, мы используем аналоговые входы как цифровые.

Распиновка:

-2

Важно по A6 и A7: они не могут работать на выход. Поэтому на ZIF-панель их подавать нельзя. Мы используем их только для кнопок.

При установке 14-пинового чипа в 16-пиновую панель получается следующее соответствие:

  • Левая сторона: 1-7 пины чипа попадают точно в 1-7 пины ZIF.
  • Правая сторона: Происходит смещение. 8-я ножка чипа попадает в 10-й пин ZIF, а 14-я ножка чипа (питание) — в 16-й пин ZIF.
  • Свободные пины: 8 и 9 пины на 16-пиновой панели остаются пустыми.

То есть 1-я ножка любого чипа вставляется в первую (начало) панельки.

Режим Меню

Главное меню

Отображение версии тестера, выбор автосканирования микросхемы, или ручной режим, выбираете какую серию микросхемы выбрать.

-3

Далее количество ножек 14 или 16

-4

Крутим энкодер и выбираем из отфильтрованного списка чип который нужен (советский и зарубежный аналог), чуть ниже экрана высвечивается количество логических элементов

-5

Прокрутка меню

-6

На экране высвечивается название чипа, чертёж микросхемы с распиновкой ножек с наружи, а внутри отображение питания +- , отображение входов и выходов ( Input, Output ), а также отображение неисправной ножки знаком (Х), и снизу надпись Fail PIN: 3

-7

А тут отображение исправного чипа Status OK

-8

Код в пробном периоде

Вы просто копируйте этот код и вставляйте в свою среду и тестируйте

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#include <avr/pgmspace.h>

#define SCREEN_WIDTH 128

#define SCREEN_HEIGHT 64

#define OLED_ADDR     0x3C

// --- РАСПИНОВКА ЭНКОДЕРА ---

#define ENC_CLK 13

#define ENC_DT  A1

#define ENC_SW  A6

// Типы пинов

#define P_VCC 0

#define P_GND 1

#define P_IN 2

#define P_OUT 3

#define P_NC 255

// Порядок пинов Arduino для 1-16 ножек ZIF панели

const uint8_t zif[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, A0, A2, A3, 1, 0};

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

struct Chip {

char name[19];

char desc[13];

uint8_t family;

uint8_t pins;

uint8_t algo;

uint8_t map[16];

};

// --- СПРАВОЧНИК МИКРОСХЕМ ---

const Chip database[] PROGMEM = {

// КАТЕГОРИЯ: TTL (K155 / 74xx)

{"K155LA1 / 7420",  "2x 4I-NE",        0, 14, 0,  {2,2,255,2,2,3, 1,255, 255, 3,2,2,255,2,2, 0}},

{"K155LA2 / 7430",  "1x 8I-NE",        0, 14, 0,  {2,2,2,2,2,2, 1,255, 255, 3,255,255,2,2,255, 0}},

{"K155LA3 / 7400",  "4x 2I-NE",        0, 14, 0,  {2,2,3, 2,2,3, 1,255, 255, 3,2,2, 3,2,2, 0}},

{"K155LA4 / 7410",  "3x 3I-NE",        0, 14, 0,  {2,2,2,2,2,3, 1,255, 255, 3,2,3,2,2,2, 0}},

{"K155LA6 / 7440",  "2x 4I-NE DRV",    0, 14, 0,  {2,2,255,2,2,3, 1,255, 255, 3,2,2,255,2,2, 0}},

{"K155LA7 / 7406",  "2x 4I-NE OK",     0, 14, 0,  {2,2,255,2,2,3, 1,255, 255, 3,2,2,255,2,2, 0}},

{"K155LA8 / 7401",  "4x 2I-NE OK",     0, 14, 0,  {3,2,2, 3,2,2, 1,255, 255, 2,2,3, 2,2,3, 0}},

{"K155LA10/ 7412",  "3x 3I-NE OK",     0, 14, 0,  {2,2,2,2,2,3, 1,255, 255, 3,2,3,2,2,2, 0}},

{"K155LA11/ 7426",  "4x 2I-NE HV",     0, 14, 0,  {2,2,3, 2,2,3, 1,255, 255, 3,2,2, 3,2,2, 0}},

{"K155LA12/ 7437",  "4x 2I-NE PWR",    0, 14, 0,  {2,2,3, 2,2,3, 1,255, 255, 3,2,2, 3,2,2, 0}},

{"K155LA13/ 7438",  "4x 2I-NE SCH",    0, 14, 0,  {2,2,3, 2,2,3, 1,255, 255, 3,2,2, 3,2,2, 0}},

{"K155LI1 / 7408",  "4x 2I",           0, 14, 1,  {2,2,3, 2,2,3, 1,255, 255, 3,2,2, 3,2,2, 0}},

{"K155LN1 / 7404",  "6x NOT",          0, 14, 3,  {2,3,2,3,2,3, 1, 255, 255, 3,2,3,2,3,2, 0}},

{"K155TV1 / 7472",  "JK-TRIG + AND",   0, 14, 7,  {2,2,2,3,3,2, 1,255, 255, 2,2,2,2,0,1, 0}},

{"K155TV15 / 74107", "2x JK-TRIG CLR", 0, 14, 7,  {2,3,3,2,0,2, 1,255, 255, 3,3,2,2,2,1, 0}},

{"K155LP5 / 7486",  "4x XOR",          0, 14, 10, {2,2,3, 2,2,3, 1,255, 255, 3,2,2, 3,2,2, 0}},

{"K155LP9 / 7407",  "6x BUFF. OK",     0, 14, 3,  {2,3,2,3,2,3, 1,255, 255, 3,2,3,2,3,2, 0}},

{"K155LP10 / 74125","4x 3-ST BUFF",    0, 14, 11, {2,2,3, 2,2,3, 1,255, 255, 3,2,2, 3,2,2, 0}},

{"K155LP11 / 74126","4x 3-ST BUFF",    0, 14, 11, {2,2,3, 2,2,3, 1,255, 255, 3,2,2, 3,2,2, 0}},

{"K155TM2 / 7474",  "2x D-TRIG",       0, 14, 6,  {2,2,3,3,2,2, 1, 255, 255, 2,2,3,3,2,2, 0}},

{"K155TM5 / 7475",  "4x D-LATCH",      0, 16, 6,  {3,3,2,2,0,0,2, 1, 2,0,0,2,2,3,3, 0}},

{"K155TM7 / 7477",  "4x D-LATCH",      0, 14, 6,  {3,2,2,0,0,2, 1,255, 255, 2,0,0,2,2,3, 0}},

{"K155TM8 / 74175", "4x D-TRIG CLR",   0, 16, 6,  {1,3,3,2,2,3,3, 1, 2,3,3,2,2,3,3, 0}},

{"K155TM9 / 74174", "6x D-TRIG CLR",   0, 16, 6,  {1,3,2,2,3,2,2, 1, 3,2,2,3,2,3,3, 0}},

{"K155IE2 / 7490",  "DEC COUNTER",     0, 14, 20, {2,3,3,255,0,2,2, 255, 255, 1,2,2,3,2,2, 255}},

{"K155IE4 / 7492",  "DIV12 COUNT",     0, 14, 20, {2,255,255,255,0,2,2,255, 255, 3,3,3,1,3,2,2}},

{"K155IE5 / 7493",  "BIN COUNTER",     0, 14, 20, {2,2,2,255,0,2,2,255, 255, 3,3,3,1,3,2,2}},

{"K155IE6 / 74192", "UD DEC COUNT",    0, 16, 20, {2,3,3,2,2,3,3, 1, 1,2,2,2,3,3,2, 0}},

{"K155IE7 / 74193", "UD BIN COUNT",    0, 16, 20, {2,3,3,2,2,3,3, 1, 1,2,2,2,3,3,2, 0}},

{"K155IE8 / 7497",  "FREQ DIVIDER",    0, 16, 20, {2,3,3,3,3,3,2, 1, 2,2,2,2,2,2,2, 0}},

{"K155IE9 / 74160", "SYNC DEC COUNT",  0, 16, 20, {2,2,3,3,3,3,2, 1, 2,2,3,3,2,2,2, 0}},

{"K155ID1 / 7441",  "NIXIE DRIVER",    0, 16, 5,  {3,3,3,3,0,3,3,3, 3,3,3,1,2,2,2,2}},

{"K155ID4 / 74155", "2x 2-4 DECODER",  0, 16, 5,  {2,2,2,3,3,3,3, 1, 3,3,3,3,2,2,2, 0}},

{"K155ID7 / 74138", "3-8 DECODER",     0, 16, 5,  {2,2,2,2,2,2,3, 1, 3,3,3,3,3,3,3, 0}},

{"K155ID10 / 74145", "4-10 BCD DEC",   0, 16, 5,  {3,3,3,3,3,3,3, 1, 3,3,3, 2,2,2,2, 0}},

{"K155KP2 / 74153", "2x MUX 4-1",      0, 16, 12, {2,2,3,2,2,2,3, 1, 3,2,2,2,3,2,2, 0}},

{"K155KP5 / 74152", "MUX 8-1",         0, 14, 12, {2,2,2,2,2,2, 1,255, 255, 3,2,2,2,2,2, 0}},

{"K155KP7 / 74151", "MUX 8-1",         0, 16, 12, {3,3,2,2,2,2,2, 1, 2,2,2,2,2,2,2, 0}},

{"K155KP11/ 74257", "4x MUX 2-1 3S",   0, 16, 12, {2,2,2,3,2,2,3, 1, 3,2,2,3,2,2,2, 0}},

{"K155PR6 / 74184", "BCD-BIN CNV",     0, 16, 52, {2,2,2,2,2,3,3, 1, 3,3,3,2,2,2,3, 0}},

{"K155PR7 / 74185", "BIN-BCD CNV",     0, 16, 52, {2,2,2,2,2,3,3, 1, 3,3,3,2,2,2,3, 0}},

// КАТЕГОРИЯ: K561 (40xx)

{"K561LA7 / 4011",  "4x 2I-NE",        1, 14, 0,  {2,2,3, 3,2,2, 1,255, 255, 2,2,3, 3,2,2, 0}},

{"K561LA8 / 4012",  "2x 4I-NE",        1, 14, 0,  {3,2,2,2,2,255,1,255, 255, 255,2,2,2,2,3, 0}},

{"K561LA9 / 4023",  "3x 3I-NE",        1, 14, 0,  {2,2,2,2,2,3, 1,255, 255, 3,2,255,2,2,3, 0}},

{"K561LA10 / 4068", "1x 8I-NE",        1, 14, 0,  {255,2,2,2,2,255,1,255, 255, 255,2,2,2,2,3, 0}},

{"K561LE5 / 4001",  "4x 2ILI-NE",      1, 14, 4,  {2,2,3, 3,2,2, 1,255, 255, 2,2,3, 3,2,2, 0}},

{"K561LE6 / 4002",  "2x 4ILI-NE",      1, 14, 4,  {3,2,2,2,2,255,1,255, 255, 255,2,2,2,2,3, 0}},

{"K561LE10 / 4025", "3x 3ILI-NE",      1, 14, 4,  {2,2,3, 2,2,3, 1,255, 255, 3,2,2,2,2,2, 0}},

{"K561LN1 / 4009",  "6x NOT BUFF",     1, 16, 3,  {0,3,2,3,2,3,2, 1, 2,3,2,3,2,3,2, 0}},

{"K561LN2 / 4049",  "6x NOT BUFF",     1, 16, 3,  {0,3,2,3,2,3,2, 1, 2,3,2,3,2,3,2, 255}},

{"K561LN3 / 4050",  "6x BUFF",         1, 16, 15, {0,3,2,3,2,3,2, 1, 2,3,2,3,2,3,2, 255}},

{"K561TM2 / 4013",  "2x D-TRIG",       1, 14, 6,  {3,3,2,2,2,2, 1,255, 255, 2,2,2,2,3,3, 0}},

{"K561TM3 / 4042",  "4x D-LATCH",      1, 16, 6,  {3,2,3,2,0,2,2, 1, 2,3,2,3,2,2,2, 0}},

{"K561IE8 / 4017",  "DEC COUNTER",     1, 16, 21, {3,3,3,3,3,3,3, 1, 3,3,3,3,2,2,2, 0}},

{"K561IE9 / 4022",  "OCT COUNTER",     1, 16, 21, {3,3,3,3,3,255,3, 1, 255,3,3,2,2,2,2, 0}},

{"K561IE10 / 4520", "2x BIN COUNT",    1, 16, 20, {2,2,3,3,3,3,2, 1, 2,2,3,3,3,3,2, 0}},

{"K561IE11 / 4510", "UD DEC COUNT",    1, 16, 20, {2,3,2,2,2,3,3, 1, 2,2,3,3,2,3,3, 0}},

{"K561IE14 / 4029", "UD BIN/DEC",      1, 16, 20, {2,3,2,2,2,3,3, 1, 2,2,3,3,2,3,3, 0}},

{"K561IE16 / 4020", "14-BIT DIV",      1, 16, 20, {3,3,3,3,3,3,3, 1, 3,3,3,3,2,2,3, 0}},

{"K561KT1 / 4016",  "4x ANALOG SW",    1, 14, 13, {2,2,3, 3,2,2, 1,255, 255, 2,2,3, 3,2,2, 0}},

{"K561KT3 / 4066",  "4x ANALOG SW",    1, 14, 13, {2,2,3, 3,2,2, 1,255, 255, 2,2,3, 3,2,2, 0}},

{"K561KP1 / 4052",  "2x MUX 4-1",      1, 16, 12, {3,3,3,3,3,0,3, 1, 3,3,3,3,3,2,2, 0}},

{"K561KP2 / 4051",  "MUX 8-1",         1, 16, 12, {3,3,3,3,3,3,0, 1, 3,3,3,2,2,2,3, 0}},

{"K561KP3 / 4053",  "3x MUX 2-1",      1, 16, 12, {3,3,3,3,3,3,0, 1, 3,3,2,2,2,3,3, 0}},

{"K561IV1 / 4532",  "8-3 ENCODER",     1, 16, 51, {2,2,2,2,2,3,3, 1, 2,2,2,2,2,3,3, 0}},

{"K561TL1 / 4093",  "4x 2I-NE SCHM",   1, 14, 0,  {2,2,3, 3,2,2, 1,255, 255, 2,2,3, 3,2,2, 0}},

{"K561TL2 / 40106", "6x NOT SCHMITT",  1, 14, 3,  {2,3,2,3,2,3, 1,255, 255, 3,2,3,2,3,2, 0}},

{"K561IP2 / 4008",  "4-BIT ADDER",     1, 16, 25, {2,2,2,3,2,3,2, 1, 3,3,3,2,2,2,2, 0}},

{"K561IP3 / 4063",  "4-BIT COMP",      1, 16, 50, {2,2,2,2,3,3,3, 1, 2,2,2,2,2,2,2, 0}},

{"K561IP5 / 40101", "9-BIT PARITY",    1, 14, 26, {2,2,2,2,2,2, 1,255, 255, 3,3,2,2,2,3, 0}},

{"K561IR2 / 4015",  "2x 4BIT SHIFT",   1, 16, 30, {2,3,3,3,2,2,3, 1, 2,3,3,3,3,2,2, 0}},

{"K561IR9 / 4035",  "4-BIT UNIV REG",  1, 16, 30, {2,2,2,3,2,1,2, 1, 3,2,3,2,3,2,2, 0}},

{"K561IR11 / 4014", "8-BIT P-S REG",   1, 16, 30, {2,3,2,2,2,3,2, 1, 2,2,2,2,2,2,2, 0}},

{"K561IR12 / 4094", "8-BIT SHIFT-L",   1, 16, 30, {3,2,2,3,3,3,3, 1, 3,3,3,3,2,2,2, 0}},

{"K561LS2 / 4019",  "4x MUX/OR",       1, 16, 2,  {2,2,3,2,2,3,2, 1, 2,3,2,2,3,2,2, 0}},

// КАТЕГОРИЯ: K176

{"K176LA7 / 4011",  "4x 2I-NE",        2, 14, 0,  {2,2,3, 3,2,2, 1,255, 255,2,2,3, 3,2,2, 0}},

{"K176LA8 / 4012",  "2x 4I-NE",        2, 14, 0,  {3,2,2,2,2,255,1,255, 255, 255,2,2,2,2,3, 0}},

{"K176LA9 / 4023",  "3x 3I-NE",        2, 14, 0,  {2,2,2,2,2,3, 1,255, 255, 3,2,255,2,2,3, 0}},

{"K176IE1", "6-BIT BIN COUNT",         2, 14, 20, {2,3,3,3,3,3, 1,255, 255, 2,2,2,2,2,2, 0}},

{"K176IE4", "COUNT TO 10/7SEG",        2, 14, 41, {3,3,3,3,3,2, 1,255, 255, 2,3,3,3,3,3, 0}},

{"K176IE5", "15-BIT CLOCK DIV",        2, 14, 40, {2,2,3,2,2,255,1,255, 255, 255,2,2,2,2,2, 0}},

{"K176IE12", "CLOCK DIV/COUNT",        2, 16, 40, {3,3,3,2,2,2,2, 1, 3,3,3,3,2,2,2, 0}},

{"K176IE13", "CLOCK W/ ALARM",         2, 16, 40, {2,2,3,3,2,2,2, 1, 2,2,2,2,3,3,2, 0}},

{"K176IE18", "CLOCK DIV/SOUND",        2, 16, 40, {3,3,3,2,2,2,2, 1, 3,3,3,3,2,2,2, 0}},

{"K176ID2", "BIN-7SEG DECODER",        2, 16, 45, {2,2,2,2,2,2,2, 1, 3,3,3,3,3,3,3, 0}},

{"K176ID3", "BIN-7SEG HIGH V",         2, 16, 45, {2,2,2,2,2,2,2, 1, 3,3,3,3,3,3,3, 0}},

{"K176LE5 / 4001",  "4x 2ILI-NE",      2, 14, 4,  {2,2,3, 3,2,2, 1,255, 255, 2,2,3, 3,2,2, 0}},

{"K176LE6 / 4002",  "2x 4ILI-NE",      2, 14, 4,  {3,2,2,2,2,255,1,255, 255, 255,2,2,2,2,3, 0}},

{"K176LE10 / 4025", "3x 3ILI-NE",      2, 14, 4,  {2,2,3, 2,2,3, 1,255, 255, 3,2,2,2,2,2, 0}},

{"K176TM1 / 4013",  "2x D-TRIG",       2, 14, 6,  {3,3,2,2,2,2, 1,255, 255, 2,2,2,2,3,3, 0}},

{"K176TM2 / 4013",  "2x D-TRIG",       2, 14, 6,  {3,3,2,2,2,2, 1,255, 255, 2,2,2,2,3,3, 0}},

{"K176TL1", "4x 2I-NE SCHMITT",        2, 14, 0,  {2,2,3, 3,2,2, 1,255, 255, 2,2,3, 3,2,2, 0}},

};

const int chipCount = sizeof(database) / sizeof(Chip);

enum State { MAIN_MENU, PIN_MENU, LIST_MENU, TEST_RESULT };

State currentState = MAIN_MENU;

int selMode = 0, selPin = 14, fCount = 0, fPos = 0, selectedIdx = 0;

int filteredIdx[80];

int failedPin = -1;

int lastClk;

bool buttonPressed = false;

// --- ФУНКЦИИ УПРАВЛЕНИЯ ---

void pulse(int pin) {

digitalWrite(zif[pin], HIGH); delayMicroseconds(10);

digitalWrite(zif[pin], LOW);  delayMicroseconds(10);

}

int runLogicTest(Chip& c) {

for (int i = 0; i < 16; i++) {

if (c.map[i] == P_OUT) {

// --- ТЕСТ ДЛЯ ПРОСТОЙ ЛОГИКИ (Algo 0, 1, 3, 4, 10) ---

if (c.algo == 0 || c.algo == 1 || c.algo == 3 || c.algo == 4 || c.algo == 10) {

for (byte t = 0; t < 4; t++) {

bool inA = t & 1;

bool inB = t & 2;

for (int j = 0; j < 16; j++) {

if (c.map[j] == P_IN) digitalWrite(zif[j], (j % 2 == 0) ? inA : inB);

}

delayMicroseconds(50);

bool result = digitalRead(zif[i]);

bool expected;

switch (c.algo) {

case 0:  expected = !(inA && inB); break; // И-НЕ

case 1:  expected = (inA && inB);  break; // И

case 3:  expected = !inA;          break; // НЕ

case 4:  expected = !(inA || inB); break; // ИЛИ-НЕ

case 10: expected = (inA ^ inB);   break; // XOR

}

if (result != expected) return i;

}

}

// --- ТЕСТ ДЛЯ ДЕШИФРАТОРОВ (Algo 5: ИД1, ИД3, ИД4, ИД7) ---

else if (c.algo == 5) {

for (byte val = 0; val < 10; val++) { // Проверяем комбинации 0-9

// 1. Подаем двоичный код на все входы (P_IN)

for (int j = 0; j < 16; j++) {

if (c.map[j] == P_IN) {

// Находим, какой это бит (упрощенно: первый встреченный IN - бит 0 и т.д.)

// Для точного теста лучше подавать val на входы согласно весам A,B,C,D

digitalWrite(zif[j], (val >> (j % 4)) & 1);

}

}

delayMicroseconds(50);

// 2. Проверяем выходы

// В дешифраторах обычно активный уровень - LOW (0)

// Мы не знаем точно, какой выход должен гореть для 'val' без сложной карты,

// но мы можем проверить, что хотя бы один выход изменился.

bool anyLow = false;

for (int outIdx = 0; outIdx < 16; outIdx++) {

if (c.map[outIdx] == P_OUT && digitalRead(zif[outIdx]) == LOW) anyLow = true;

}

if (!anyLow && val < 10) return i; // Если при поданном коде ни один выход не "прижался"

}

}

// --- ТЕСТ ДЛЯ D-ТРИГГЕРОВ (Algo 6: ТМ2, ТМ5, ТМ7) ---

else if (c.algo == 6) {

// Сначала пробуем записать "1"

for (int j = 0; j < 16; j++) if (c.map[j] == P_IN) digitalWrite(zif[j], HIGH);

delayMicroseconds(10);

// Если это ТМ2, нужно дернуть CLK. Для простоты дергаем все входы.

for (int j = 0; j < 16; j++) if (c.map[j] == P_IN) { digitalWrite(zif[j], LOW); delayMicroseconds(5); digitalWrite(zif[j], HIGH); }

if (digitalRead(zif[i]) != HIGH) return i; // Не записалась единица

// Теперь пробуем записать "0"

for (int j = 0; j < 16; j++) if (c.map[j] == P_IN) digitalWrite(zif[j], LOW);

for (int j = 0; j < 16; j++) if (c.map[j] == P_IN) { digitalWrite(zif[j], HIGH); delayMicroseconds(5); digitalWrite(zif[j], LOW); }

if (digitalRead(zif[i]) != LOW) return i; // Не записался ноль

}

// --- ТЕСТ ДЛЯ СЧЕТЧИКОВ (Algo 20: ИЕ2, ИЕ5) ---

else if (c.algo == 20) {

// Проверяем, что выход вообще может менять состояние при пульсациях на входе

bool initial = digitalRead(zif[i]);

bool changed = false;

for (int p = 0; p < 20; p++) {

for (int j = 0; j < 16; j++) if (c.map[j] == P_IN) { digitalWrite(zif[j], !digitalRead(zif[j])); }

delayMicroseconds(10);

if (digitalRead(zif[i]) != initial) { changed = true; break; }

}

if (!changed) return i; // Счётчик не считает (выход "залип")

}

}

}

return -1;

}

int autoScan() {

display.clearDisplay();

display.setCursor(20, 30);

display.print(F("SCANNING..."));

display.display();

for (int i = 0; i < chipCount; i++) {

Chip c;

memcpy_P(&c, &database[i], sizeof(Chip));

// Сканируем только те чипы, которые подходят под текущий выбор ног (14 или 16)

if (c.pins != selPin) continue;

if (performTest(i) == -1) return i; // Ура, нашли!

resetZif();

}

return -1; // Не нашли

}

void resetZif() {

for (uint8_t i = 0; i < 16; i++) {

pinMode(zif[i], INPUT); // Переводим все пины в безопасный режим

}

}

int performTest(int idx) {

selectedIdx = idx;

Chip c;

memcpy_P(&c, &database[idx], sizeof(Chip));

resetZif(); // Шаг 1: Сброс

delay(50);

// Шаг 2: Подача питания

for (uint8_t i = 0; i < 16; i++) {

uint8_t mode = c.map[i];

if (mode == P_GND) {

pinMode(zif[i], OUTPUT);

digitalWrite(zif[i], LOW);

} else if (mode == P_VCC) {

pinMode(zif[i], OUTPUT);

digitalWrite(zif[i], HIGH);

}

}

delay(20); // Даем чипу "проснуться"

// Шаг 3: Настройка входов и выходов

for (uint8_t i = 0; i < 16; i++) {

uint8_t mode = c.map[i];

if (mode == P_IN) {

pinMode(zif[i], OUTPUT);

digitalWrite(zif[i], LOW);

} else if (mode == P_OUT) {

pinMode(zif[i], INPUT_PULLUP);

}

}

// Шаг 4: Запуск логики (ваша функция runLogicTest)

int result = runLogicTest(c);

// Шаг 5: Не сбрасываем пины сразу, чтобы увидеть результат на OLED

return result;

}

// --- ГРАФИКА ---

void drawResult(Chip& c, int err) {

display.clearDisplay();

display.setTextSize(1);

display.setTextColor(WHITE);

// Заголовок

display.setCursor(0, 0);

display.print(c.name);

// Рисуем корпус (прямоугольник)

int x = 12, y = 22, w = 104, h = 20;

display.drawRect(x, y, w, h, WHITE);

display.drawCircle(x, y + h/2, 3, WHITE); // Ключ микросхемы

int pinsHalf = c.pins / 2;

float pinStep = (float)w / (pinsHalf + 1);

for (int i = 0; i < pinsHalf; i++) {

// --- НИЖНИЙ РЯД ПИНОВ (1..pins/2) ---

int px = x + (int)(pinStep * (i + 1));

display.drawLine(px, y + h, px, y + h + 2, WHITE);

// Определяем тип пина для нижней стороны

uint8_t type = c.map[i];

display.setCursor(px - 3, y + h - 10); // Внутри рамки снизу

if (type == P_IN)  display.print('I');

else if (type == P_OUT) display.print('O');

else if (type == P_VCC) display.print('+');

else if (type == P_GND) display.print('-');

// Отрисовка ошибки или номера пина

if (i == err) {

display.fillRect(px - 4, y + h + 4, 9, 9, WHITE);

display.setTextColor(BLACK);

display.setCursor(px - 3, y + h + 5); display.print('X');

display.setTextColor(WHITE);

} else {

display.setCursor(px - 3, y + h + 5); display.print(i + 1);

}

// --- ВЕРХНИЙ РЯД ПИНОВ (pins..pins/2+1) ---

int idxR = c.pins - 1 - i;

int pinMapIdx = (c.pins == 14 && idxR >= 7) ? idxR + 2 : idxR; // Коррекция для 14-пин в 16-панели

display.drawLine(px, y - 2, px, y, WHITE);

// Определяем тип пина для верхней стороны

uint8_t typeT = c.map[pinMapIdx];

display.setCursor(px - 3, y + 2); // Внутри рамки сверху

if (typeT == P_IN)  display.print('I');

else if (typeT == P_OUT) display.print('O');

else if (typeT == P_VCC) display.print('+');

else if (typeT == P_GND) display.print('-');

if (pinMapIdx == err) {

display.fillRect(px - 4, y - 12, 9, 9, WHITE);

display.setTextColor(BLACK);

display.setCursor(px - 3, y - 11); display.print('X');

display.setTextColor(WHITE);

} else {

display.setCursor(px - (idxR >= 9 ? 6 : 3), y - 11); display.print(idxR + 1);

}

}

// Статус внизу

display.drawLine(0, 54, 128, 54, WHITE);

display.setCursor(0, 57);

if (err == -1) display.print(F("STATUS: OK"));

else { display.print(F("FAIL PIN: ")); display.print(err + 1); }

display.display();

}

void drawMenu() {

display.clearDisplay();

display.setTextColor(WHITE);

if (currentState == MAIN_MENU) {

display.setCursor(20, 0); display.print(F("IC TESTER v1.5"));

const char* m[] = {"AUTO SCAN", "TTL K155", "CMOS K561", "CMOS K176"};

for(int i=0; i<4; i++) {

display.setCursor(10, 15+i*11);

if(selMode == i) display.print(F("> "));

display.print(m[i]);

}

} else if (currentState == PIN_MENU) {

display.setCursor(30, 15); display.print(F("SELECT PINS:"));

display.setCursor(50, 35); display.print(selPin == 14 ? F("> 14") : F("  14"));

display.setCursor(50, 45); display.print(selPin == 16 ? F("> 16") : F("  16"));

} else if (currentState == LIST_MENU) {

Chip c; memcpy_P(&c, &database[filteredIdx[fPos]], sizeof(Chip));

display.setCursor(0, 0); display.print(F("SELECT CHIP:"));

display.drawRect(0, 15, 128, 25, WHITE);

display.setCursor(5, 23); display.print(c.name);

display.setCursor(0, 45); display.print(c.desc);

} else if (currentState == TEST_RESULT) {

Chip c; memcpy_P(&c, &database[selectedIdx], sizeof(Chip));

drawResult(c, failedPin);

}

display.display();

}

void setup() {

resetZif(); // Сразу переводим панель в безопасный режим

display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);

pinMode(ENC_CLK, INPUT_PULLUP);

pinMode(ENC_DT, INPUT_PULLUP);

lastClk = digitalRead(ENC_CLK);

drawMenu();

}

void loop() {

bool up = false, dn = false, ok = false;

int currentClk = digitalRead(ENC_CLK);

if (currentClk != lastClk && currentClk == LOW) {

if (digitalRead(ENC_DT) != currentClk) dn = true; else up = true;

}

lastClk = currentClk;

int swVal = analogRead(ENC_SW);

if (swVal < 100) {

if (!buttonPressed) { delay(50); ok = true; buttonPressed = true; }

} else { buttonPressed = false; }

if (up || dn || ok) {

if (up) {

if (currentState == MAIN_MENU) selMode = (selMode > 0) ? selMode - 1 : 3;

else if (currentState == PIN_MENU) selPin = (selPin == 14) ? 16 : 14;

else if (currentState == LIST_MENU && fPos > 0) fPos--;

}

if (dn) {

if (currentState == MAIN_MENU) selMode = (selMode < 3) ? selMode + 1 : 0;

else if (currentState == PIN_MENU) selPin = (selPin == 16) ? 14 : 16;

else if (currentState == LIST_MENU && fPos < fCount - 1) fPos++;

}

if (ok) {

delay(200);

if (currentState == MAIN_MENU) {

if (selMode == 0) { // Нажали AUTO SCAN

int foundIdx = autoScan();

if (foundIdx != -1) {

selectedIdx = foundIdx;

failedPin = -1;

currentState = TEST_RESULT;

} else {

display.clearDisplay();

display.setCursor(15, 30);

display.print(F("UNKNOWN CHIP"));

display.display();

delay(1500);

}

} else currentState = PIN_MENU;

} else if (currentState == PIN_MENU) {

fCount = 0;

for(int i=0; i<chipCount; i++) {

Chip c; memcpy_P(&c, &database[i], sizeof(Chip));

if(c.family == (selMode-1) && c.pins == selPin) filteredIdx[fCount++] = i;

}

fPos = 0; currentState = LIST_MENU;

} else if (currentState == LIST_MENU) {

failedPin = performTest(filteredIdx[fPos]);

currentState = TEST_RESULT;

} else if (currentState == TEST_RESULT) currentState = MAIN_MENU;

}

drawMenu();

}

}

Дорогие подписчики! Все кто сможет помочь пишите в комментарии, структура кода будет постоянно меняться, пока не обретёт финальный вид !