单片机基于CR95HF的NFC读卡器方案
在物联网产品开发过程中,近距离与静态标签和动态标签无线通信的NFC读卡器比较丰富,
与MCU提供众多通信接口,比如串口,I2C,SPI等等,并且使用复杂的框架库和交互协议
使得调试起来比较麻烦。
CR95HF提供串口通信,简单字节序的应答逻辑,方便快速与NFC标签完成交互。
ST公司的CR95HF具有SPI和UART串行连接的多协议无接触13.6MHz收发器IC,可作为13.56MHz空中接口的模拟前端(AFE),支持ISO / IEC 14443 A和B,ISO / IEC 15693 (单或双用户)以及ISO / IEC 18092等协议,能管理阅读器模式的帧编码和转换,主要用在NFC中,接近标准应用。
CR95HF是用于非接触式应用的集成收发器IC。

cr95hf.c使用串口阻塞方式与读卡器交互。
#ifndef __CR95HF_H__
#define __CR95HF_H__#include
#include "usart3.h"
#include "comtypes.h"BOOLEAN CR95HF_Init(void);BOOLEAN CR95HF_Inventory(uint8_t*uid);BOOLEAN CR95HF_ReadBlock(uint8_t*text,uint8_t*textlen);#endif
#include "cr95hf.h"/*
串口波特率576001.协议选择iso15693 LR family02 02 01 05成功返回00 002.射频增益配置09 04 68 01 01 50成功返回00 003.标签搜索04 03 26 01 00成功返回80 0D 00 00 0C BC C1 11 00 24 02 E0(UID) 6F B1 00no tag87 004.获取标签系统信息04 02 02 2B成功返回80 12 00 0F 0C BC C1 11 00 24 02 E0(UID) 00(DSFID) 00(AFI) 7F(MemorySize) 03(BlockSize) 24(IC Reference) AA 61 005.读块04 03 02 20 00(00--7F)遍历成功结果,每行从index 03取4个字节TEXT存储结构:D1 01 textSize T(54) 02 en(65 6E) text80 08 00 E1 40 40 05 FB 70 0080 08 00 03 27 D1 01 EE 32 0080 08 00 23 54 02 65 70 82 0080 08 00 6E 22 E0 41 46 F4 0080 08 00 F5 6A C4 A9 3D 35 0080 08 00 26 5A 63 C7 A9 06 0080 08 00 99 9E 34 03 E0 A2 0080 08 00 FD F0 AB 30 33 C5 0080 08 00 EF 43 3D AB 15 3D 0080 08 00 A2 AA 8B 61 7A 32 0080 08 00 4F A7 FF DE D8 28 0080 08 00 E8 FE 00 00 0A 02 0080 08 00 00 00 00 00 77 CF 0080 08 00 00 00 00 00 77 CF 00*/static const uint8_t protocol_sel[] = {0x02,0x02,0x01,0x05};static const uint8_t rf_gain[] = {0x09,0x04,0x68,0x01,0x01,0x50};static const uint8_t label_inventory[] = {0x04,0x03,0x26,0x01,0x00};static const uint8_t lable_system_info[] = {0x04,0x02,0x02,0x2B};static uint8_t read_single_block[] = {0x04,0x03,0x02,0x20,0x00};#define KEYWORDS "_CR95HF_"
#define KEYWORDS_LENGTH 8/**
串口配置,协议选择,增益配置,芯片初始化。
*/
BOOLEAN CR95HF_Init(void)
{uint8_t tmpbuf[2];uint8_t trycnt;USART3_Init(57600);HAL_Delay(100);trycnt = 0;memset(tmpbuf,0x01,sizeof(tmpbuf));TRY_PROTOCOL_SEL_WRITE: USART3_SendBuffer((uint8_t*)protocol_sel,sizeof(protocol_sel));USART3_ReceiveBuffer(tmpbuf,sizeof(tmpbuf));if(!(tmpbuf[0] == 0 && tmpbuf[1] == 0)){if(trycnt++ < 10) goto TRY_PROTOCOL_SEL_WRITE;else return FALSE;}trycnt = 0;memset(tmpbuf,0x01,sizeof(tmpbuf));TRY_RF_GAIN_WRITE: USART3_SendBuffer((uint8_t*)rf_gain,sizeof(rf_gain));USART3_ReceiveBuffer(tmpbuf,2);if(!(tmpbuf[0] == 0 && tmpbuf[1] == 0)){if(trycnt++ < 10) goto TRY_RF_GAIN_WRITE;else return FALSE;}return TRUE;
}/**
搜索NFC标签并返回标签UID。
*/
BOOLEAN CR95HF_Inventory(uint8_t*uid)
{uint8_t tmpbuf[20];uint8_t trycnt;uint8_t i; trycnt = 0;memset(tmpbuf,0,sizeof(tmpbuf));TRY_LABEL_INVENTORY_WRITE: USART3_SendBuffer((uint8_t*)label_inventory,sizeof(label_inventory));USART3_ReceiveBuffer(tmpbuf,sizeof(tmpbuf));//没有应答if(tmpbuf[0] == 0x00){if(trycnt++ < 10) goto TRY_LABEL_INVENTORY_WRITE;else return FALSE;}//搜索到标签else if(tmpbuf[0] == 0x80 && tmpbuf[1] == 0x0D){if(uid == NULL) return TRUE;memcpy(uid,&tmpbuf[4],8);//需要颠倒一下for(i=0;i < 4;i++){trycnt = uid[i];uid[i] = uid[7 - i];uid[7 - i] = trycnt;}return TRUE;}//没有发现else{//tmpbuf[0] == 0x87return FALSE;}
}/**
读取标签系统信息,获取内存大小和块大小,轮询所有块找出有标记信息的即为存储内容所在位置。
*/
BOOLEAN CR95HF_ReadBlock(uint8_t*text,uint8_t*textlen)
{#define SYSTEM_INFO_SIZE (24)#define READ_BLOCK_SIZE (10)uint8_t tmpbuf[SYSTEM_INFO_SIZE];uint8_t readbuf[128];uint8_t trycnt;uint8_t i,j;uint16_t memorysize; trycnt = 0;memset(tmpbuf,0,SYSTEM_INFO_SIZE);TRY_LABEL_SYSTEM_INFO_WRITE: USART3_SendBuffer((uint8_t*)lable_system_info,sizeof(lable_system_info));USART3_ReceiveBuffer(tmpbuf,SYSTEM_INFO_SIZE);//没有应答if(tmpbuf[0] == 0x00){if(trycnt++ < 10) goto TRY_LABEL_SYSTEM_INFO_WRITE;else return FALSE;}else if(tmpbuf[0] == 0x80 && tmpbuf[1] == 0x12){memorysize = tmpbuf[14];}else{return FALSE;} memset(readbuf,0,sizeof(readbuf));for(i=0;i < memorysize / 4;i++){trycnt = 0;memset(tmpbuf,0,READ_BLOCK_SIZE);TRY_READ_SINGLE_BLOCK_WRITE:read_single_block[4] = i; USART3_SendBuffer((uint8_t*)read_single_block,sizeof(read_single_block));USART3_ReceiveBuffer(tmpbuf,READ_BLOCK_SIZE);//没有应答if(tmpbuf[0] == 0x00){if(trycnt++ < 10) goto TRY_READ_SINGLE_BLOCK_WRITE;else return FALSE;}else if(tmpbuf[0] == 0x80 && tmpbuf[1] == 0x08){memcpy(&readbuf[i << 2],&tmpbuf[3],4);if(tmpbuf[7] == 0x77 && tmpbuf[8] == 0xCF) break;}else{return FALSE;} }//逐字节比较关键字,找出标记信息,获取真实内容。for(j=0;j < i << 2;j++){if(readbuf[j] == 0xD1 && readbuf[j + 1] == 0x01){*textlen = readbuf[j + 2] - 3 - KEYWORDS_LENGTH;if(readbuf[j + 3] == 0x54 && readbuf[j + 4] == 0x02 &&readbuf[j + 5] == 0x65 && readbuf[j + 6] == 0x6E){if(strncmp(KEYWORDS,&readbuf[j + 7]),KEYWORDS_LENGTH)) return FALSEmemcpy(text,&readbuf[j + 7 + KEYWORDS_LENGTH],*textlen);return TRUE;}else break;}}return FALSE;
}/***
for test
if(CR95HF_Init())
{USART1_SendBuf("OKOK",4);
}
else{USART1_SendBuf("FAILED",6);
}uint8_t uid[8];
uint8_t readata[128];
uint8_t readlen;while(1)
{if(CR95HF_Inventory(uid)){if(CR95HF_ReadBlock(readata,&readlen))USART1_SendBuf(readata,readlen);}HAL_Delay(100);
}
*/
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
