IC卡读卡
时间:10-02
整理:3721RD
点击:
上一篇我们把SPI的驱动搞定了,那么下一步,就是要使用SPI协议对RC522进行读写了。
RC522 是应用于13.56MHz 非接触式通信中高集成度读写卡系列芯片中的一员。是NXP 公司针对“三表”应用推出的一款低电压、低成本、体积小的非接触式读写卡芯片,是智能仪表和便携 式手持设备研发的较好选择
RC522运行以下三种通讯方式,UART、SPI、I2C。其对应于引脚列表如下图:
SPI的写数据
SPI的读数据
本功能主要是移植STM32方案的IC卡读取程序,打开SPI设备,SPI的配置。
- static uint8_t mode = 0;
- static uint8_t bits = 8;
- static uint32_t speed = 50000;
- static uint16_t delay;
-
- int ret = 0;
- int fd;
-
- fd = open("/dev/spidev1.0", O_RDWR);
- ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
- ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
- ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
- ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
- ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
- ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
-
接收数据程序
- uint8_t rx[32];
- int receive_data(unsigned char *rBuf, unsigned int size,int fd) {
-
- struct spi_ioc_transfer tr = {
- .rx_buf = (unsigned long) rx,
- .len = size,
- .delay_usecs = delay,
- .speed_hz = speed,
- .bits_per_word = bits,
- };
-
- return ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- }
发送数据程序
- uint8_t tx[32];
- int send_data(unsigned char *rBuf, unsigned int size,int fd) {
-
- struct spi_ioc_transfer tr = {
- .tx_buf = (unsigned long) tx,
- .len = size,
- .delay_usecs = delay,
- .speed_hz = speed,
- .bits_per_word = bits,
- };
-
- return ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
- }
对卡的操作分成四步:寻卡→防冲突→选卡→读/写卡;
寻卡:
- char PcdRequest(unsigned char req_code, unsigned char *pTagType,int fd)
- {
- char status;
- unsigned int unLen;
- unsigned char ucComMF522Buf[MAXRLEN];
-
- ClearBitMask(Status2Reg, 0x08,int fd);
- WriteRawRC(BitFramingReg, 0x07,int fd);
- SetBitMask(TxControlReg, 0x03,int fd);
- ucComMF522Buf[0] = req_code;
- status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 1, ucComMF522Buf, &unLen,int fd);
- if ((status == MI_OK) && (unLen == 0x10)) {
- *pTagType = ucComMF522Buf[0];
- *(pTagType + 1) = ucComMF522Buf[1];
- } else {
- status = MI_ERR;
- }
- return status;
- }
防冲突:
- char PcdAnticoll(unsigned char *pSnr,int fd)
- {
- char status;
- unsigned char i, snr_check = 0;
- unsigned int unLen;
- unsigned char ucComMF522Buf[MAXRLEN];
- ClearBitMask(Status2Reg, 0x08,int fd);
- WriteRawRC(BitFramingReg, 0x00,int fd);
- ClearBitMask(CollReg, 0x80,int fd);
- ucComMF522Buf[0] = PICC_ANTICOLL1;
- ucComMF522Buf[1] = 0x20;
- status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 2, ucComMF522Buf, &unLen,int fd);
- if (status == MI_OK) {
- for (i = 0; i < 4; i++) {
- *(pSnr + i) = ucComMF522Buf[i];
- snr_check ^= ucComMF522Buf[i];
- }
- if (snr_check != ucComMF522Buf[i]) {
- status = MI_ERR;
- }
- }
- SetBitMask(CollReg, 0x80,int fd);
- return status;
- }
其他函数,也是类似的,基本与STM32上的函数用法是一样的,只是添加文件描述符。使每个函数都通过文件描述符所打开的设备。不再赘述。
IC卡模块与转接板的连接:
程序在开发板上,程序将在IC卡上写入两个数据,再读取出来,判断两次操作的值是不是一样以判断IC卡驱动程序的正确运行,其运行结果:
可以看到已经可以正确对IC卡进行读写了,但是这样的方式只是对数据的明文传输,在正常的应用过程中,还要对数据进行必要的加密,以及对IC卡中的存储扇区进行功能上的划分,以确保安全。其实际市场应用还要使用到国网的加密模块芯片,由于手头上也没有,就无法测试了。