如何解决STM32驱动MFRC522收发功能失效问题?
MFRC522与STM32无线通信故障调试求助
我正在开发一款基于STM32和MFRC522的PCB,用于读写13.56MHz RFID标签。目前已实现寄存器的读写操作,但无线通信功能无法正常工作。硬件与常见Arduino MFRC522 breakout board高度匹配,线圈场强良好,因此确信问题出在固件层面。
MFRC.c驱动文件
/* Write single byte MFRC register * * @param addr: register address * * @param data: value to write to register */ HAL_StatusTypeDef MFRC_REGW(uint8_t addr,uint8_t data){ uint8_t value=data; if(HAL_I2C_Mem_Write(&hi2c1, MFRC_ADDR<<1, addr, 1, &value, 1, 100)!=HAL_OK){ return(HAL_ERROR); } else{ return(HAL_OK); } HAL_Delay(1); } /* Read single byte from MFRC register * * @param addr: register address * * @param data: pointer to store read value */ HAL_StatusTypeDef MFRC_REGR(uint8_t addr,uint8_t* data){ if(HAL_I2C_Mem_Read(&hi2c1, MFRC_ADDR<<1, addr, 1, data, 1, 100)!=HAL_OK){ return(HAL_ERROR); } else{ return(HAL_OK); } HAL_Delay(1); } /* Write to MFRC FIFO buffer * * @param data: Array of data to write to FIFO * * @param size: Size of array (bytes) */ HAL_StatusTypeDef MFRC_FIFOW(uint8_t* data,uint8_t size){ for(int i=0;i<size;i++){ if(HAL_I2C_Mem_Write(&hi2c1, MFRC_ADDR<<1, 0x09, 1, &data[i], 1, 100)!=HAL_OK){ return(HAL_ERROR); } HAL_Delay(1); } return(HAL_OK); } /* Read from MFRC FIFO buffer * * @param data: Array to store read values (Ensure array is large enough) * * @param size: Number of bytes to read from FIFO */ HAL_StatusTypeDef MFRC_FIFOR(uint8_t* data,uint8_t size){ for(int i=0;i<size;i++){ if(HAL_I2C_Mem_Read(&hi2c1, MFRC_ADDR<<1, 0x09, 1, &data[i], 1, 100)!=HAL_OK){ return(HAL_ERROR); } HAL_Delay(1); } return(HAL_OK); } /* * Function to calculate CRC on whatever data is in FIFO * !!CRCIRQ bit in DivIrqReg register can be used to detect when CRC has been calculated!! * * @param result: Array to store the two bytes of CRC * * */ HAL_StatusTypeDef CALC_CRC(uint8_t* data,uint8_t size,uint8_t* result){ uint8_t CRCIRQ; MFRC_REGW(CMD_REG,IDLE); //clear command register MFRC_REGW(DIVIRQ,0x04); //Clear interrupt bits so we can detect when CRCIRQ is set MFRC_REGW(FIFO_LEV,0x80); MFRC_FIFOW(data, size); //Write data to FIFO ready for CRC calculation MFRC_REGW(CMD_REG,CALCCRC); //Execute CRC calculation command HAL_Delay(100); MFRC_REGR(DIVIRQ,&CRCIRQ); if((CRCIRQ&0x04)!=0x04){ return(HAL_ERROR); } MFRC_REGW(CMD_REG,IDLE); MFRC_REGR(CRCL, &result[0]); MFRC_REGR(CRCH,&result[1]); return(HAL_OK); } /* Initialise MFRC to begin transceiving * * Code is written to interface with MIFARE Ultralight PICC. Different PICCs will need different baud rate. */ HAL_StatusTypeDef MFRC_INIT(void){ HAL_GPIO_WritePin(GPIOB, NRST, 1); //Make sure MFRC is not reset HAL_GPIO_WritePin(GPIOB, NRST, 0); HAL_Delay(1); HAL_GPIO_WritePin(GPIOB, NRST, 1); HAL_Delay(50); MFRC_REGW(TX_REG,0x00); MFRC_REGW(RX_REG,0x00); SET_ANTGAIN(); MFRC_REGW(MODWIDTH,0x26); //MFRC_REGW(TModeReg,0x80); //timer starts automatically after every transmission //MFRC_REGW(TPrescalerRegLO,0xA9); //Set prescaler to 169 => f_timer=40kHz, use this for timeouts //MFRC_REGW(TReloadHI,0x03); //Set reload counter to 4000 => 100ms timeout //MFRC_REGW(TReloadLO,0xE8); MFRC_REGW(TXASK,0x40); //Force 100% ASK modulation regardless of ModGsPrereg MFRC_REGW(MODE_REG,0x3D); MFRC_ANTON(); return(HAL_OK); } /* Transceive data between MFRC and PICC * * @param sendData: Array of data to send * * @param sendsize: Number of bytes to send * * @param recdata: Array to store received data * * @param recsize: Number of bytes to receive * */ HAL_StatusTypeDef MFRC_TRANSCEIVE(uint8_t* sendData,uint8_t sendsize,uint8_t* recdata,uint8_t recsize){ uint8_t IRQval=0; uint8_t BIT_val=0; uint8_t stat; uint8_t transaction[sendsize]; memcpy(transaction,sendData,sendsize); MFRC_REGW(CMD_REG,IDLE); //Clear command register MFRC_REGW(IRQ_REG,0x7F); MFRC_REGW(BITFRAME,0x00); MFRC_REGW(FIFO_LEV,0x80); //Clear FIFO buffer MFRC_FIFOW(sendData,sendsize); //Write data to FIFO ready for transmission //MFRC_FIFOR(FIFO_State, sendsize); //CDC_Transmit_FS(FIFO_State, sendsize); MFRC_REGW(CMD_REG,TRANSCEIVE); //Send FIFO data and receive PICC response MFRC_REGR(BITFRAME,&BIT_val); MFRC_REGW(BITFRAME,(BIT_val|0x80)); //Start send bit HAL_Delay(100); MFRC_REGR(IRQ_REG,&IRQval); if((IRQval&0x30)!=0x30){ //Return error if RXIRQ and IDLEIRQ bits are not set return(HAL_ERROR); } MFRC_FIFOR(recdata,recsize); //Read and store received data return(HAL_OK); }
main.c代码片段
HAL_Delay(5000); MFRC_INIT(); uint8_t value[18]; uint8_t CRC_val[2]; uint8_t FIFO; uint8_t transaction[4]={0x30,0x00}; //Read starting from 0x00 and we will receive first four pages (16 bytes) + CRC (2 bytes) char mess[]="Transceive Error"; char messcrc[]="CRC error"; /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { if(CALC_CRC(transaction, 2, CRC_val)!=HAL_OK){ CDC_Transmit_FS(messcrc, strlen(messcrc)); } memcpy(transaction+2,CRC_val,2); //CDC_Transmit_FS(transaction, 4); if(MFRC_TRANSCEIVE(transaction, 4, value, 18)!=HAL_OK){ } else{ CDC_Transmit_FS(value, 18); } HAL_Delay(1000); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
当前排查情况
- 目标功能:读取MIFARE Ultralight PICC的前4页内存
- 参考实现:基于广泛使用的MFRC522 Arduino库,但核心的
MFRC_TRANSCEIVE函数无法正常工作 - 发送状态:数据已写入FIFO并发送(发送前FIFO_LEVEL寄存器值为4,发送TRANSCEIVE命令后变为0)
- CRC疑点:针对读取命令
0x30,0x00,MFRC522计算出的CRC为0xA802,与在线ISO CRC计算器结果不符,怀疑CRC错误可能是故障根源,但无法确认
求助需求
除CRC问题外,不确定还有哪些可能的故障点,恳请有MFRC522驱动开发经验的人士提供调试思路。
内容的提问来源于stack exchange,提问作者Swiss Gnome
相关产品推荐
相关产品推荐

