IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Debugování nefunkční čtečky RFID MFRC522

Aktivity
Avatar
Antonín Dolejš:5.4.2021 4:21

Ahoj,
mám takový ten modul s čipem MFRC522 (datasheet zde) a Nucleo (konkrétně je to F411RE, ale to je asi celkem jedno). Potřebuju ten modul zprovoznit, našel jsem na internetu nějaké knihovny přímo pro STM32, ale žádná z nich nefungovala (nešla zkompilovat, a opravování chyb v ní vyvolávalo akorát ještě více chyb...). Tak jsem se rozhodl, že použiju tu z Arduina (source code zde) , která vím, že funguje. Vyházel jsem z ní veškeré cally na Serial (protože ty by nefungovali) a vyhodil jsem myslím i pár nějakých metod, které nepotřebuji a byli v nich errory. Napsal jsem do ní nové metody pro používání SPI, které využívají HAL místo třídy SPI Arduina.

void MFRC522::PCD_WriteRegister(PCD_Register reg, uint8_t value) {
        HAL_GPIO_WritePin(csPort, csPin, GPIO_PIN_RESET);
        HAL_SPI_Transmit(readers[reader], (uint8_t*)&reg, 1, 100);
        HAL_SPI_Transmit(readers[reader], &value, 1, 100);
        HAL_GPIO_WritePin(csPort, csPin, GPIO_PIN_SET);
}

uint8_t MFRC522::PCD_ReadRegister(PCD_Register reg) {
        uint8_t data;
        uint8_t zero = 0x00;
        uint8_t addr = 0x80 | reg;
        HAL_GPIO_WritePin(csPort, csPin, GPIO_PIN_RESET);
        HAL_SPI_Transmit(readers[reader], &addr, 1, 100);
        HAL_SPI_TransmitReceive(readers[reader], &zero, &data, 1, 100);
        HAL_GPIO_WritePin(csPort, csPin, GPIO_PIN_SET);
        return data;
}

a knihovnu používám:

bool readID() {
  if (!rfid.PICC_IsNewCardPresent()) {
    return false;
  }
  if (!rfid.PICC_ReadCardSerial()) {
    return false;
  }
  for (int i = 0; i < 4; i++) {
    lastId[i] = rfid.uid.uidByte[i];
  }
  rfid.PICC_HaltA();
  return true;
}

Metoda PICC_IsNewCar­dPresent() ale stále vrací false, ikdyž je v blízkosti karta. Pomocí debuggeru jsem dohledal, že problém vězí v této části metody PCD_Communica­teWithPICC (součást té knihovny):

uint16_t i;
for (i = 2000; i > 0; i--) {
        uint8_t n = PCD_ReadRegister(ComIrqReg);        // ComIrqReg[7..0] bits are: Set1 TxIRq RxIRq IdleIRq HiAlertIRq LoAlertIRq ErrIRq TimerIRq
        if (n & waitIRq/*konstanta 0x30*/) {                                    // One of the interrupts that signal success has been set.
                break;
        }
        if (n & 0x01) {                                         // Timer interrupt - nothing received in 25ms
                return STATUS_TIMEOUT;
        }
}

Vždy do dojde k tomu řádku

return STATUS_TIMEOUT;

cyklus ani vícekrát neběží. Chytil jsem si ten dotaz na registr ComIrqReg na osciloskopu (viz obrázek 1), STM odeslalo 0x88 (což odpovídá požadavku na čtení z ComIrqReg) a modul odpověděl 0x45, což když se v debuggeru podívám na proměnou n, tak je v ní také 0x45. Takže v mé implementaci těch metod problém pravděpodobně nebude. Zobrazil jsem si i kus inicializace modulu (obrázek 2) a část (celé se mi teda fakt nechtělo – nevidím důvod, proč by funkce párkrát fungovala a potom najednou přestala) jsem ručně zkontroloval a i zde to sedí. A obecně ta komunikace na tom osciloskopu vypadá asi tak, jak má.

0x45 je 0b01000101, tj n&0x01 je 0b1 tj. true a vrací to STATUS_TIMEOUT... Já potřebuji, aby 5. nebo 6. (RxIRq nebo IdleIRq) LSB byl 1.

Nějak mi teda teď došli nápady, co dál zkusit. Prvně mě napadlo, že procesor má nějaký buffer a že čtu nějaké předchozí nesmysly, ale tak to není, protože se to shoduje s osciloskopem a zkusil jsem i return zakomentovat a nechat cyklus pársetkrát proběhnout a ta odpověď byla vždy naprosto stejná. A to ať s kartou nebo bez.

Nepředpokládám, že někdo budete hned vědět, co přesně s tím... Ale ocením jakýkoliv nápad, co zkusit, popř. na co se zaměřit v debuggeru, v čem by mohl být problém. Pokud vás cokoliv napadne, určitě prosím napiště, i kdyby to měla být nakonec blbost... Třeba mě to ale alespoň navede správným směrem :D

 
Odpovědět
5.4.2021 4:21
Avatar
Antonín Dolejš:21.4.2021 23:37

Přišel jsem na to, že problém není v tom TimerIRq, to je správně, tím že jsem to procházel v debuggeru, tak těch 25ms už opravdu samozřejmě uběhlo. Ale obecný problém přetrvává a čtečka s STM32 stále nečte.

Nahrál jsem si komunikaci přes logický analyzér a porovnal s komunikací Arduina a je to včetně odpovědí do písmene stejné, tak nechápu, proč když je ta čtečka s STM32 MCU, tak nečte... Přikládám screen z analyzátoru, nějaké nápady? Díky!

 
Nahoru Odpovědět
21.4.2021 23:37
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.