#include "mfrc522.h" #include <zephyr/drivers/gpio.h> #include <zephyr/drivers/spi.h> #define PICC_TIMEOUT_5MS 0x09 #define PICC_TIMEOUT_10MS 0x13 #define PICC_TIMEOUT_15MS 0x1E #define GPIO_CS 28 const struct device *gpio0_dev; const struct device *spi_dev; struct spi_config spi_cfg; struct spi_cs_control chip; struct spi_buf tx_buf; struct spi_buf rx_buf; void SPI_Init(void) { spi_dev = DEVICE_DT_GET(DT_NODELABEL(spi1)); if (!spi_dev) { printk("Failed to get SPI device\n"); return; } gpio0_dev = DEVICE_DT_GET(DT_NODELABEL(gpio0)); // GPIO cihazını tanımla if (!gpio0_dev) { printk("Failed to get GPIO device\n"); return; } // SPI yapılandırması spi_cfg.frequency = 10000000; spi_cfg.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB | SPI_MODE_CPOL | SPI_MODE_CPHA; spi_cfg.slave = 0; // CS pini için yapılandırma chip.gpio.port = gpio0_dev; chip.gpio.pin = GPIO_CS; chip.gpio.dt_flags = GPIO_ACTIVE_LOW; chip.delay = 2; // SPI yapılandırmasına CS pinini ekle spi_cfg.cs = chip; printk("\r\nSPI device is initialized and ready.\n"); } uint8_t TM_MFRC522_RdReg(uint8_t ucAddress) { uint8_t command = ((ucAddress << 1) & 0x7E) | 0x80; // MFRC522 adresi ile okuma komutunu oluştur uint8_t tx_data[2] = {command, 0x00}; // Okunan veriyi alacak buffer uint8_t rx_data[2] = {0}; // Okunan veriyi alacak buffer tx_buf.buf = tx_data; tx_buf.len = 2; rx_buf.buf = rx_data; rx_buf.len = 2; struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1}; struct spi_buf_set rx = { .buffers = &rx_buf, .count = 1}; if (spi_transceive(spi_dev, &spi_cfg, &tx, &rx) != 0) { printk("\r\nError reading MFRC522 register\r\n"); return 0; // Hata durumunda 0 dön } printk("data responds <<<<: %02X-%02X\n", rx_data[0], rx_data[1]); return rx_data[1]; // Okunan veriyi dön } TM_MFRC522_STS_T MFRC522_Authenticate(uint8_t auth_mode, uint8_t block_addr, uint8_t *key, uint8_t *uid) { TM_MFRC522_STS_T status; uint16_t recvBits; uint8_t i; uint8_t buff[12]; //Verify the command block address + sector + password + card serial number buff[0] = auth_mode; buff[1] = block_addr; for (i = 0; i < 6; i++) { buff[i + 2] = *(key + i); } for (i = 0; i < 4; i++) { buff[i + 8] = *(uid + i); } status = TM_MFRC522_ToCard(PCD_AUTHENT, buff, 12, buff, &recvBits); k_sleep(K_MSEC(100)); printk("------------------Status: 0x%02X", status); TM_MFRC522_RdReg(MFRC522_REG_STATUS2); if ((status != MI_OK) || (!(TM_MFRC522_RdReg(MFRC522_REG_STATUS2) & 0x08))) { status = MI_ERR; } return status; } void TM_MFRC522_WrReg(uint8_t ucAddress, uint8_t ucValue) { uint8_t command = (ucAddress << 1) & 0x7E; // MFRC522 adresi ile yazma komutunu oluştur uint8_t value = ucValue; struct spi_buf_set tx_bufs; struct spi_buf txb[2]; txb[0].buf = &command; txb[0].len = 1; txb[1].buf = &value; txb[1].len = 1; tx_bufs.buffers = txb; tx_bufs.count = 2; int ret = spi_write(spi_dev, &spi_cfg, &tx_bufs); if (ret != 0) { printk("\r\nSPI transfer failed with error: %d\r\n", ret); // Hata durumunda gerekli işlemler yapılabilir } else { // SPI iletişimi başarıyla gerçekleştirildi } } void TM_MFRC522_Init(void) { TM_MFRC522_Reset(); TM_MFRC522_WrReg(MFRC522_REG_T_MODE, 0x8D); TM_MFRC522_WrReg(MFRC522_REG_T_PRESCALER, 0x3E); TM_MFRC522_WrReg(MFRC522_REG_T_RELOAD_L, 5); TM_MFRC522_WrReg(MFRC522_REG_T_RELOAD_H, 0); TM_MFRC522_WrReg(MFRC522_REG_TX_AUTO, 0x40); TM_MFRC522_WrReg(MFRC522_REG_MODE, 0x3D); TM_MFRC522_WrReg(MFRC522_REG_RF_CFG, 0x70); TM_MFRC522_SetBitMask(MFRC522_REG_DIV1_EN, 0x80); TM_MFRC522_AntennaOn(); // TM_MFRC522_WrReg(MFRC522_REG_T_MODE, 0x8D); // TM_MFRC522_WrReg(MFRC522_REG_T_PRESCALER, 0x3E); // TM_MFRC522_WrReg(MFRC522_REG_T_RELOAD_L, 30); // TM_MFRC522_WrReg(MFRC522_REG_T_RELOAD_H, 0); // /* 48dB gain */ // //TM_MFRC522_WriteRegister(MFRC522_REG_RF_CFG, 0x70); // TM_MFRC522_WrReg(MFRC522_REG_TX_AUTO, 0x40); // TM_MFRC522_WrReg(MFRC522_REG_MODE, 0x3D); // TM_MFRC522_AntennaOff(); // TM_MFRC522_AntennaOn(); //Open the antenna } /* A function to initialize SPI Instance */ void TM_MFRC522_SetBitMask(uint8_t reg, uint8_t mask) { TM_MFRC522_WrReg(reg, TM_MFRC522_RdReg(reg) | mask); } void TM_MFRC522_ClearBitMask(uint8_t reg, uint8_t mask) { TM_MFRC522_WrReg(reg, TM_MFRC522_RdReg(reg) & (~mask)); } void TM_MFRC522_AntennaOn(void) { uint8_t temp; temp = TM_MFRC522_RdReg(MFRC522_REG_TX_CONTROL); if (!(temp & 0x03)) TM_MFRC522_SetBitMask(MFRC522_REG_TX_CONTROL, 0x03); } void TM_MFRC522_AntennaOff(void) { TM_MFRC522_ClearBitMask(MFRC522_REG_TX_CONTROL, 0x03); } void TM_MFRC522_Reset(void) { uint8_t temp; TM_MFRC522_WrReg(MFRC522_REG_COMMAND, PCD_RESETPHASE); do { temp = TM_MFRC522_RdReg(MFRC522_REG_COMMAND); temp &= 0x10; } while (temp); } uint8_t MFRC522_ToCard(uint8_t command, uint8_t *sendData, uint8_t sendLen, uint8_t *backData, unsigned *backLen) { uint8_t _status = MI_ERR; uint8_t irqEn = 0x00; uint8_t waitIRq = 0x00; uint8_t lastBits; uint8_t n; unsigned i; switch (command) { case PCD_AUTHENT: { irqEn = 0x12; waitIRq = 0x10; break; } case PCD_TRANSCEIVE: { irqEn = 0x77; waitIRq = 0x30; break; } default: break; } TM_MFRC522_WrReg(MFRC522_REG_COMM_IE_N, irqEn | 0x80); TM_MFRC522_ClearBitMask(MFRC522_REG_COMM_IRQ, 0x80); TM_MFRC522_SetBitMask(MFRC522_REG_FIFO_LEVEL, 0x80); TM_MFRC522_WrReg(MFRC522_REG_COMMAND, PCD_IDLE); for (i = 0; i < sendLen; i++) { TM_MFRC522_WrReg(MFRC522_REG_FIFO_DATA, sendData[i]); } TM_MFRC522_WrReg(MFRC522_REG_COMMAND, command); if (command == PCD_TRANSCEIVE) { TM_MFRC522_SetBitMask(MFRC522_REG_BIT_FRAMING, 0x80); } i = 0xFFFF; do { n = TM_MFRC522_RdReg(MFRC522_REG_COMM_IRQ); i--; } while (i && !(n & 0x01) && !(n & waitIRq)); TM_MFRC522_ClearBitMask(MFRC522_REG_BIT_FRAMING, 0x80); if (i != 0) { if (!(TM_MFRC522_RdReg(MFRC522_REG_ERROR) & 0x1B)) { _status = MI_OK; if (n & irqEn & 0x01) { _status = MI_NOTAGERR; } if (command == PCD_TRANSCEIVE) { n = TM_MFRC522_RdReg(MFRC522_REG_FIFO_LEVEL); lastBits = TM_MFRC522_RdReg(MFRC522_REG_CONTROL) & 0x07; if (lastBits) { *backLen = (n - 1) * 8 + lastBits; } else { *backLen = n * 8; } if (n == 0) { n = 1; } if (n > 16) { n = 16; } for (i = 0; i < n; i++) { backData[i] = TM_MFRC522_RdReg(MFRC522_REG_FIFO_DATA); } backData[i] = 0; } } else { _status = MI_ERR; } } return _status; } uint8_t MFRC522_Request(uint8_t reqMode, uint8_t *TagType) { uint8_t _status = MI_ERR; // Mặc định là lỗi, chỉ đổi thành MI_OK khi thành công uint8_t backBits = 0; // Số bit phản hồi từ thẻ printk("MFRC522_Request: Sending reqMode = 0x%02X\n", reqMode); // Đặt BitFramingReg thành 0x07 (chỉ cần nếu có vấn đề giao tiếp) TM_MFRC522_WrReg(MFRC522_REG_BIT_FRAMING, 0x07); // Chuẩn bị dữ liệu gửi đi TagType[0] = reqMode; // Gửi lệnh và nhận phản hồi từ thẻ _status = MFRC522_ToCard(PCD_TRANSCEIVE, TagType, 1, TagType, &backBits); printk("MFRC522_Request: Status = %d, backBits = 0x%02X\n", _status, backBits); // Kiểm tra xem phản hồi có hợp lệ không if ((_status == MI_OK) && (backBits == 0x10)) { printk("MFRC522_Request: Card detected successfully!\n"); } else { printk("MFRC522_Request: Failed! _status = %d, backBits = 0x%02X\n", _status, backBits); _status = MI_ERR; } return _status; } uint8_t MFRC522_isCard(uint8_t *TagType) { if (MFRC522_Request(PICC_REQA, TagType) == MI_OK) return 1; else return 0; } TM_MFRC522_STS_T TM_MFRC522_Anticoll(uint8_t *serNum) { TM_MFRC522_STS_T status; uint8_t i; uint8_t serNumCheck = 0; uint16_t unLen; TM_MFRC522_ClearBitMask(MFRC522_REG_STATUS2, 0x08); TM_MFRC522_WrReg(MFRC522_REG_BIT_FRAMING, 0x00); // TxLastBists = BitFramingReg[2..0] TM_MFRC522_SetBitMask(MFRC522_REG_COLL, 0x80); /* ANTICOLLISION command with NVB does not specify 40 valid bits (NVB not to 0x70) */ /* Note: "NVB=0x20" defines that the PCD will transmit no part of UID CLn, and it forces all PICCs in the field to respond with their complete UID CLn. */ serNum[0] = PICC_ANTICOLL; serNum[1] = 0x20; // NVB status = TM_MFRC522_ToCard(PCD_TRANSCEIVE, serNum, 2, serNum, &unLen); if (status == MI_OK) { /* Check card serial number */ for (i = 0; i < 4; i++) { serNumCheck ^= serNum[i]; } /* BCC: UID CLn checkbyte and is calculated as exclusive-or over the 4 previous bytes */ if (serNumCheck != serNum[i]) { status = MI_ERR; } } TM_MFRC522_SetBitMask(MFRC522_REG_COLL, 0x80); return status; } TM_MFRC522_STS_T TM_MFRC522_ToCard(uint8_t command, uint8_t *sendData, uint8_t sendLen, uint8_t *backData, uint16_t *backLen) { TM_MFRC522_STS_T status = MI_ERR; uint8_t irqEn = 0x00; uint8_t waitIRq = 0x00; uint8_t lastBits; uint8_t n; uint16_t i; switch (command) { case PCD_AUTHENT: { irqEn = 0x12; waitIRq = 0x10; break; } case PCD_TRANSCEIVE: { irqEn = 0x77; waitIRq = 0x30; break; } default: break; } TM_MFRC522_WrReg(MFRC522_REG_COMM_IE_N, irqEn | 0x80); TM_MFRC522_ClearBitMask(MFRC522_REG_COMM_IRQ, 0x80); TM_MFRC522_SetBitMask(MFRC522_REG_FIFO_LEVEL, 0x80); TM_MFRC522_WrReg(MFRC522_REG_COMMAND, PCD_IDLE); // Writing data to the FIFO for (i = 0; i < sendLen; i++) { TM_MFRC522_WrReg(MFRC522_REG_FIFO_DATA, sendData[i]); } // Execute the command TM_MFRC522_WrReg(MFRC522_REG_COMMAND, command); if (command == PCD_TRANSCEIVE) { TM_MFRC522_SetBitMask(MFRC522_REG_BIT_FRAMING, 0x80); // StartSend=1,transmission of data starts } // Waiting to receive data to complete i = 2000; // i according to the clock frequency adjustment, the operator M1 card maximum waiting time 25ms??? do { // CommIrqReg[7..0] // Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq n = TM_MFRC522_RdReg(MFRC522_REG_COMM_IRQ); i--; } while ((i != 0) && !(n & 0x01) && !(n & waitIRq)); TM_MFRC522_ClearBitMask(MFRC522_REG_BIT_FRAMING, 0x80); // StartSend=0 if (i != 0) { if (!(TM_MFRC522_RdReg(MFRC522_REG_ERROR) & 0x1B)) { status = MI_OK; if (n & irqEn & 0x01) { status = MI_NOTAGERR; } if (command == PCD_TRANSCEIVE) { n = TM_MFRC522_RdReg(MFRC522_REG_FIFO_LEVEL); lastBits = TM_MFRC522_RdReg(MFRC522_REG_CONTROL) & 0x07; if (lastBits) { *backLen = (n - 1) * 8 + lastBits; } else { *backLen = n * 8; } if (n == 0) { n = 1; } if (n > MFRC522_MAX_LEN) { n = MFRC522_MAX_LEN; } // Reading the received data in FIFO for (i = 0; i < n; i++) { backData[i] = TM_MFRC522_RdReg( MFRC522_REG_FIFO_DATA); } } } else { status = MI_ERR; } } // TM_MFRC522_SetBitMask(MFRC522_REG_TX_CONTROL, 0x80); // TM_MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_IDLE); return status; } void TM_MFRC522_CalculateCRC(uint8_t *pIndata, uint8_t len, uint8_t *pOutData) { uint8_t i, n; TM_MFRC522_ClearBitMask(MFRC522_REG_DIV_IRQ, 0x04); TM_MFRC522_SetBitMask(MFRC522_REG_FIFO_LEVEL, 0x80); for (i = 0; i < len; i++) { TM_MFRC522_WrReg(MFRC522_REG_FIFO_DATA, *(pIndata + i)); } TM_MFRC522_WrReg(MFRC522_REG_COMMAND, PCD_CALCCRC); i = 0xFF; do { n = TM_MFRC522_RdReg(MFRC522_REG_DIV_IRQ); i--; } while ((i != 0) && !(n & 0x04)); pOutData[0] = TM_MFRC522_RdReg(MFRC522_REG_CRC_RESULT_L); pOutData[1] = TM_MFRC522_RdReg(MFRC522_REG_CRC_RESULT_M); } void TM_MFRC522_Halt(void) { uint8_t buff[4]; buff[0] = PICC_HALT; // 0x50: Lệnh HALT buff[1] = 0x00; TM_MFRC522_CalculateCRC(buff, 2, &buff[2]); // Tính CRC // Ghi dữ liệu vào FIFO TM_MFRC522_ClearBitMask(MFRC522_REG_COLL, 0x80); // Clear lỗi for (int i = 0; i < 4; i++) { TM_MFRC522_WrReg(MFRC522_REG_FIFO_DATA, buff[i]); } // Kích hoạt lệnh HALT nhưng không chờ phản hồi TM_MFRC522_WrReg(MFRC522_REG_COMMAND, PCD_IDLE); printk("TM_MFRC522_Halt: Card halted successfully.\n"); } uint8_t TM_MFRC522_Check(uint8_t *id) { uint8_t status; uint8_t cardtype[3]; status = MFRC522_Request(PICC_REQA, cardtype); if (status == MI_OK) status = TM_MFRC522_Anticoll(id); else status = MI_ERR; return status; } TM_MFRC522_STS_T TM_MFRC522_Auth(uint8_t auth_mode, uint8_t block_addr, uint8_t *key, uint8_t *uid) { uint8_t auth_cmd[12]; auth_cmd[0] = auth_mode; // 0x60 = KeyA, 0x61 = KeyB auth_cmd[1] = block_addr; // Địa chỉ block cần xác thực memcpy(&auth_cmd[2], key, 6); // Copy key vào mảng memcpy(&auth_cmd[8], uid, 4); // Copy UID vào mảng // 🔹 Reset trạng thái trước khi gửi authentication TM_MFRC522_WrReg(MFRC522_REG_COMMAND, 0x00); TM_MFRC522_WrReg(MFRC522_REG_COMM_IRQ, 0x7F); TM_MFRC522_WrReg(MFRC522_REG_FIFO_LEVEL, 0x80); TM_MFRC522_WrReg(MFRC522_REG_FIFO_DATA, 0x0A); TM_MFRC522_WrReg(MFRC522_REG_FIFO_DATA, 0x04); TM_MFRC522_WrReg(MFRC522_REG_COMMAND, 0x0C); k_sleep(K_MSEC(10)); // Thêm delay nhỏ để chip xử lý // 🔹 Reset lại FIFO trước khi gửi authentication TM_MFRC522_WrReg(MFRC522_REG_FIFO_LEVEL, 0x80); // 🔹 Gửi 12 byte auth command vào FIFO TM_MFRC522_WrRegMulti(MFRC522_REG_FIFO_DATA, auth_cmd, 12); // 🔹 Cấu hình truyền dữ liệu TM_MFRC522_WrReg(MFRC522_REG_BIT_FRAMING, 0x00); // 🔹 Kích hoạt authentication TM_MFRC522_WrReg(MFRC522_REG_COMMAND, PCD_AUTHENT); // 🔹 Chờ hoàn thành auth bằng polling thay vì delay cố định uint8_t wait = 1000; while (!(TM_MFRC522_RdReg(MFRC522_REG_COMM_IRQ) & 0x10) && wait--) { k_sleep(K_MSEC(1)); } // 🔹 Kiểm tra authentication thành công hay không for (int i = 0; i < 5; i++) { int a = TM_MFRC522_RdReg(MFRC522_REG_STATUS2); k_sleep(K_MSEC(100)); if (a & 0x08) { // Kiểm tra CRYPTO1_ON return MI_OK; // ✅ Thành công } printk("========================%02X\n", a); } // 🔹 Nếu thất bại, đọc ErrorReg để debug uint8_t error = TM_MFRC522_RdReg(MFRC522_REG_ERROR); printk("Authentication failed! ErrorReg: 0x%02X\n", error); return MI_ERR; // ❌ Authentication thất bại } TM_MFRC522_STS_T MFRC522_ReadBlock(uint8_t block, uint8_t *buffer, uint16_t *back_len) { // TM_MFRC522_STS_T status; // uint8_t sendData[4]; // uint16_t length = 0; // // Chuẩn bị lệnh đọc // sendData[0] = PICC_READ; // Lệnh MIFARE_READ // sendData[1] = block; // Địa chỉ block cần đọc // // TM_MFRC522_CalculateCRC(sendData, 2, &sendData[2]); // // printf("send data: %X %X %X %X\n", sendData[0], sendData[1], sendData[2], sendData[3]); // // Gọi hàm MFRC522_ToCard // status = TM_MFRC522_ToCard(PCD_TRANSCEIVE, sendData, 2, buffer, &length); // printk("lendata: %d\n", length); // printf("status: %d\n", status); // // Kiểm tra kết quả // if (status != MI_OK) // { // return MI_ERR; // Đọc thất bại hoặc dữ liệu trả về không đúng kích thước // } // TM_MFRC522_SetBitMask(MFRC522_REG_CONTROL, 0x80); // TM_MFRC522_WrReg(MFRC522_REG_COMMAND, PCD_IDLE); // return MI_OK; // Đọc thành công // uint8_t keyA[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // Key mặc định // uint8_t blockAddr = 8; // Đọc block 8 // uint8_t authData[12]; // uint8_t backData[18]; // uint16_t backLen; // TM_MFRC522_STS_T status; // // Ghép dữ liệu xác thực // authData[0] = PICC_AUTHENT_A; // Hoặc PICC_AUTHENT_B nếu dùng Key B // authData[1] = blockAddr; // memcpy(&authData[2], keyA, 6); // memcpy(&authData[8], ID + 0, 4); // UID từ 4 byte cuối // // Thực hiện xác thực // status = TM_MFRC522_ToCard(PCD_AUTHENT, authData, 12, NULL, 0); // if (status != MI_OK) // { // printk("Authen failed\n"); // return status; // } // // Đọc dữ liệu từ block // uint8_t readCmd[2] = {PICC_READ, blockAddr}; // status = TM_MFRC522_ToCard(PCD_TRANSCEIVE, readCmd, 2, backData, &backLen); // if (status == MI_OK && backLen == 16 * 8) // { // printk("Data read from block %d: ", blockAddr); // for (int i = 0; i < 16; i++) // { // printk("%02X ", backData[i]); // } // printk("\n"); // } // else // { // printk("Read failed\n"); // } } TM_MFRC522_STS_T TM_MFRC522_WriteData(uint8_t cmd, uint8_t *data, uint8_t length) { uint8_t command = (cmd << 1) & 0x7E; // Lệnh ghi (bit 0 = 0) struct spi_buf txb[2]; struct spi_buf_set tx_bufs; txb[0].buf = &command; txb[0].len = 1; txb[1].buf = data; txb[1].len = length; tx_bufs.buffers = txb; tx_bufs.count = 2; int ret = spi_write(spi_dev, &spi_cfg, &tx_bufs); if (ret != 0) { printk("SPI transfer failed with error: %d\n", ret); } uint8_t irq = TM_MFRC522_RdReg(MFRC522_REG_COMM_IRQ); if (irq & 0x10) // Kiểm tra bit IdleIRq (0x10) { return MI_OK; // Authentication thành công } return MI_ERR; // Authentication thất bại } void TM_MFRC522_WrRegMulti(uint8_t reg, uint8_t *data, uint8_t len) { uint8_t command = ((reg << 1) & 0x7E); // Lệnh ghi struct spi_buf_set tx_bufs; struct spi_buf txb[2]; txb[0].buf = &command; txb[0].len = 1; txb[1].buf = data; txb[1].len = len; tx_bufs.buffers = txb; tx_bufs.count = 2; printf("==========>: "); for (int i = 0; i < len; i++) { printk("0x%02X ", data[i]); } printf("\n"); int ret = spi_write(spi_dev, &spi_cfg, &tx_bufs); if (ret != 0) { printk("SPI write failed! Error: %d\n", ret); } } TM_MFRC522_STS_T TM_MFRC522_Read(uint8_t blockAddr, uint8_t *recvData) { uint8_t cmd[2]; uint16_t recvLen; TM_MFRC522_STS_T status; cmd[0] = 0x30; cmd[1] = blockAddr; status = TM_MFRC522_ToCard(PCD_TRANSCEIVE, cmd, 2, recvData, &recvLen); if (status == MI_OK && recvLen == 16) { return MI_OK; } return MI_ERR; }
#include <zephyr/drivers/gpio.h> #include <zephyr/drivers/SPi.h> #include "mfrc522.h" /* The devicetree node identifier for the "led0" alias. */ #define LED0_NODE DT_ALIAS(led1) uint8_t ID[5]; /* * A build error on this line means your board is unsupported. * See the sample documentation for information on how to fix this. */ static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios); TM_MFRC522_STS_T TM_MFRC522_ReadBlock(uint8_t blockAddr, uint8_t *buffer, uint16_t *bufferLen) { TM_MFRC522_STS_T status; uint8_t cmd[2]; cmd[0] = PICC_READ; // Lệnh đọc block (0x30) cmd[1] = 0; // Địa chỉ block muốn đọc // Gửi lệnh đọc status = TM_MFRC522_ToCard(PCD_TRANSCEIVE, cmd, 2, buffer, bufferLen); // Kiểm tra kết quả if (status != MI_OK) { printk("=========================Reading block %d failed!status %d \n", blockAddr, status); return MI_ERR; } printk("Read Block %d: ", blockAddr); for (int i = 0; i < 16; i++) { printk("%02X ", buffer[i]); } printk("\n"); return MI_OK; } TM_MFRC522_STS_T TM_MFRC522_ReadUID(uint8_t *uid) { uint8_t tagType[2]; TM_MFRC522_STS_T status; // 🔹 Gửi yêu cầu kiểm tra thẻ status = MFRC522_Request(0x26, tagType); // 0x26 = REQA (0x52 nếu dùng WUPA) if (status != MI_OK) { return status; } // 🔹 Gửi lệnh Anti-Collision để lấy UID status = TM_MFRC522_Anticoll(uid); if (status != MI_OK) { return status; } // 🔹 Gửi lệnh Select thẻ // status = MFRC522_Authenticate(0x93, 0x00, NULL, uid); // Chỉ cần xác nhận UID // if (status != MI_OK) // { // return status; // } return MI_OK; } #include "MFRC522.h" uint8_t MFRC522_SelectTag(uint8_t *uid) { uint8_t buffer[9]; // Buffer dữ liệu gửi đi uint16_t recvBits; // Số bit nhận được uint8_t status; uint8_t i; uint8_t sak; // Select Acknowledge (SAK) // Gửi lệnh SELECT với mã thẻ (0x93 cho MIFARE 1K) buffer[0] = PICC_SElECTTAG; buffer[1] = 0x70; // Byte chỉ định mức SELECT for (i = 0; i < 5; i++) { buffer[i + 2] = uid[i]; // Copy UID vào buffer } // Tính CRC-A (bắt buộc để xác thực) TM_MFRC522_CalculateCRC(buffer, 7, &buffer[7]); // Gửi lệnh SELECT qua giao tiếp với thẻ status = TM_MFRC522_ToCard(PCD_TRANSCEIVE, buffer, 9, buffer, &recvBits); // Kiểm tra phản hồi từ thẻ if ((status == MI_OK) && (recvBits == 24)) { sak = buffer[0]; // Lưu Select Acknowledge (SAK) return sak; } return 0; // Lỗi hoặc thẻ không phản hồi đúng } int main(void) { int ret; SPI_Init(); TM_MFRC522_Init(); if (!gpio_is_ready_dt(&led)) { return 0; } ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE); if (ret < 0) { return 0; } uint8_t version = TM_MFRC522_RdReg(MFRC522_REG_VERSION); printk("MFRC522 Version: 0x%X\n", version); // uint8_t buffer[16]; // uint8_t len; // uint8_t status = TM_MFRC522_ReadBlock(7, buffer, &len); // if (status == MI_OK) // { // printk("Sector Trailer (Block 7): "); // for (int i = 0; i < 16; i++) // { // printk("%02X ", buffer[i]); // } // printk("\n"); // } // while (1) // { // uint8_t keyA[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // Key A mặc định // uint8_t keyB[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // Key B mặc định // // Xác thực với Key A // printk("Authentication Start\n"); // TM_MFRC522_STS_T status = TM_MFRC522_Auth(PICC_AUTHENT1A, 4, keyA, ID); // if (status != MI_OK) // { // printk("Authentication failed with Key A!\n"); // // return MI_ERR; // } // printk("Authentication successful with Key A!\n"); // // Sau khi xác thực thành công, bạn có thể tiếp tục đọc Block 7 // uint8_t buffer[16]; // uint16_t len; // printk("Read data on block Start\n"); // status = TM_MFRC522_ReadBlock(0, buffer, &len); // if (status == MI_OK) // { // printk("Block 0 data: "); // for (int i = 0; i < 16; i++) // { // printk("%02X ", buffer[i]); // } // printk("\n"); // } // printk("End Read\n"); // k_sleep(K_MSEC(1000)); // } if (TM_MFRC522_ReadUID(ID) == MI_ERR) printk("UID-1: %02X-%02X-%02X-%02X-%02X\r\n", ID[0], ID[1], ID[2], ID[3], ID[4]); if (TM_MFRC522_ReadUID(ID) == MI_ERR) printk("UID-2: %02X-%02X-%02X-%02X-%02X\r\n", ID[0], ID[1], ID[2], ID[3], ID[4]); if (TM_MFRC522_ReadUID(ID) == MI_ERR) printk("UID-3: %02X-%02X-%02X-%02X-%02X\r\n", ID[0], ID[1], ID[2], ID[3], ID[4]); uint8_t key[4][6] = { {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // Key 0: FF FF FF FF FF FF (Mặc định) {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Key 1: 00 00 00 00 00 00 {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7}, // Key 2: D3 F7 D3 F7 D3 F7 {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5} // Key 3: A0 A1 A2 A3 A4 A5 }; // uint8_t uid[4] = {0xF3, 0x50, 0xBA, 0x02}; // UID của thẻ (cần lấy từ bước đọc UID) uint8_t block_addr = 4; // Block cần xác thực uint8_t type_tag[2] = {0}; while (1) { k_sleep(K_MSEC(1000)); TM_MFRC522_Halt(); printk("=================================== MFRC522_Request\n"); if (MFRC522_Request(0x26, type_tag) != MI_OK) { printk("ERROR: MFRC522_Request failed! No card detected.\n"); continue; } printk("Card detected! Type: 0x%X 0x%X\n", type_tag[0], type_tag[1]); printk("=================================== TM_MFRC522_Anticoll\n"); if (TM_MFRC522_Anticoll(ID) != MI_OK) { printk("ERROR: TM_MFRC522_Anticoll failed! Unable to get UID.\n"); continue; } printk("Card UID: %02X %02X %02X %02X\n", ID[0], ID[1], ID[2], ID[3]); TM_MFRC522_Halt(); k_sleep(K_MSEC(500)); printk("=================================== MFRC522_SelectTag\n"); uint8_t sak = MFRC522_SelectTag(ID); if (sak == 0) { printk("ERROR: MFRC522_SelectTag failed! No response from card.\n"); continue; } printk("Card SAK: 0x%X\n", sak); TM_MFRC522_Halt(); k_sleep(K_MSEC(500)); int auth_status = MFRC522_Authenticate(PICC_AUTHENT1A, block_addr, key[0], ID); while (auth_status != MI_OK) { if (TM_MFRC522_ReadUID(ID) == MI_ERR) printk("UID-3: %02X-%02X-%02X-%02X-%02X\r\n", ID[0], ID[1], ID[2], ID[3], ID[4]); printk("Retrying Authentication...\n"); TM_MFRC522_AntennaOn(); k_sleep(K_MSEC(1000)); printk("=================================== MFRC522_Authenticate\n"); auth_status = MFRC522_Authenticate(PICC_AUTHENT1A, block_addr, key[0], ID); if(auth_status == MI_OK) { printk("========================== MFRC522_Authenticate Fail\n"); } TM_MFRC522_AntennaOff(); k_sleep(K_MSEC(1000)); TM_MFRC522_AntennaOn(); uint8_t buffer[16]; uint16_t len; printk("Read data onblock\n"); uint8_t status = TM_MFRC522_ReadBlock(block_addr, buffer, &len); } return 0; } }
Hello everyone,
I am currently facing an issue when trying to read data from a block of a Mifare 1K card. After debugging, I found that my program fails to authenticate the sector of the block. Has anyone encountered this issue before?
Enviroment: nrf connect Desktop, nRF Connect SDK Toolchain v2.9.0
Lib MFRC522: mfrc5222_lib
TM_MFRC522_STS_T TM_MFRC522_Read(uint8_t blockAddr, uint8_t *recvData) { uint8_t cmd[2]; uint16_t recvLen; TM_MFRC522_STS_T status; cmd[0] = 0x30; cmd[1] = blockAddr; status = TM_MFRC522_ToCard(PCD_TRANSCEIVE, cmd, 2, recvData, &recvLen); if (status == MI_OK && recvLen == 16) { return MI_OK; } return MI_ERR; }