📄 read_card.h
字号:
/******************************************************************************************************************
程序名: 射频卡门禁系统_读卡头
功能概述:
读射频卡头文件 适用于AVR 7.3728MHZ
射频卡类型: 4001、EM4100和含E2PROM的RF卡。如E5550。
MCU类型: ATmega16
晶振频率: 7.3728MHZ
版本: V0.1
修改: 于军峰
原作者: 章其波先生
编译日期: 2007-05-01
******************************************************************************************************************/
#ifndef _read_card_H
#define _read_card_H
#define DELAY_VALUE 425 //在7.3728MHZ下425----384us
#define TIME_OF 380 //超时退出
#define Manchester_IN (PIND&(1<<PD2)) //曼彻斯特码输入端
uchar rev_dat[5]={0,0,0,0,0}; //接收的5个字节数据
ulong lcd_dis_num=0;
//*****************************************************************************************************************
void delay_384us(void); //适用机型 :用于AVR系列单片机延时处理,7.3728MHZ晶振下
void send_initial(void);
uchar read_card_number(void); //尝试读十次卡,无卡则返回0,有卡则返回卡号
void delay_384us(void) //适用机型 :用于AVR系列单片机延时处理,7.3728MHZ晶振下
{
uint n=DELAY_VALUE;
for(;n>0;n--)
{
asm("nop");
asm("nop");
}
}
uchar read_card_number(void)
{
uchar i=0; //起始为的计数值
uchar error_flag=0; //时间溢出标志
uchar row=0,col=0; //行列寄存器
uchar row_parity=0; //行校验寄存器
uchar col_parity[5]; //列校验寄存器
uchar card_data=0; //数据寄存器
uchar temp=0; //卡号寄存器
uchar seek_num=0; //搜索次数寄存器
uint error=0; //时间溢出的计数值
uchar pp=0;
uchar ii=0;
while(1)
{
if(seek_num>=10) //尝试10次搜索,如没有则返回0
{
return 0;
}
else
{
seek_num++;
WDR(); //喂狗
}
error=0;
ii=pp=0;
while(Manchester_IN); //等待高电平结束,主要是判断曼码结束位0
while(Manchester_IN==0) //等低电平,判断如果后面有连续9个1,表示可以接收数据
{
if(error==TIME_OF)
{
error=0;
break; //超时退出
}
else
{
error++;
}
}
delay_384us(); //延时384us
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++;
}
}
delay_384us(); //延时384us
if(Manchester_IN&&error_flag==0) //判断下一位是否为1 和是否没有时间溢出
{
;
}
else
{
break; //不是1退出,溢出退出
}
}
if(error_flag) //因时间溢出造成的本次主循环退出
{
error_flag=0;
ii=pp=0;
continue; //退出本次循环
}
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;
ii=pp=0;
continue; //因等待待第一个正式数据错误引起的本次主循环退出
}
col_parity[0]=col_parity[1]=col_parity[2]=col_parity[3]=col_parity[4]=0; //所有列校验清零
WDR(); //喂狗
for(row=0;row<11;row++) //共11行数据
{
for(col=0,row_parity=0;col<5;col++) //共5列数据
{
delay_384us(); //延时384us
if(Manchester_IN)
{
card_data=1; //数据为1
}
else
{
card_data=0; //数据为0
}
if(col<4&&row<10) //数据区的接受,后四个字节
{
temp<<=1; //左移一位
temp+=card_data; //数据相加
lcd_dis_num<<=1;
lcd_dis_num+=card_data;
ii++;
if(ii>=8)
{
ii=0;
rev_dat[pp++]=temp;
temp=0;
}
}
row_parity+=card_data; //行校验加入数据
col_parity[col]+=card_data; //相应列校验加入数据 虽最后一列没有校验但为了方便也加上
error=0; //限定等待时间清零
while(Manchester_IN==card_data)
{
if(error==TIME_OF) //由于时间溢出造成的数据出错
{
error_flag=1;
break; //退出本while循环
}
else error++;
}
if(error_flag)
{
break; //出错退出内层for循环
}
}
if(row<10) //最后一行没有校验所以要加限制
{
if((row_parity&0x01)||error_flag) //出错退出外for循环
{
temp=0;
error_flag=1;
break; //退出
}
}
}
//对最后接收的列校验进行判断,及对来自上面数据错误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;
ii=pp=0;
continue; //退出本次循环
}
else
{
ii=pp=0;
return 0xaa; //将正确的数据返回
}
}
ii=pp=0;
continue;
}
ii=pp=0;
continue;
}
return 0;
}
#endif
//**************************************************Program End****************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -