前言:
前些日子老师布置一个任务叫我们焊接一个RFID读卡器,其中刚好我们手上也有一个STM32F103RBT6开发板,老师于是布置任务叫我们用STM32完成对EM4100进行读卡操作
EM4100简介:
中 文 名:EM4100卡 存储容量:64bit 工作频率:125KHZ 读写距离:2-15cm 产品名称:EM4100/EM4102卡 芯片类型:μEM瑞士微电 EM4100/EM4102 擦写寿命:读不限,只读 外形尺寸:ISO标准卡/厚卡 封装材料:PVC、ABS 典型应用:身份识别、考勤系统、门禁系统、财物标识等 详细资料: 进口瑞士微电子EM4100/4102无线射频芯片,采用先进的芯片封装工艺,可作为非接触卡片应用的优良解决方案。同时提供优惠的印刷服务和适合应用环境的异形卡。可广泛用于身份识别,考勤系统,门禁系统,财物标识,过程控制,企业一卡通系统,停车,物流,动物识别,身份识别,识别货品,工业自动化,会议签到,电子标签,超市,仓库管理,人员管理,安防系统,医疗机构等。
EM4100卡命名的原因是该卡的核心芯片是由EM Microelectronic(瑞士微电)公司生产。
该段信息来源 https://blog.csdn.net/yichu5074/article/details/82621415
EM4100数据帧格式
要点:
- 数据总共有64bit。
- 以连续的9个1开头。
- 前4个bit为厂商位。
- 采用偶校验的方法。(保证1的个数为偶数个)
- 最后一列为行校验。
- 最后一行为列检验。
- 数据最后一位为0。
曼彻斯特编码:
两种格式刚好相反:
- 第一种:(EM4100采用这种编码)
1:高电平到低电平(下降) 0:低电平到高电平(上升) - 第二种:
1:低电平到高电平(上升) 0:高电平到低电平(下降)
下图为一次完整的EM4100帧数据
STM32F103RBT6解码EM4100:
思路:
- 首先找到高电平时间或者低电平时间在
512us 附近。 - 找到后标记已经同步,并且此时为一次有效捕获中断。
- 下一次上升沿或者下降沿必须距离上一次有效捕获中断512us附近。
- 选用
uint64_t 的RFID_DATA 来存放每一次有效数据。 - 采集完一次有效捕获中断后检查
RFID_DATA 是否以连续的9个1开头并且最后一位为0。 - 如果满足条件则标记采集完成。否则继续采集。
采用的外设:TIM2 TIM3
- TIM2:捕获中断以及125khz载波生成。
- TIM3:计时器(32us更新中断一次,每次
RFID_CNT 增加1 )
行校验以及列检验思路:
方案①: 每一行(除了连续的9个1以及最后一行)加起来%2 为0。前四列加起来%2 为0。(不推荐) 方案②: 采用异或逻辑^ :每一行(除了连续的9个1以及最后一行)异或为0。前四列异或为0。
代码片段:
RFID_init(void)
void RFID_init(void){
TIM_TimeBaseInitTypeDef TIM2_struct;
TIM_OCInitTypeDef TIM2_oc;
GPIO_InitTypeDef GPIO1_InitStruct;
GPIO_InitTypeDef GPIO2_InitStruct;
TIM_ICInitTypeDef TIM2_ICInitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIMER_init(3,71,31);
GPIO1_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO1_InitStruct.GPIO_Pin=RFID_PIN_IN;
GPIO1_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO2_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO2_InitStruct.GPIO_Pin=RFID_PIN_OUT;
GPIO2_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(RFID_IN, &GPIO1_InitStruct);
GPIO_Init(RFID_OUT, &GPIO2_InitStruct);
TIM2_struct.TIM_ClockDivision=TIM_CKD_DIV1;
TIM2_struct.TIM_Prescaler=71;
TIM2_struct.TIM_CounterMode=TIM_CounterMode_Up;
TIM2_struct.TIM_Period=7;
TIM_ARRPreloadConfig(TIM2, ENABLE);
TIM_TimeBaseInit(TIM2, &TIM2_struct);
TIM2_oc.TIM_OCMode=TIM_OCMode_PWM1;
TIM2_oc.TIM_OCPolarity=TIM_OCPolarity_High;
TIM2_oc.TIM_OutputState=TIM_OutputState_Enable;
TIM2_oc.TIM_Pulse=4;
TIM_OC1Init(TIM2,&TIM2_oc);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_InitStruct);
TIM2_ICInitStruct.TIM_Channel=TIM_Channel_2;
TIM2_ICInitStruct.TIM_ICFilter=0xf;
TIM2_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_Falling;
TIM2_ICInitStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1;
TIM2_ICInitStruct.TIM_ICSelection=TIM_ICSelection_DirectTI;
TIM_ICInit(TIM2, &TIM2_ICInitStruct);
TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
TIM_Cmd(TIM2, ENABLE);
}
void TIM2_IRQHandler(void)
uint64_t RFID_DATA=0;
u8 RFID_CNT=0;
u8 RFID_STA=0;
u16 TIME_CNT=0;
const u16 Sample=384;
const u8 Sample_Per=32;
void TIM2_IRQHandler(void){
if(TIM_GetITStatus(TIM2,TIM_IT_CC2)!=RESET){
if((RFID_STA&0X80)==0){
if(GPIO_ReadInputDataBit(RFID_OUT, RFID_PIN_OUT)==Bit_SET){
TIM_OC2PolarityConfig(TIM2, TIM_ICPolarity_Falling);
if(RFID_STA&0X20){
if((RFID_CNT>(Sample/Sample_Per))&&(RFID_CNT<2*(Sample/Sample_Per))){RFID_STA|=0X80;}
else{RFID_STA|=0X40;if((RFID_CNT>2*(Sample/Sample_Per))||(RFID_CNT<(Sample/Sample_Per)/2)){RFID_STA=0;RFID_CNT=0;}}
RFID_STA&=0XDF;
RFID_CNT=0;
}else{
RFID_STA|=0X40;
RFID_CNT=0;
}
}else{
TIM_OC2PolarityConfig(TIM2, TIM_ICPolarity_Rising);
if(RFID_STA&0X40){
if((RFID_CNT>(Sample/Sample_Per))&&(RFID_CNT<2*(Sample/Sample_Per))){RFID_STA|=0X80;}
else{RFID_STA|=0X20;if((RFID_CNT>2*(Sample/Sample_Per))||(RFID_CNT<(Sample/Sample_Per)/2)){RFID_STA=0;RFID_CNT=0;}}
RFID_STA&=0XBF;
RFID_CNT=0;
}else{
RFID_STA|=0X20;
RFID_CNT=0;
}
}
}else{
if((RFID_STA&0X10)==0){
if(GPIO_ReadInputDataBit(RFID_OUT, RFID_PIN_OUT)==Bit_SET){
TIM_OC2PolarityConfig(TIM2, TIM_ICPolarity_Falling);
if((RFID_CNT>2*(Sample/Sample_Per))||(RFID_CNT<(Sample/Sample_Per)/2)){RFID_STA=0;RFID_CNT=0;}
if((RFID_CNT>(Sample/Sample_Per))&&(RFID_CNT<2*(Sample/Sample_Per))){RFID_DATA=RFID_DATA<<1;RFID_CNT=0;}
}else{
TIM_OC2PolarityConfig(TIM2, TIM_ICPolarity_Rising);
if((RFID_CNT>2*(Sample/Sample_Per))||(RFID_CNT<(Sample/Sample_Per)/2)){RFID_STA=0;RFID_CNT=0;}
if((RFID_CNT>(Sample/Sample_Per))&&(RFID_CNT<2*(Sample/Sample_Per))){RFID_DATA=RFID_DATA<<1;RFID_DATA|=0x01;RFID_CNT=0;}
}
if(((RFID_DATA&0XFF80000000000001)==0XFF80000000000000)){RFID_STA|=0X10;}
}else{
if(GPIO_ReadInputDataBit(RFID_OUT, RFID_PIN_OUT)==Bit_SET){
TIM_OC2PolarityConfig(TIM2, TIM_ICPolarity_Falling);
RFID_CNT=0;
}else{
TIM_OC2PolarityConfig(TIM2, TIM_ICPolarity_Rising);
RFID_CNT=0;
}
}
}
}
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
}
void TIM3_IRQHandler(void)
void TIM3_IRQHandler(void){
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET){
if(RFID_CNT==0XFF){RFID_CNT=0;}
if(TIME_CNT==0XFFFF){TIME_CNT=0;}
RFID_CNT+=1;
TIME_CNT+=1;
}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
数据切片
采用unsigned char 类型的数组ID[11] ,通过移位操作进行获取:
u8 i=0;
u8 ID[11]={0};
u8 RFID_ID[10]={0};
if(RFID_STA&0X10){
for(i=0;i<11;i++)
{
ID[i]=((RFID_DATA>>(50-5*i))&0x1f);
}
}
行校验以及列检验
u8 RFID_check(void){
u8 i=0,j=0;
u8 sum=0;
for(i=0;i<10;i++){
for(j=0;j<5;j++){
sum^=(ID[i]>>(4-j))&0x01;
}
if(sum!=0)return 0;
}
for(i=0;i<11;i++){
sum^=ID[i];
}
if(sum>>1!=0)return 0;
return 1;
}
附加功能:(把每一位换算成ASCII码值)
void RFID_process(void)
{
u8 i;
for(i=0;i<10;i++){
switch(ID[i]>>1){
case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8: case 9:RFID_ID[i]=(ID[i]>>1)+48;break;
case 10:case 11:case 12:case 13:case 14:case 15:RFID_ID[i]=(ID[i]>>1)-10+65;break;
default:RFID_ID[i]=32;
}
}
}
|