?? 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 + -