Пример MFRC522 ReadNUID перезагружается, если я не включу оператор null if

Я новичок в Arduino (и C), но не во встроенной электронике и программировании.

Я использую модуль MFRC522 (обычный) с Nano и получаю странные результаты. Они находятся на очень простой заказной печатной плате, которую я сделал (единственные части на ней, за исключением пары светодиодов на D4 и D5). Я использую SS_PIN на 8 и RST_PIN на 7, который изменен с 10 & 9, потому что на плате также будет использоваться модуль NRF24L01 на шине SPI (еще не установлен).

И я использую библиотеку MFRC522. Пример DumpInfo в библиотеке работает нормально, но не пример ReadNUID.

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

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

Добавлен оператор null if в начале цикла:

if (GotIRQ) {}  

и определил изменчивую переменную для проверки:-

volatile boolean GotIRQ=false; 

Не работает, если он не изменчив. (Подсказка?)

Что дает? Какая-то глупая ошибка новичка?

(Я мог бы опубликовать весь код, если потребуется, но я снова начал с исходного кода и сделал только 2 изменения и 2 добавления, описанные выше)

Вот код:-

/*
* -------------------------------------------------- -------------------------------------------------- ------------------
* Пример скетча/программы, показывающий, как считывать новый NUID с PICC в последовательный порт.
* -------------------------------------------------- -------------------------------------------------- ------------------
* Это пример библиотеки MFRC522; для получения дополнительной информации и других примеров см.: https://github.com/miguelbalboa/rfid
*
* Пример скетча/программы, показывающий, как считывать данные с PICC (то есть с RFID-метки или карты) с использованием RFID на основе MFRC522.
* Считыватель на интерфейсе Arduino SPI.
*
* Когда Arduino и модуль MFRC522 подключены (см. раскладку контактов ниже), загрузите этот скетч в Arduino IDE.
* затем проверьте/скомпилируйте и загрузите его. Чтобы увидеть вывод: используйте Tools, Serial Monitor IDE (нажмите Ctrl+Shft+M). Когда
* вы предъявляете PICC (т. е. RFID-метку или карту) на расстоянии считывания считывателя/PCD MFRC522, последовательный выход
* покажет тип и NUID, если была обнаружена новая карта. Примечание. Вы можете увидеть сообщения «Тайм-аут связи».
* при слишком раннем удалении PICC с расстояния чтения.
*
* @license Выпущено в общественное достояние.
*
* Используемое типичное расположение выводов:
 * -----------------------------------------------------------------------------------------
 *             MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
 *             Reader/PCD   Uno           Mega      Nano v3    Leonardo/Micro   Pro Micro
 * Signal      Pin          Pin           Pin       Pin        Pin              Pin
 * -----------------------------------------------------------------------------------------
 * RST/Reset   RST          9             5         D9         RESET/ICSP-5     RST
 * SPI SS      SDA(SS)      10            53        D10        10               10
 * SPI MOSI    MOSI         11 / ICSP-4   51        D11        ICSP-4           16
 * SPI MISO    MISO         12 / ICSP-1   50        D12        ICSP-1           14
 * SPI SCK     SCK          13 / ICSP-3   52        D13        ICSP-3           15
 */

#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 8   //QQ Это изменено с 10
#define RST_PIN 7   //QQ Это изменено с 9

MFRC522 rfid(SS_PIN, RST_PIN); // Экземпляр класса

MFRC522::MIFARE_Key key; 

volatile boolean GotIRQ=false; // QQ требуется для нулевого оператора if

// Массив инициализации, в котором будет храниться новый NUID
byte nuidPICC[3];

void setup() { 
  Serial.begin(9600);
  SPI.begin(); // Инициируем шину SPI
  rfid.PCD_Init(); // Инициализация MFRC522

  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }

  Serial.println(F("This code scan the MIFARE Classsic NUID."));
  Serial.print(F("Using the following key:"));
  printHex(key.keyByte, MFRC522::MF_KEY_SIZE);
}

void loop() {
  if (GotIRQ) {}   //QQ Если это не включено, плата сбрасывается при обнаружении метки RFID

  // Ищем новые карты
  if ( ! rfid.PICC_IsNewCardPresent())
    return;

  // Проверяем, был ли прочитан NUID
  if ( ! rfid.PICC_ReadCardSerial())
    return;

  Serial.print(F("PICC type: "));
  MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
  Serial.println(rfid.PICC_GetTypeName(piccType));

  // Проверяем, что это PICC типа Classic MIFARE
  if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&  
    piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
    piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
    Serial.println(F("Your tag is not of type MIFARE Classic."));
    return;
  }

  if (rfid.uid.uidByte[0] != nuidPICC[0] || 
    rfid.uid.uidByte[1] != nuidPICC[1] || 
    rfid.uid.uidByte[2] != nuidPICC[2] || 
    rfid.uid.uidByte[3] != nuidPICC[3] ) {
    Serial.println(F("A new card has been detected."));

    // Сохраняем NUID в массив nuidPICC
    for (byte i = 0; i < 4; i++) {
      nuidPICC[i] = rfid.uid.uidByte[i];
    }

    Serial.println(F("The NUID tag is:"));
    Serial.print(F("In hex: "));
    printHex(rfid.uid.uidByte, rfid.uid.size);
    Serial.println();
    Serial.print(F("In dec: "));
    printDec(rfid.uid.uidByte, rfid.uid.size);
    Serial.println();
  }
  else Serial.println(F("Card read previously."));

  // Остановить PICC
  rfid.PICC_HaltA();

  // Остановить шифрование на PCD
  rfid.PCD_StopCrypto1();
}


