我是靠谱客的博主 忧心唇膏,最近开发中收集的这篇文章主要介绍STM32解码EM4100的曼彻斯特编码(库函数版本)前言:EM4100简介:EM4100数据帧格式曼彻斯特编码:STM32F103RBT6解码EM4100:行校验以及列检验思路:代码片段:,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言:

前些日子老师布置一个任务叫我们焊接一个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数据帧格式

EM4100数据帧模式

要点:

  • 数据总共有64bit。
  • 以连续的9个1开头。
  • 前4个bit为厂商位。
  • 采用偶校验的方法。(保证1的个数为偶数个)
  • 最后一列为行校验。
  • 最后一行为列检验。
  • 数据最后一位为0。

曼彻斯特编码:

两种格式刚好相反:

  • 第一种:(EM4100采用这种编码)
    1:高电平到低电平(下降)
    0:低电平到高电平(上升)
  • 第二种:
    1:低电平到高电平(上升)
    0:高电平到低电平(下降)

下图为一次完整的EM4100帧数据
图为完整的EM4100数据帧格式

STM32F103RBT6解码EM4100:

思路:

  1. 首先找到高电平时间或者低电平时间在512us附近。
  2. 找到后标记已经同步,并且此时为一次有效捕获中断。
  3. 下一次上升沿或者下降沿必须距离上一次有效捕获中断512us附近。
  4. 选用uint64_tRFID_DATA来存放每一次有效数据。
  5. 采集完一次有效捕获中断后检查RFID_DATA是否以连续的9个1开头并且最后一位为0。
  6. 如果满足条件则标记采集完成。否则继续采集。

采用的外设: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);//定时器3初始化
	
	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;//RFID状态
u16 TIME_CNT=0;
const u16 Sample=384;//(256+512)/2
const u8 Sample_Per=32;//定时器3溢出一次 32us
/*
RFID_STA    没有用到后4位
bit7是否同步 bit6是否捕捉上升沿 bit5是否捕捉下降沿  bit4解析成功
*/
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;}//上升沿代表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;}//下降沿代表1
						}
						if(((RFID_DATA&0XFF80000000000001)==0XFF80000000000000)){RFID_STA|=0X10;}//RFID_DATA以9个连续的1开头,以0结尾标记捕捉完成
					}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};//换算成ASCII码的RFID_ID值
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;//换算成ASCII码的1 2 3 4 5 6 7 8 9
			case 10:case 11:case 12:case 13:case 14:case 15:RFID_ID[i]=(ID[i]>>1)-10+65;break;//换算成ASCII码的A B C D E F
			default:RFID_ID[i]=32;//转换成ASCII码的空格
		}
	}
}

下面附上51单片机C语言发送EM4100曼彻斯特信号代码:

#include <regx51.h>
sbit TAG_OUT=P2^0;
typedef unsigned char uint8_t;
void DELAY256(void)
{
    unsigned char a,b;
    for(b=23;b>0;b--)
        for(a=4;a>0;a--);
}
uint8_t EVEN_Generate(uint8_t d)
 {
  	uint8_t ans=0;
     uint8_t i=0;
     for(i=0;i<4;i++){
      	ans^=d>>i&0X01;
      }
 	   d=d<<1|ans;
     return  d;
 }
void TAG_BIT_1(void)
{
   TAG_OUT=1;
   DELAY256();
   TAG_OUT=0;
   DELAY256();
}
void TAG_BIT_0(void)
{
   TAG_OUT=0;
   DELAY256();
   TAG_OUT=1;
   DELAY256();
}
void TAG_Send_Bit(uint8_t b)
{
	if(b){
  	TAG_BIT_1();
  }else{
   	TAG_BIT_0();
   }
}
void TAG_Send_5_Bits(uint8_t d)//高位先发
{
 	uint8_t i=0;
   for(i=0;i<5;i++){
   	TAG_Send_Bit(d>>(4-i)&0X01);
   } 
 }
 void TAG_Send_4_Bits(uint8_t d)//高位先发
{
 	uint8_t i=0;
   for(i=0;i<4;i++){
   	TAG_Send_Bit(d>>(3-i)&0X01);
   } 
 }

void TAG_Send_Begin(void)
{
 	uint8_t i=0;
  	for(i=0;i<9;i++){
    	TAG_Send_Bit(1);
    }
 }
 void TAG_Send_End(void)
 {
  	TAG_Send_Bit(0);
  
  }
 void TAG_Send_ID(uint8_t id[])
{
 	uint8_t i=0;
 	TAG_Send_Begin();
    for(i=0;i<10;i++){
  		TAG_Send_5_Bits(id[i]);     
    }
 	TAG_Send_4_Bits(id[i]);    
    TAG_Send_End();
 } 
 void ID_Process(uint8_t id[])
{
	uint8_t i=0;
	id[10]=0;
    for(i=0;i<10;i++){
    	id[10]=id[10]^id[i];
    }
    for(i=0;i<10;i++){
     	id[i]=EVEN_Generate(id[i]);
    } 
 }
void main(void)
{
 	uint8_t LGA[11]={5,7,2,0,1,9,2,7,2,1};
	ID_Process(LGA);
 	while(1){
 	  TAG_Send_ID(LGA);
    }
 }

最后

以上就是忧心唇膏为你收集整理的STM32解码EM4100的曼彻斯特编码(库函数版本)前言:EM4100简介:EM4100数据帧格式曼彻斯特编码:STM32F103RBT6解码EM4100:行校验以及列检验思路:代码片段:的全部内容,希望文章能够帮你解决STM32解码EM4100的曼彻斯特编码(库函数版本)前言:EM4100简介:EM4100数据帧格式曼彻斯特编码:STM32F103RBT6解码EM4100:行校验以及列检验思路:代码片段:所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部