⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 em4100.c

📁 一个完整的读卡的C语言程序
💻 C
字号:

/*                 检测方法
1).确定起始位,首先要正确找到数据1 按规则下跳为1 上跳为0. 可检测高电平并等其变低
	但这会把0错检为1因为0也存在高电平。但是如果检测到一个周期的高电平(数据01)则可
	确定找到了数据1,找到1后就可以同步了,因为EM4100卡最后一位数据就是0正好可以利用
	作为判断的特征。

2).对于数据的确定,由于有了同步则可在同步后延时384us即3/4个码原周期在判断接受段电平如何
	如为高则置数据为1,并一直等到低电平的出现,相反则等高电平的出现,并在此之间插入超时
	判断。这样,一个完整的数据判断就完成了,并确保数据的准确性,另外这种方法的抗干扰性
	会非常好,而如果采用定时同步的话则会因信号的畸变而引起数据出错,整体会导致读卡几率降低
	但是此程序也有其缺点,因为采用纯延时判断的手段,因此其占用单片机的运行时间比较大。

3).同步后开始接受同步数据即9个1,这一部分用一个循环做,如果出错则放弃接收

4).同步数据接收完后,则开始接受数据,数据分11行5列接收以利于校验位的判断
	如有出错则放弃数据

5).如一切正常则返回卡号,如因尝试读卡次数到了则返回0以表示没有卡

*/

#include"EM4100.h"


//精确的384us延时,此延时可以不严格,但要大于256us小于512us
void Delay384us()
{
	uchar i=DELAY_VAL;
	while(i--);
}


//读取卡号,
ulong Read_Card()
{
	uchar i=0;	//起始为的计数值
	uchar error;  //时间溢出的计数值
	uchar error_flag; //时间溢出标志
	uchar row,col;	  //行列寄存器
	uchar row_parity;  //行校验寄存器
	uchar col_parity[5]; //列校验寄存器
	uchar _data;		//数据寄存器
	ulong temp;			//卡号寄存器
	ulong timeout=0;	 //搜索次数寄存器
 
	while(1)
	{		
		if(timeout==10)return 0;//尝试10次搜索,如没有责返回0
		else timeout++;
		error=0;
       // Manchester_IN=0;
		while(Manchester_IN==0)//等高电平
		{
			if(error==TIME_OF)break;//超时退出
			else error++;
		} 	
		if(error==150)continue;//结束本次主循环
		else error=0;	
		Delay384us();	  
		if(Manchester_IN)//寻找真正的1起始位,利用01的波形确定1起始位,即最后一位加第一位
		{	 
			for(i=0;i<8;i++)//判断是否是真的起始位
			{	  
				error=0;	   //限定等待时间
				while(Manchester_IN)
				{	
					if(error==TIME_OF)
					{	  
						error_flag=1;//时间溢出
						break;	//退出
					}
					else error++;
				}	 
				Delay384us();				   //延时至下一码原
				if(Manchester_IN&&error_flag==0); //判断下一位是否为1 和是否没有时间溢出
				else break;			 //不是1退出,溢出退出			   
			}
			if(error_flag)//因时间溢出造成的本次主循环退出
			{	  
				error_flag=0;
				continue;	//退出本次循环
			}
			else;
			if(i==8)  //起始位接受完并且正确后开始接受数据
			{	
				error_flag=0;
				error=0;	 //限定等待时间
				while(Manchester_IN)
				{  
					if(error==TIME_OF)
					{	
						error_flag=0;
						break;		 //时间溢出造成的出错
					}
					else error++;
				}	  
				if(error_flag)	   
				{
					error_flag=0;
					continue;	   //因等待待第一个正式数据错误引起的本次主循环退出
				}
				else; 
				//所有列校验清零
				col_parity[0]=col_parity[1]=col_parity[2]=col_parity[3]=col_parity[4]=0;
				for(row=0;row<11;row++)	//共11行数据
				{
					for(col=0,row_parity=0/*行校验清零*/;col<5;col++)//共5列数据
					{
						Delay384us();  //延时至下一码原
						if(Manchester_IN)_data=1;  //数据为1
						else _data=0;			   //数据为0
						if(col<4&&row<10)		   //数据区的接受,后四个字节
						{
							temp<<=1;			 //左移一位
							temp+=(ulong)_data;	 //数据相加
						}
						else;
						row_parity+=_data;		 //行校验加入数据
						col_parity[col]+=_data;	 //相应列校验加入数据  虽最后一列没有校验但为了方便也加上
						error=0;				 //限定等待时间清零
						while(Manchester_IN==(bit)_data)
						{
							if(error==TIME_OF)		  //由于时间溢出造成的数据出错
							{	
								error_flag=1;
								break;			  //退出本while循环
							}
							else error++;
						}
						if(error_flag)break;	 //出错退出内层for循环
						else;
					}
					if(row<10)//最后一行没有校验所以要加限制
					{
						if((row_parity&0x01)||error_flag) //出错退出外for循环
						{
							temp=0;
							error_flag=1; 
							break;			 //退出
						}
						else;
					}
					else; 	 
				}

				//对最后接收的列校验进行判断,及对来自上面数据错误error_flag处理以结束本次主循环
				if(error_flag||((col_parity[0]&0x01)&&(col_parity[1]&0x01)&&(col_parity[2]&0x01)&&(col_parity[3]&0x01)))
				{	//最后一列没有校验												 
					error_flag=0;
					temp=0;
					continue; //退出本次循环
				} 
				else return temp;//将正确的数据返回
			}
			continue;
		}
		continue;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -