#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;
}