Что такое 93C76?

Микросхема 93C76 представляет собой электрически перезаписываемое ПЗУ с последовательным доступом, объемом 8 Кбит. Содержит, непосредственно, блок ПЗУ + логический контроллер для работы с шиной SPI. Напряжение питания 5.0 Вольт. Имеет два вида адресации данных (по 8 бит и по 16 бит) - об этом далее в статье.

Классификация микросхем семейства 93C76/86:
93C86 - объем увеличен в 2 раза, до 16 Кбит.
93LC76 - с пониженным напряжением питания 2.5 В.
S93C76 - в корпусе SOIC-8 (SMD-монтаж).

Зачем программировать 93C76?

Микросхема применяется в автомобильных блоках, платах управления жесткими дисками, различных мультимедийных устройствах. Если есть необходимость запрограммировать данное ПЗУ срочно, рекомендую воспользоваться практически любым китайским программатором, это можно сделать даже на недорогих моделях. Но мне интересно не просто понажимать кнопки, а разобраться в процессе, в сути происходящего. На создание этой статьи меня вдохновило видео от известного ютубера Ben Eater.

В нём показано, в том числе, вычитывание данных из ПЗУ данного типа. В своём коде я частично буду ориентироваться на его код, но при этом мы реализуем все функции программатора: чтение, стирание, запись.

Какие средства необходимы?

Как и в видео, нам понадобится Arduino Uno (подойдет, в т.ч., и китайская копия), сама микросхема 93C76 (у меня нашлась S93C76 с адаптером под DIP-8) и макетная плата с проводами. Конечно, я мог бы расписать всё то же самое, например, для Atmega8, но в нашем случае не нужно всё усложнять, Arduino будет вполне достаточно для демонстрации принципа работы с данной ПЗУ, так как имеется COM-порт для связи с контроллером, через который мы и будем обмениваться информацией в связке ПК - Arduino - 93C76. Язык программирования - си. Итак, приступим.

Этап 1. Подготовка. Распиновка ПЗУ. Соединение аппаратной части.

Рассмотрим назначение выводов ПЗУ:

Левая половина - выводы шины SPI, для связи с микроконтроллером (далее - Arduino). Правая половина - технические выводы.

  1. CS - выбор чипа. Определяет, ведётся ли работа с этим чипом в данный момент.

  2. CLK - тактовый сигнал. Его выдаёт Arduino.

  3. DI - вход для данных. Данные выдаёт Arduino.

  4. DO - выход данных. Его принимает Arduino. На этом выходе будет появляться информация после получения команды на чтение.

  5. VSS - Минус питания, в нашем случае - земля (GND)

  6. ORG - влияет на организацию порядка хранения данных и, соответственно, адресацию. Если установлен низкий уровень, то будет происходить приём данных по 8 бит (режим x8), если высокий - то по 16 бит (x16). Режим x8 показан на видеозаписи от Ben Eater. Некоторые факты о режиме x16, полученные опытным путём:

    1. Если микросхема включена в режим x16, и после команды записи передать только 1 байт, то второй байт будет заполнен нулями, то есть, произойдет потеря данных в ячейке.

    2. Адресация при записи в режиме x16 осуществляется с шагом 2, т.е. не 0,1,2...f, а 0,1,2..7, так как по каждому адресу будет храниться по 2 байта. При чтении можно получить отдельно любой байт (не обязательно пару) по его обычному адресу (0...f), либо несколько байт подряд, так как чтение выполняется последовательно (после подачи команды данные поступают, пока идёт и не прекращается тактовый сигнал).

    3. В моей микросхеме, не смотря на состояние уровня на ORG, всё равно использовалась 16-разрядная организация памяти. Возможно, у некоторых производителей эта функция просто не работает, поэтому иногда на форумах встречаются записи о том, что программатор не может корректно записать микросхему. Либо у моей микросхемы был повреждён данный вывод. В любом случае, к этому моменту нужно относиться внимательно, иначе возникнет потеря данных.

  7. PE - (active low) вывод для защиты микросхемы от записи и стирания. Если в вашем устройстве не нужна запись данных, а лишь их чтение, то вывод подключается на землю. В нашем случае мы его установим на высокий логический уровень, так как будем писать в ПЗУ. В устройстве есть две защиты записи - аппаратная (вывод PE) и программная (EWEN). Если одну из них не снять - записать в чип не получится.

  8. VCC - плюс питания (4.5-7 В для C76, 2.5-7 В для LC76)

Выводы SPI подключаются к любым удобным цифровым ножкам микроконтроллера. В нашем случае, это будут ножки 2-6. Питание можно взять также от МК. Технические выводы я установил так: PE - высокий, ORG - высокий.

Теперь соединим платы:

Этап 2. Изучаем принцип работы ПЗУ. Передача и чтение данных

Когда все соединения выполнены, откроем редактор скетчей Arduino. Для начала, напишем определение ножек для удобной работы:

#define CS 2
#define CLK 3
#define DI 4
#define DO 5

В setup инициализируем COM-порт для связи, назначим направление данных для выводов согласно этапу 1:

Serial.begin(57600);
pinMode(CS, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(DI, OUTPUT);
pinMode(DO, INPUT);

Далее, необходимо разобраться, как работать с шиной SPI. Для этого смотрим в даташит микросхемы:

Отсюда для минимальной работы нам будут нужны команды READ, EWEN, ERAL, WRITE, WRAL (опционально). Передача команды осуществляется переключением сигналов в определенном порядке, который также указан в даташите микросхемы. Например, чтение:

Исходя из этого, мы видим:

  • Первым включается сигнал CS, он же выключается последним.

  • Сначала на DI устанавливается уровень, соответствующий очередному биту подаваемой команды, затем включается и тут выключается тактовый сигнал, как бы "подтверждая" действие и фиксируя данные. Соответственно, нам нет необходимости укладываться во временные рамки - нету жестких требований к таймингам. Скорость переключения портов Arduino высока, но и частота срабатывания логики микросхемы - до 2 МГц. Поэтому, с учетом времени, затрачиваемого на переключение уровней через библиотеки Arduino, мы можем просто подавать сигналы, а задержку проставлять лишь после длительных функций (таких, как ERAL, WRAL).

  • При чтении, после передачи команды + адреса, на выходе DO начнет появляться информация, переключаемая тактовым сигналом. Её мы будем извлекать. Разрешается последовательное чтение всего массива: если не прекратить подачу тактового сигнала, то дальше будут передаваться следующие биты информации, таким образом, команду на чтение отдельно для каждого байта подавать не обязательно.

  • При записи мы передаём последовательность, состоящую из команды, битов адреса A9-A0, и двух байт информации (для организации x16), или адреса A10-A0, но одного байта (для организации x8). При этом для записи каждых двух байт (байта) команду надо передавать заново, последовательная запись в весь массив не осуществляется.

Инструкция состоит из 14 для x8 (либо 13 для x16) бит, порядок следующий: установили первый бит, переключили CLK вверх и тут же вниз, установили второй бит, переключили CLK, и так далее. Исходя из этого, давайте реализуем функцию "sendInstruction", для того, чтобы передать данные в ПЗУ.

void sendInstruction(word comand) { //SEND 14
    for (word mask = 0b10000000000000; mask > 0; mask >>= 1) {
    if (comand & mask) {
      digitalWrite(DI, HIGH);
    } else {
      digitalWrite(DI, LOW);
    }
    digitalWrite(CLK, HIGH);
    digitalWrite(CLK, LOW);
    }
}

Функция принимает в качестве аргумента слово (команду), после чего "прогоняет" шину столько раз, сколько чисел содержится в маске. Сдвинули маску в сторону - переключили уровни, переключили CLK, и так далее, пока маска не кончится (не уйдет последняя единица).

Команды (слова) для различных операций следующие (согласно даташиту):

  • READ (читать с адреса) - 0b1100000000000 + адрес

  • WRITE (запись в ячейку) - 0b1010000000000 + адрес

  • EWEN (разрешить запись и стирание) - 0b10011000000000

  • ERAL (стереть всё) - 0b10010000000000

  • WRAL (записать всё 2 байтами) - 0b10001000000000 + 2 байта (по 8 переключений)

То есть, например, вызвав по очереди

sendInstruction(0b10011000000000);
sendInstruction(0b10010000000000);

Мы сначала разрешим запись (убедившись, что она разрешена на 7 ножке микросхемы), а затем, сотрём чип. Данные функции реализуются следующим образом:

void ERAL() { // ERASE CHIP
  digitalWrite(CS, HIGH);
  sendInstruction(0b10010000000000);
  digitalWrite(CS, LOW);
  delay(15);
}

Задержка в 15 мс на стирание всего чипа согласно даташиту. При чтении и записи:

sendInstruction(0b1100000000000 + address); 

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

byte readByte() {
   byte data = 0;
   for (byte bit = 0; bit < 8; bit +=1) {
      digitalWrite(CLK, HIGH);
      digitalWrite(CLK, LOW);
      if (digitalRead(DO))  {
        data = data << 1 | 1;
        } else {
          data = data << 1;
        }
     }
    return data;
}

После передачи инструкции на чтение, данная функция должна быть вызвана требуемое количество раз (1 для одного байта, 16 для 16 байт и т.д.) при помощи цикла for, а возвращаемый байт data - последовательно записан в массив. Захват уровня на ножке (чтение) осуществляется встроенной в библиотеку Arduino функцией digitalRead.

Для записи реализуем отдельную функцию, отправляющую один байт:

void sendByte(word comand) { //SEND 8
    for (word mask = 0b10000000; mask > 0; mask >>= 1) {
    if (comand & mask) {
      digitalWrite(DI, HIGH);
    } else {
      digitalWrite(DI, LOW);
    }
    digitalWrite(CLK, HIGH);
    digitalWrite(CLK, LOW);
    }
}

Далее мы будем её вызывать после отправки инструкции с адресом на запись. Вызывается один раз для x8, два раза подряд для x16, например:

void WRITE(word addr, byte bt1, byte bt2) {
  digitalWrite(CS, HIGH);
  sendInstruction(0b1010000000000 + addr);
  sendByte(bt1);
  sendByte(bt2);
  digitalWrite(CS, LOW);
  delay(5);
}

То есть, принимаемые аргументы: адрес (например, 0x030f для x8 или 0x0107 для x16) и два байта информации. Исходя из этого высылаем инструкцию на запись, и два байта, которые мы записываем. После этого дополнительная задержка в 5 мс (согласно даташиту - 3 мс, но иногда не успевает в данный тайминг и пишется с ошибками). Как я уже раньше упоминал, если не передавать второй байт - вместо него просто будут записаны нули.

На этом функции обращения к ПЗУ (чтение, стирание, запись) выполнены. Для остальных команд выполняются по аналогии. Далее попытаемся написать UI для работы с этими функциями.

Этап 3. Реализуем функции программатора x16 в ПО для Arduino

Функция "read", скопирована с той, которую выполнил Ben Eater в своём видео. Функция принимает начальный адрес, с которого требуется начать чтение, и количество байт для чтения. Результат отправляет на COM порт в следующем формате: адрес HEX, 16 байт в HEX, 16 байт в виде ASCII-символов, если в таблице находится соответствующий (в противном случае заменяется на точку). Сама функция:

void READ(word startAddress, int endAddress) { //read fashion HEX by Ben Eater
    byte line[16]; //VARIABLE FOR WORD
    for (word address = startAddress; address < endAddress; address += 8) { //1024 for C76, 2048 for C86; 8 for 16-BIT ORG, 16 for 8-bit ORG
    char temp[6]; //VARIABLE FOR ADDR - TMP
    sprintf(temp, "%04x  ", address);
    Serial.print(temp); //PRINT ADDR
    digitalWrite(CS, HIGH); //BEGIN READING DATA
    sendInstruction(0b1100000000000 + address); //please add external zero for x8 org
    for (int i = 0; i < 16; i += 1) { //READ DATA BYTE FOR EVERY LINE BYTE
        line[i] = readByte();
    }
    digitalWrite(CS, LOW);
    for (int i = 0; i < 16; i += 1) {
        char temp[4]; //VARIABLE FOR DATA IN HEX
        sprintf(temp, "%02x ", line[i]);
        Serial.print(temp); //PRINT DATA IN HEX - 16 BYTES
    }
    Serial.print(" ");
    // PRINT DATA IN LETTERS HEX ARR.
    for (int i = 0; i < 16; i += 1) { //PRINT DATA IN LETTERS - 16
        if (line[i] < 32 || line[i] > 126) {
            Serial.print(".");
        } else {
            Serial.print((char) line[i]);
        }
    }
    Serial.println(); //PRINT NEW LINE
  }
}

Вызовем её: READ(0x00, 512). Результат:

Так как микросхема была очищена, она заполнена FF байтами. Конечный адрес записи: 01ff (что является 511 "двойным байтом", если учесть, что нумерация идет с нуля). Давайте подсчитаем: мы имеем 64 строки по 16 байт, итого, 1024 байта (килобайт), что и заявлено в даташите. Если бы была микросхема LC86, то было бы доступно 2 килобайта. Если бы была выбрана организация x8 - то последним адресом был бы 1023, а не 511.
Если пробовать читать или писать дальше доступного пространства - последние биты адреса (A10-A11 и т.д.) игнорируются, и чтение сначала начинается по кругу, а далее вообще не происходит (так как микросхема LC76 не поймёт данную ей входящую команду).

Теперь попробуем написать функцию, записывающую в EEPROM последовательность байт, полученную по терминалу:

void writeWord(word beginAddress) { //WRITES 16 BYTES SEQUENCE FROM TERMINAL
  while (Serial.available() == 0) {
  }
  byte lineToSend[16];
  int recLen = Serial.readBytes(lineToSend, 16);
  for (int i = 0; i < recLen; i += 2) {
    WRITE(beginAddress+(i/2), lineToSend[i], lineToSend[i+1]);
  }
}

Функция ожидает ввод с терминала, до этого будет висеть в бесконечном цикле. Принимает в качестве аргумента адрес, по которому нужно писать. Далее, пишет 16 принятых байт в память EEPROM.

Данная функция адаптирована под 16-битную организацию (x16): так как мы получаем по 1 байту (функция readBytes), то массив имеет размер 16 байт, отправляются на микросхему же байты попарно: i прибавляется кратно двум, обращение идет по адресу от 0 до 7, при этом, байты передаются 0-1, 2-3 и т.д., то есть, от 0 до f.

При 8-битной записи (режим x8) можно непосредственно отправлять WRITE(адрес, байт) 16 раз.

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

void waitAddr() {
   if (Serial.available() > 0) {
   byte receivedAddr[2];
    //RECEIVES ADDRESS IN 2 SEPARATE BYTES (example: 0x30 0x01)
   int recLen = Serial.readBytes(receivedAddr, 2);
   word programAddr = 0;
   programAddr |= receivedAddr[0];
   programAddr <<= 8;
   programAddr |= receivedAddr[1];
    //RETURNS REAL ADDRESS IN DECIMAL
   Serial.print("Received Addr: ");
   Serial.println(programAddr);
    //WAITING FOR 16-BYTE DATA INPUT SEQUENCE IN SEPARATE BYTES
   writeWord(programAddr);
  }
}

Конечно, эту функцию я написал немного криво, впрочем, для демонстрационных целей её достаточно. Вызовем waitAddr() в loop. Он сразу же будет ожидать два байта адреса и 16 байт для записи. Теперь стандартный терминал Arduino нам не помощник - так как он умеет передавать только ASCII символы. Для тестирования подключимся по CoolTerm, передадим значения в HEX, и прочитаем то, что у нас получилось. Передаём адрес, далее Arduino отвечает, что приняло его, и отправляет нам его же обратно в DEC виде. Значения сходятся:



Теперь передадим информацию, и сразу же выполним чтение всего блока, чтобы посмотреть результат:

Функция работает. После отключения питания эти данные уже останутся в памяти ПЗУ. Перебрав в терминале все адреса от 0000 до 01f8 мы сможем записать полностью килобайт информации, тем самым, цель работы является достигнутой. После записи всей микросхемы рекомендуется проверить CRC, прочитав её, но это делается на ответной части в ПК, а не в микроконтроллере.

Таким образом, мы получили возможность чтения данных из ПЗУ, и записи их из терминала. Для того, чтобы реализовать полноценный программатор, который способен записывать полученные данные в бинарный файл, и, в свою очередь, записывать данные из бинарного файла в ПЗУ необходима разработка "ответной" части ПО для компьютера, её я попытаюсь реализовать на python (хотя в компьютерной разработке я не силён, мне удавалось сделать более-менее работоспособные скрипты).

Специально для habr.com, 2022 год.

Комментарии (29)


  1. sim2q
    13.12.2022 00:38
    +5

    С прибытием :)
    Но тут в отличии "другого сайта" в комментах нам не погутарить :)
    Немного странная статья для 2022 г, но красивая и кто я такой бесстатейный тут что-бы об этом рассуждать :)


    1. Kekovsky Автор
      13.12.2022 02:29
      +1

      Благодарю, вот уж точно не ожидал


  1. Boris_Bishkek
    13.12.2022 08:12
    +1

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


    1. Kekovsky Автор
      13.12.2022 08:13
      +2

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


      1. pvvv
        13.12.2022 18:59
        +1

        прослойка в виде ардуины с терминалом для этого совсем лишняя,

        есть ft[2]232h с mpsse, ну или копеечные китайские же клоны альтеровских усббластеров (которые внутри на 8051 тот же ftdi из себя изображают c самопальной и упрощённой версией "mpsse") для получения usb -> spi + gpio.

        да и CH341 - для месье знающих толк в китайской документации.


        1. Alexeyslav
          14.12.2022 00:31

          беда этих чипов в нестабильности функционирования. По сути программный ногодрыг на костылях. Который в связи с закручиванием гаек в виндовс всё сложнее и геморнее использовать. В какой-то момент эти решения внезапно с точки зрения безопасности станут "вне закона" и что делать? Не обновляться? ну, кое кто 98-ю винду использует для программаторов, т.к. софт требует прямого доступа к портам.... на ХР был драйвер, который по сути делает огромную брешь в бехопасости системы.... а люди хавали, ибо не понимают чем это чревато. работа на костылях. Поэтому ардуинка, как бы ни казалось странным, это более правильный путь - на ней у нас все аппаратные возможности под полным контролем, а поддержку uart в том или ином виде с операционной системы врятли выпилят. Но если нужны будут скорости, есть вектор развития - USB... и USer-mode драйвера на свои поделки.


          1. pvvv
            14.12.2022 02:27
            +2

            Это не так, костыли тут ардуина, и учитывая что usb->serial в них иногда лепят из чего попало (особенно в клонах), вероятность потенциальных граблей с драйверами в будущем у них имхо чуть ли не больше чем с ftdi.

            в ft232h mpsse - конечный автомат который на скорости, вроде бы, 6МГц исполняет отправленные ему простые команды,

            то есть им можно аккуратно, с точностью до такта этих 6МГц дрыгать ногами, отправив разом последовательность команд, и исполняться они будут не зависимо от ОС и милисекундных циклов усб.

            Для синхронизации этого автомата правда только один единственный вход, то есть присутсвуют команды "ждать положительного/отрицательного перепада на входе", но только на одном. Но можно прицепить какой-нибудь spi АЦП, который по готовности данных дергает drdy, который ждёт mpsse, после чего начинает пересылку байтов по spi, опять же сам, независимо от ОС, и без поллинга статусных байтов.

            Помимо этого сам spi там "аппаратный" то есть команды "отправь следующие N байт с в нужном cha/pol режиме ногами/головой вперёд, с заданной скоростью" также как дрыгание io исполнятся независимо от ОС.

            И альтервоский usb blaster - то же самое, только там, до появления mpsse, изначально был колхоз из usb->fifo ft245 и мелкой cpld которая разбирала приходящие байты и на заданной скорости отправляла их в spi и дергала ногами, снова не зависимо от того что там наверху у ОС происходит.

            Протокол там проще mpsse и давно доступен, как-то делал программатор для какого-то еепрома как раз альтеровским бластером, лет 10, наверное, назад, если не больше.


            1. Alexeyslav
              14.12.2022 22:31

              Ардуина может это же делать на 20Мгц тактах, а в соседстве с ПЛИС и на 100МГц... а FTDI как была специализированным чипом так и останется - развития нет, расширения функционала тоже. В то время как ардуина в качестве USB-интерфейса имеет тот же МК с USB на борту, прошивку которого можно поменять и получить более гибкое устройство. Кроме того непонятно ещё как тот самый FTDI чип программировать и использовать, не очень открытая документация.


              1. pvvv
                14.12.2022 23:44

                не может, хотя бы потому что для того чтобы какие-то осмысленные данные из какого-то буфера достать и положить в порт, надо несколько больше одного такта, во-вторых full speed usb, а до самого контроллера вообще уарт, который больше мегабита не разогнать.

                ардуина и тут-то не нужна, а в соседстве с ПЛИС тем более.

                какое может быть развитие у usb->spi интерфейса?

                mpsse и так любой последовательный, да и не только, интерфейс может изобразить.

                и я так понимаю что тот же человек, что парой сообщений выше опасался закручивания гаек виндой на предмет подключения непонятных устройств со всяким подписыванием драйверов, теперь предлагает запилить кастомное usb устройство, потому что это более гибко?

                вся документация на ftdi открыта, доступна и понятна.

                там единственная dll c функциями FT_Read, write, open, close, и AN_108 с описанием байтовых команд mpsse.


    1. Arhammon
      13.12.2022 08:52

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


      1. dlinyj
        13.12.2022 17:15
        +1

        Стоит 3 тысячи на Али. Не проблема.


        1. Azya
          14.12.2022 07:41

          Есть, например, MCS-48. Для него найти нормальный программатор за 3к проблема.


    1. Alexeyslav
      14.12.2022 00:22
      +1

      Вот только.... разбираешь прогер, ба.... а там та же самая ардуина стоит по сути. Но не в этом фишка... в том что на ардуине можно сделать любой программатор, даже тех экзотических чипов которые не поддерживаются китаем, ибо программистам лень было внести их параметры в прогу. А потом столкнешься с чипами вроде ПЗУ для хранения БИОСа на материнках, с защищёнными от чтения/записи областями и таже TPM областью под хранение ключей шифрования, и прошить такую можно только зная ключ, а считать нельзя будет - данные будут ЗАШИФРОВАНЫ хранящимся внутри ключом, так что даже на работающей системе сдампить содержимое путем анализа обмена будет нельзя. Казалось бы, простой чип памяти...


      1. Kekovsky Автор
        14.12.2022 00:24

        Поэтому, прежде чем начать процесс, лезем куда? В даташит. Чтобы оценить целесообразность мероприятия.


  1. GarryC
    13.12.2022 12:56
    +2

    Ну не знаю, как на других ресурсах, а тут некоторыми принято читать посты...

    Итак, приступим:

    Язык программирования - си.

    не бьется с

    откроем редактор скетчей Arduino

    поскольку здесь С++.

    сколько чисел содержится в маске

    и сколько именно чисел в маске?

    void ERAL() { // ERASE CHIP

    а назвать функцию, к примеру, Erase_Chip, нельзя?

    void READ(word startAddress, int endAddress) { //read fashion HEX by Ben Eater

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

    дальше просто лень стало, извините.


    1. GeorgeIV
      13.12.2022 13:17

      Адресация при записи в режиме x16 осуществляется с шагом 2, т.е. не 0,1,2...f, а 0,1,2..7, 

      Аналогично (. Где тут шаг 2?


      1. VT100
        13.12.2022 19:19

        Название функции ERAL, вероятно, взято из документации на ИМС.


      1. Alexeyslav
        14.12.2022 00:50
        +1

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


    1. Kekovsky Автор
      14.12.2022 07:42

      1. В данном случае, это скорее ближе к чистому си, хотя язык для скетчей Arduino и C++ (к тому же, в редакторе кода нет кнопки "C", а есть только C++), здесь функции ООП не задействованы, всё укладывается в рамки именно процедурного программирования

      2. Про числа - верная оговорка, я имел ввиду разрядность применяемой маски (13/14 бит), но неверно написал, и не скорректировал.

      3. ERAL, WRAL и т.п., функции, взятые из даташита. Конечно, по naming convention это некрасиво, но сделано для более понятного текста.

      4. Здесь тоже верно, возникло из-за того, что startAddress я задавал словом, а второй параметр у меня был - длина (размер читаемой области), которую прибавлял к адресу. А при отладке уже в какой-то момент заменил длину на конкретное значение конечного адреса, и не заметил несоответствия типов.

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

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


  1. Nixhibrid
    13.12.2022 17:26

    Эти EEPROM очень часто встречаются в автомобильных блоках SRS, и часто используются в блоках ЭБУ как накопитель для данных иммобилайзера. Всегда не хватает устройства для отладки, а именно в идеале нужна железка, которая пошагово разберет, в какой момент времени и на какой адрес идет обращение. Есть мысли как собрать такую приблуду из говна и палок на Arduino?


    1. Kekovsky Автор
      14.12.2022 00:21

      Для автомобилистов отчасти и писал статью.

      Мысли есть - навесить Arduino на шину SPI (так как она разрешает подключение многих устройств), и, отследив сигналы CS и CLK, записать последовательность данных, переданную по шинам, а потом расшифровать данные. Есть промышленные логические анализаторы, которые стоят сотни нефти, но сами способны на ходу читать SPI. А из палок придётся повозиться. Сигнал CS включается, когда идёт работа именно с данным чипом, чтобы другие чипы на шине не принимали команды. Включение CS на нужной микросхеме можно отследить как момент для начала чтения данных.


      1. Alexeyslav
        14.12.2022 22:19

        Не такие дорогие, 10-20$ CS даст момент обращения к чипу, но не событие на котором нужно данные зафиксировать.


    1. Alexeyslav
      14.12.2022 00:40
      +2

      зачем ардуино.... есть же лог. анализаторы. Цепляете его на CLK DI DO и один вывод на нужное событие, чтобы потом сориентироваться с моментом. Во многих программах анализаторов есть даже SPI I2C декодеры, просто поставил на запись, сделал что нужно, смотришь результат и делаешь выводы. На ардуино сделать это будет проблематично, нужеен аппаратный адаптер в виде регистров - дело в том что ардуине может не хватить скорости чтобы отрабатывать корректно сигнал CLK, но это прекрасно делает регистр, и на каждый 16 такт внешнего сигнала CLK после активного CS вызывать прерывание ардуины и в нем считывать этот регистр - с этим она справится. Ну а дальше понятно, разбираешь команду, адрес результат.... надо только забыть про реал-тайм передачу в терминал, скорей всего не будет успевать. Поэтому приняли блок данных целиком, и только тогда слать в терминал.


  1. VT100
    13.12.2022 19:18

    Какие такие 7 вольт? Это же абсолютный предел. Максимальное напряжение питание для долгой беспорочной службы — 5,5 В.


  1. Alexeyslav
    14.12.2022 00:44

    Кстати в коде вижу что сигнал выбора кристалла предполагается активный уровень - лог.1, но по опыту в схемотехнике, у этих чипов активный уровень - лог.0 тоесть "0" - кристалл активен, принимает команды, "1" - игнорирует. Это не ошибка?


    1. Kekovsky Автор
      14.12.2022 01:32

      Делалось согласно фигуры 3-2, а так верно подмечено, для SPI же шина должна быть занулена, если чип выбран. Но тогда на чипе пишется SS (CS) с черточкой наверху (active low), здесь же чёрточки нету, значит, данный чип - active high.


      P.S. я так думаю, в схемах на данную линию ставится одинарный логический инвертор


      1. Alexeyslav
        14.12.2022 22:39

        не ставится. ибо это дополнительная ненужная задержка и вообще лишний элемент. Скорей всего опечатка. Что говорит таблица состояния чипа?
        Хм, и правда "1" выбирает чип, черным по белому написано. Неожиданно.


        1. Kekovsky Автор
          15.12.2022 02:09

          Таки ставится, я сам несколько раз видел одинарные SMD SOT-23-5 инверторы по линии CS, стоящие около логических микросхем. Особой задержки оно не даст, роли не играет. Поэтому элемент не лишний.


  1. powerbroker
    14.12.2022 02:00

    да и здОрово. а еще есть 25-я серия, более распространенная. и тоже SPI