/**
 * Helper routine to dump a byte array as hex values to Serial. 
 */
void printHex(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}

/**
 * Helper routine to dump a byte array as dec values to Serial.
 */
void printDec(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], DEC);
  }
}

Хорошо, попытка сократить до минимального примера оказалась полезной. Кажется, проблема вызвана циклом, в котором хранится NUID, но не в том случае, если присутствует лишний оператор if. Код: -

// Урезанная версия библиотеки MFRC522, пример ReadNUID, который демонстрирует странгл
// проблема перезагрузки платы при поднесении карты к считывателю.
// Но только если:-
// * включен цикл Store NUID
// и
// * лишнего оператора "if" в начале цикла() НЕТ.
// Отличия от исходного примера обозначены комментариями, начинающимися с "//QQ"
// (плюс много удаленного кода)

#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 8   //QQ Это изменено с 10
#define RST_PIN 7   //QQ Это изменено с 9

MFRC522 rfid(SS_PIN, RST_PIN); // Экземпляр класса

MFRC522::MIFARE_Key key; 

volatile boolean GotIRQ=false; // QQ требуется для нулевого оператора if

// Массив инициализации, в котором будет храниться новый NUID
byte nuidPICC[3];

void setup() { 
  Serial.begin(9600);
  SPI.begin(); // Инициируем шину SPI
  rfid.PCD_Init(); // Инициализация MFRC522

  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }

  Serial.println(F("This code scan the MIFARE Classsic NUID."));
}

void loop() {
// if (GotIRQ) {} //QQ Если это не включено, плата сбрасывается при обнаружении метки RFID

  // Ищем новые карты
  if ( ! rfid.PICC_IsNewCardPresent())
    return;

  // Проверяем, был ли прочитан NUID
  if ( ! rfid.PICC_ReadCardSerial())
    return;

  Serial.print(F("PICC type: "));
  MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
  Serial.println(rfid.PICC_GetTypeName(piccType));

  // Сохраняем NUID в массиве nuidPICC // QQ не завершается ошибкой, если этот цикл исключен
  for (byte i = 0; i < 4; i++) {
    nuidPICC[i] = rfid.uid.uidByte[i];
  }

  // Остановить PICC
  rfid.PICC_HaltA();

  // Остановить шифрование на PCD
  rfid.PCD_StopCrypto1();
}

, 👍1

Обсуждение

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

Добро пожаловать в Ардуино SE. Обязательно посетите тур, чтобы увидеть, как здесь все работает: https://arduino.stackexchange.com/Tour, @SDsolar

«минимальный проверяемый пример кода». Я хотел использовать код, с которым многие были бы знакомы, и просто показать простое изменение, которое я сделал, которое вызывает проблему. Я попытаюсь уменьшить его, но тогда у нас нет знакомой отправной точки. просто добавление двух строк ничего не значит., @bertoid

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

Добавлен мой модифицированный код примера и его минимальная версия. Кажется, что цикл, в котором хранится NUID, вызывает проблему (новая проблема), и включение оператора null if исправляет ее (исходная проблема)., @bertoid

Я включил этот код в другой скетч, также используя SPI для связи с NRF24L01, и снова появляется (другая) проблема, когда присутствует код для хранения NUID. "я=0; я<4;" означает, что цикл выполняется 4 раза с i=0,1,2,3. Правильный? Но если я изменю объявление массива на «byte NUID [4]», проблема исчезнет. Но ведь это 5 байт, не так ли? Значит, не должно быть переполнения с NUID[3]?, @bertoid


2 ответа


0

Я предполагаю, что дополнительный байт в массиве необходим, возможно, для нулевого терминатора или чего-то еще, и что в примере кода есть ошибка. У меня больше не было проблем после изменения NUID[3] на NUID[4], так что я остановлюсь на этом.

,

1

Вы определили, что этот массив состоит из трех элементов:

byte nuidPICC[3];

эти три элемента пронумерованы 0, 1 и 2.

В этом цикле for:

for (byte i = 0; i < 4; i++) {
    nuidPICC[i] = rfid.uid.uidByte[i];
  }

вы пишете в позицию 3, которая находится за пределами этого массива.

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

,