342 lines
7.1 KiB
C
342 lines
7.1 KiB
C
#include "RFID.h"
|
|
#include "main.h"
|
|
#include "stdbool.h"
|
|
#include "stdio.h"
|
|
|
|
/**
|
|
* @brief initialize function
|
|
*/
|
|
|
|
/**
|
|
* @brief read register
|
|
*/
|
|
|
|
|
|
bool rc522_toCard(
|
|
uint8_t command,
|
|
uint8_t* sendData,
|
|
uint8_t sendLen,
|
|
uint8_t* backData,
|
|
uint16_t* backLen);
|
|
|
|
bool rc522_request(uint8_t reqMode, uint8_t *tagType);
|
|
|
|
bool rc522_antiColl(uint8_t* serNum);
|
|
|
|
void spi_cs_rfid_write(bool state)
|
|
{
|
|
HAL_GPIO_WritePin(RFID_CS_GPIO_Port, RFID_CS_Pin, state);
|
|
}
|
|
|
|
uint8_t rc522_regRead8(uint8_t reg)
|
|
{
|
|
spi_cs_rfid_write(0);
|
|
reg = ((reg << 1) & 0x7E) | 0x80;
|
|
// spi1_transmit(®, 1);
|
|
// TODO: change to interrupting or something.
|
|
HAL_SPI_Transmit(&hspi1, ®, 1, 1000);
|
|
uint8_t dataRd=0;
|
|
HAL_SPI_Receive(&hspi1, &dataRd, 1, 1000);
|
|
// spi1_receive(&dataRd, 1);
|
|
spi_cs_rfid_write(1);
|
|
return dataRd;
|
|
}
|
|
|
|
/**
|
|
* @brief write register
|
|
*/
|
|
void rc522_regWrite8(uint8_t reg, uint8_t data8)
|
|
{
|
|
spi_cs_rfid_write(0);
|
|
uint8_t txData[2] = {0x7E&(reg << 1), data8};
|
|
// spi1_transmit(txData, 2);
|
|
HAL_SPI_Transmit(&hspi1, (uint8_t*)&txData, 2, 1000);
|
|
spi_cs_rfid_write(1);
|
|
}
|
|
|
|
/**
|
|
* @brief set bit
|
|
*/
|
|
void rc522_setBit(uint8_t reg, uint8_t mask)
|
|
{
|
|
rc522_regWrite8(reg, rc522_regRead8(reg)|mask);
|
|
}
|
|
|
|
/**
|
|
* @brief clear bit
|
|
*/
|
|
void rc522_clearBit(uint8_t reg, uint8_t mask)
|
|
{
|
|
rc522_regWrite8(reg, rc522_regRead8(reg)&(~mask));
|
|
}
|
|
|
|
/**
|
|
* @brief reset function
|
|
*/
|
|
void rc522_reset(void)
|
|
{
|
|
rc522_regWrite8(0x01, 0x0F);
|
|
}
|
|
|
|
/**
|
|
* @brief Antenna ON
|
|
*/
|
|
void rc522_antennaON(void)
|
|
{
|
|
uint8_t temp;
|
|
|
|
temp = rc522_regRead8(MFRC522_REG_TX_CONTROL);
|
|
if (!(temp & 0x03)) {
|
|
rc522_setBit(MFRC522_REG_TX_CONTROL, 0x03);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Check card
|
|
*/
|
|
bool rc522_checkCard(uint8_t *id)
|
|
{
|
|
bool status=false;
|
|
//Find cards, return card type
|
|
status = rc522_request(PICC_REQIDL, id);
|
|
if (status == true) {
|
|
//Card detected
|
|
//Anti-collision, return card serial number 4 bytes
|
|
status = rc522_antiColl(id);
|
|
}
|
|
rc522_halt(); //Command card into hibernation
|
|
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* @brief Request function
|
|
*/
|
|
bool rc522_request(uint8_t reqMode, uint8_t *tagType)
|
|
{
|
|
bool status=false;
|
|
uint16_t backBits;
|
|
rc522_regWrite8(MFRC522_REG_BIT_FRAMING, 0x07);
|
|
tagType[0] = reqMode;
|
|
status = rc522_toCard(PCD_TRANSCEIVE, tagType, 1, tagType, &backBits);
|
|
if ((status != true) || (backBits != 0x10)) {
|
|
status = false;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* @brief to Card
|
|
*/
|
|
bool rc522_toCard(
|
|
uint8_t command,
|
|
uint8_t* sendData,
|
|
uint8_t sendLen,
|
|
uint8_t* backData,
|
|
uint16_t* backLen)
|
|
{
|
|
bool status = false;
|
|
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;
|
|
}
|
|
|
|
rc522_regWrite8(MFRC522_REG_COMM_IE_N, irqEn | 0x80);
|
|
rc522_clearBit(MFRC522_REG_COMM_IRQ, 0x80);
|
|
rc522_setBit(MFRC522_REG_FIFO_LEVEL, 0x80);
|
|
|
|
rc522_regWrite8(MFRC522_REG_COMMAND, PCD_IDLE);
|
|
|
|
//Writing data to the FIFO
|
|
for (i = 0; i < sendLen; i++) {
|
|
rc522_regWrite8(MFRC522_REG_FIFO_DATA, sendData[i]);
|
|
}
|
|
|
|
//Execute the command
|
|
rc522_regWrite8(MFRC522_REG_COMMAND, command);
|
|
if (command == PCD_TRANSCEIVE) {
|
|
rc522_setBit(MFRC522_REG_BIT_FRAMING, 0x80); //StartSend=1,transmission of data starts
|
|
}
|
|
|
|
//Waiting to receive data to complete
|
|
i = 100; //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 = rc522_regRead8(MFRC522_REG_COMM_IRQ);
|
|
i--;
|
|
} while ((i!=0) && !(n&0x01) && !(n&waitIRq));
|
|
|
|
rc522_clearBit(MFRC522_REG_BIT_FRAMING, 0x80); //StartSend=0
|
|
|
|
if (i != 0) {
|
|
if (!(rc522_regRead8(MFRC522_REG_ERROR) & 0x1B)) {
|
|
status = true;
|
|
if (n & irqEn & 0x01) {
|
|
status = false;
|
|
}
|
|
|
|
if (command == PCD_TRANSCEIVE) {
|
|
n = rc522_regRead8(MFRC522_REG_FIFO_LEVEL);
|
|
uint8_t l = n;
|
|
lastBits = rc522_regRead8(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++) {
|
|
uint8_t d = rc522_regRead8(MFRC522_REG_FIFO_DATA);
|
|
if (l == 4)
|
|
printf("%02x ", d);
|
|
backData[i] = d;
|
|
}
|
|
if (l==4)
|
|
printf("\r\n");
|
|
return status;
|
|
}
|
|
} else {
|
|
printf("error\r\n");
|
|
status = false;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
bool rc522_antiColl(uint8_t* serNum)
|
|
{
|
|
bool status;
|
|
uint8_t i;
|
|
uint8_t serNumCheck = 0;
|
|
uint16_t unLen;
|
|
//for (i = 0; i < 4; i++)
|
|
// printf("Anticoll In %d: 0x%02x\r\n", i, serNum[i]);
|
|
|
|
|
|
rc522_regWrite8(MFRC522_REG_BIT_FRAMING, 0x00); //TxLastBists = BitFramingReg[2..0]
|
|
|
|
serNum[0] = PICC_ANTICOLL;
|
|
serNum[1] = 0x20;
|
|
status = rc522_toCard(PCD_TRANSCEIVE, serNum, 2, serNum, &unLen);
|
|
|
|
//for (i = 0; i < 4; i++)
|
|
// printf("Anticoll ToCard %d: 0x%02x\r\n", i, serNum[i]);
|
|
|
|
if (status == true) {
|
|
//Check card serial number
|
|
for (i = 0; i < 4; i++) {
|
|
serNumCheck ^= serNum[i];
|
|
}
|
|
if (serNumCheck != serNum[i]) {
|
|
status = false;
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
void rc522_halt(void)
|
|
{
|
|
uint16_t unLen;
|
|
uint8_t buff[4];
|
|
|
|
buff[0] = PICC_HALT;
|
|
buff[1] = 0;
|
|
rc522_calculateCRC(buff, 2, &buff[2]);
|
|
|
|
rc522_toCard(PCD_TRANSCEIVE, buff, 4, buff, &unLen);
|
|
}
|
|
|
|
void rc522_calculateCRC(uint8_t* pIndata, uint8_t len, uint8_t* pOutData)
|
|
{
|
|
uint8_t i, n;
|
|
|
|
rc522_clearBit(MFRC522_REG_DIV_IRQ, 0x04); //CRCIrq = 0
|
|
rc522_setBit(MFRC522_REG_FIFO_LEVEL, 0x80); //Clear the FIFO pointer
|
|
//Write_MFRC522(CommandReg, PCD_IDLE);
|
|
|
|
//Writing data to the FIFO
|
|
for (i = 0; i < len; i++) {
|
|
rc522_regWrite8(MFRC522_REG_FIFO_DATA, *(pIndata+i));
|
|
}
|
|
rc522_regWrite8(MFRC522_REG_COMMAND, PCD_CALCCRC);
|
|
|
|
//Wait CRC calculation is complete
|
|
i = 0xFF;
|
|
do {
|
|
n = rc522_regRead8(MFRC522_REG_DIV_IRQ);
|
|
i--;
|
|
} while ((i!=0) && !(n&0x04)); //CRCIrq = 1
|
|
|
|
//Read CRC calculation result
|
|
pOutData[0] = rc522_regRead8(MFRC522_REG_CRC_RESULT_L);
|
|
pOutData[1] = rc522_regRead8(MFRC522_REG_CRC_RESULT_M);
|
|
}
|
|
|
|
/**
|
|
* @brief compare IDs
|
|
*/
|
|
bool rc522_compareIds(uint8_t *idCurrent, uint8_t *idReference)
|
|
{
|
|
uint8_t i;
|
|
for(i=0; i<4;i++)
|
|
{
|
|
if(idCurrent[i] != idReference[i])
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void rc522_init(void)
|
|
{
|
|
/*
|
|
* STM32 ->RFID
|
|
* SPI -> SPI
|
|
* PA8 ->RST
|
|
* PB0 ->CS
|
|
* */
|
|
|
|
HAL_GPIO_WritePin(RFID_RST_GPIO_Port, RFID_RST_Pin, 0);
|
|
HAL_GPIO_WritePin(RFID_RST_GPIO_Port, RFID_RST_Pin, 1);
|
|
rc522_reset();
|
|
|
|
rc522_regWrite8(MFRC522_REG_T_MODE, 0x80);
|
|
rc522_regWrite8(MFRC522_REG_T_PRESCALER, 0xA9);
|
|
rc522_regWrite8(MFRC522_REG_T_RELOAD_L, 0xE8);
|
|
rc522_regWrite8(MFRC522_REG_T_RELOAD_H, 0x03);
|
|
|
|
|
|
rc522_regWrite8(MFRC522_REG_TX_AUTO, 0x40);
|
|
rc522_regWrite8(MFRC522_REG_MODE, 0x3D);
|
|
|
|
rc522_antennaON(); //Open the antenna
|
|
}
|
|
|